hap-cli 0.8.5__tar.gz → 0.8.7__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 (216) hide show
  1. {hap_cli-0.8.5 → hap_cli-0.8.7}/PKG-INFO +19 -9
  2. {hap_cli-0.8.5/hap_cli → hap_cli-0.8.7}/README.md +18 -8
  3. {hap_cli-0.8.5 → hap_cli-0.8.7/hap_cli}/README.md +18 -8
  4. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/README_CN.md +10 -6
  5. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/__init__.py +1 -1
  6. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/auth_cmd.py +55 -36
  7. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/icon_cmd.py +50 -5
  8. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/instance_cmd.py +3 -1
  9. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/node_cmd.py +30 -9
  10. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/record_cmd.py +6 -1
  11. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/workflow_cmd.py +9 -2
  12. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/worksheet_cmd.py +19 -2
  13. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/action_spec_adapter.py +17 -6
  14. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/auth.py +129 -198
  15. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/chat.py +28 -2
  16. hap_cli-0.8.7/hap_cli/core/cli_access.py +344 -0
  17. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/apply.py +12 -1
  18. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/flow_node.py +103 -0
  19. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/icon_index.py +19 -0
  20. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/record.py +130 -33
  21. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/session.py +42 -22
  22. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/update.py +3 -9
  23. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/upload.py +9 -5
  24. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/view_spec_adapter.py +61 -4
  25. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/workflow.py +43 -15
  26. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/workflow_node_dsl.py +124 -8
  27. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/worksheet.py +174 -14
  28. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/locale/messages.json +6 -3
  29. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/conftest.py +22 -0
  30. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_app_editor.py +20 -0
  31. hap_cli-0.8.7/hap_cli/tests/test_auth_prerelease.py +154 -0
  32. hap_cli-0.8.7/hap_cli/tests/test_cli_access.py +663 -0
  33. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_core.py +851 -10
  34. hap_cli-0.8.7/hap_cli/tests/test_instance_history_cli.py +34 -0
  35. hap_cli-0.8.7/hap_cli/tests/test_record_field_alias.py +146 -0
  36. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_update.py +4 -3
  37. hap_cli-0.8.7/hap_cli/tests/test_workflow_list_cli.py +73 -0
  38. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_worksheet_v3_semantic_cli.py +10 -4
  39. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli.egg-info/PKG-INFO +19 -9
  40. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli.egg-info/SOURCES.txt +5 -0
  41. hap_cli-0.8.5/hap_cli/tests/test_auth_prerelease.py +0 -410
  42. {hap_cli-0.8.5 → hap_cli-0.8.7}/MANIFEST.in +0 -0
  43. {hap_cli-0.8.5 → hap_cli-0.8.7}/app_live_tests/__init__.py +0 -0
  44. {hap_cli-0.8.5 → hap_cli-0.8.7}/app_live_tests/__main__.py +0 -0
  45. {hap_cli-0.8.5 → hap_cli-0.8.7}/app_live_tests/config.py +0 -0
  46. {hap_cli-0.8.5 → hap_cli-0.8.7}/app_live_tests/harness.py +0 -0
  47. {hap_cli-0.8.5 → hap_cli-0.8.7}/app_live_tests/smoke.py +0 -0
  48. {hap_cli-0.8.5 → hap_cli-0.8.7}/app_live_tests/state.py +0 -0
  49. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/__main__.py +0 -0
  50. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/__init__.py +0 -0
  51. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/app_cmd.py +0 -0
  52. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/app_editor_cmd.py +0 -0
  53. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/calendar_cmd.py +0 -0
  54. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/chart_cmd.py +0 -0
  55. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/chat_cmd.py +0 -0
  56. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/chatbot_cmd.py +0 -0
  57. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/config_cmd.py +0 -0
  58. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/contact_cmd.py +0 -0
  59. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/department_cmd.py +0 -0
  60. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/group_cmd.py +0 -0
  61. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/optionset_cmd.py +0 -0
  62. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/page_cmd.py +0 -0
  63. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/post_cmd.py +0 -0
  64. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/region_cmd.py +0 -0
  65. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/role_cmd.py +0 -0
  66. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/update_cmd.py +0 -0
  67. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/upload_cmd.py +0 -0
  68. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/commands/v3_registry.py +0 -0
  69. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/context.py +0 -0
  70. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/__init__.py +0 -0
  71. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/app.py +0 -0
  72. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/calendar_mod.py +0 -0
  73. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/chart.py +0 -0
  74. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/chatbot.py +0 -0
  75. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/contact.py +0 -0
  76. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/control_type_codes.py +0 -0
  77. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/department.py +0 -0
  78. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/__init__.py +0 -0
  79. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/_hapmeta/__init__.py +0 -0
  80. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/_hapmeta/control_type_codes.py +0 -0
  81. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/componentlower.py +0 -0
  82. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/editspec.py +0 -0
  83. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/errors.py +0 -0
  84. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/fieldlower.py +0 -0
  85. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/jsonschema_mini.py +0 -0
  86. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/models.py +0 -0
  87. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/ops.py +0 -0
  88. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/planner.py +0 -0
  89. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/editor/reader.py +0 -0
  90. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/field_normalizer.py +0 -0
  91. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/field_spec_adapter.py +0 -0
  92. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/filter_translator.py +0 -0
  93. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/global_meta.py +0 -0
  94. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/group.py +0 -0
  95. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/instance.py +0 -0
  96. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/logger.py +0 -0
  97. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/optionset.py +0 -0
  98. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/page.py +0 -0
  99. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/post.py +0 -0
  100. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/response_crypto.py +0 -0
  101. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/role.py +0 -0
  102. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/role_perm_builder.py +0 -0
  103. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/token_crypto.py +0 -0
  104. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/v3/__init__.py +0 -0
  105. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/v3/dispatcher.py +0 -0
  106. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/v3/render.py +0 -0
  107. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/v3/schema.py +0 -0
  108. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/core/worksheet_templates.py +0 -0
  109. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/hap_cli.py +0 -0
  110. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/i18n.py +0 -0
  111. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/locale/__init__.py +0 -0
  112. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/locale/messages.schema.json +0 -0
  113. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/__init__.py +0 -0
  114. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_app_export_usage.py +0 -0
  115. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_bug_036430.py +0 -0
  116. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_chart.py +0 -0
  117. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_config_cmd.py +0 -0
  118. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_destructive_confirm_cli.py +0 -0
  119. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_full_e2e.py +0 -0
  120. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_global_meta.py +0 -0
  121. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_i18n.py +0 -0
  122. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_integration.py +0 -0
  123. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_integration_approval.py +0 -0
  124. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_integration_approval_actions.py +0 -0
  125. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_integration_calendar.py +0 -0
  126. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_integration_destructive.py +0 -0
  127. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_integration_misc.py +0 -0
  128. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_integration_post.py +0 -0
  129. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_integration_social.py +0 -0
  130. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_integration_v3.py +0 -0
  131. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_integration_workflow.py +0 -0
  132. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_integration_worksheet_extra.py +0 -0
  133. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_multi_profile.py +0 -0
  134. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_org_approval_v3_semantic_cli.py +0 -0
  135. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_org_id_cli.py +0 -0
  136. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_org_id_docs.py +0 -0
  137. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_parameter_conventions.py +0 -0
  138. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_parameter_mapping_registry.py +0 -0
  139. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_record_batch_v3_semantic_cli.py +0 -0
  140. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_record_v3_semantic_cli.py +0 -0
  141. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_semantic_types_registry.py +0 -0
  142. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_v3_api_schema_loader.py +0 -0
  143. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_v3_dispatcher.py +0 -0
  144. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_v3_registry_coverage.py +0 -0
  145. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_v3_session.py +0 -0
  146. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_v3_yaml_translation.py +0 -0
  147. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_workflow_v3_semantic_cli.py +0 -0
  148. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/tests/test_worksheet_crud_cli.py +0 -0
  149. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/utils/__init__.py +0 -0
  150. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/utils/formatting.py +0 -0
  151. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/utils/options.py +0 -0
  152. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli/utils/parameter_mapping.py +0 -0
  153. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli.egg-info/dependency_links.txt +0 -0
  154. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli.egg-info/entry_points.txt +0 -0
  155. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli.egg-info/requires.txt +0 -0
  156. {hap_cli-0.8.5 → hap_cli-0.8.7}/hap_cli.egg-info/top_level.txt +0 -0
  157. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/__init__.py +0 -0
  158. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/__main__.py +0 -0
  159. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/_wftest.py +0 -0
  160. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/charts.py +0 -0
  161. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/cleanup.py +0 -0
  162. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/compiler.py +0 -0
  163. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/config.py +0 -0
  164. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/errors.py +0 -0
  165. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/executor.py +0 -0
  166. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/fields.py +0 -0
  167. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/hap.py +0 -0
  168. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/recording/__init__.py +0 -0
  169. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/recording/console.py +0 -0
  170. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/recording/jsonl.py +0 -0
  171. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/recording/mirror.py +0 -0
  172. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/recording/report.py +0 -0
  173. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/schema.py +0 -0
  174. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/seed/__init__.py +0 -0
  175. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/seed/cli.py +0 -0
  176. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/seed/executor.py +0 -0
  177. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/seed/template.py +0 -0
  178. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/selftest.py +0 -0
  179. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/smoke.py +0 -0
  180. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/step.py +0 -0
  181. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/steps.py +0 -0
  182. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/store.py +0 -0
  183. {hap_cli-0.8.5 → hap_cli-0.8.7}/live_tests/workflow_dsl.py +0 -0
  184. {hap_cli-0.8.5 → hap_cli-0.8.7}/setup.cfg +0 -0
  185. {hap_cli-0.8.5 → hap_cli-0.8.7}/setup.py +0 -0
  186. {hap_cli-0.8.5 → hap_cli-0.8.7}/skills/hap-cli-app-editor/scripts/editspec/component.schema.json +0 -0
  187. {hap_cli-0.8.5 → hap_cli-0.8.7}/skills/hap-cli-app-editor/scripts/editspec/custom-action.schema.json +0 -0
  188. {hap_cli-0.8.5 → hap_cli-0.8.7}/skills/hap-cli-app-editor/scripts/editspec/envelope.schema.json +0 -0
  189. {hap_cli-0.8.5 → hap_cli-0.8.7}/skills/hap-cli-app-editor/scripts/editspec/field.schema.json +0 -0
  190. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/INDEX.json +0 -0
  191. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/add_member_to_role.yaml +0 -0
  192. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/batch_delete_records.yaml +0 -0
  193. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/create_optionset.yaml +0 -0
  194. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/create_role.yaml +0 -0
  195. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/delete_optionset.yaml +0 -0
  196. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/delete_record.yaml +0 -0
  197. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/delete_role.yaml +0 -0
  198. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/delete_worksheet.yaml +0 -0
  199. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_app_info.yaml +0 -0
  200. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_app_knowledge_list.yaml +0 -0
  201. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_app_worksheets_list.yaml +0 -0
  202. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_optionset_list.yaml +0 -0
  203. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_record_details.yaml +0 -0
  204. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_record_discussions.yaml +0 -0
  205. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_record_list.yaml +0 -0
  206. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_record_logs.yaml +0 -0
  207. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_record_pivot_data.yaml +0 -0
  208. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_record_relations.yaml +0 -0
  209. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_record_share_link.yaml +0 -0
  210. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_regions.yaml +0 -0
  211. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_role_details.yaml +0 -0
  212. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/get_role_list.yaml +0 -0
  213. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/knowledge_search.yaml +0 -0
  214. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/leave_all_roles.yaml +0 -0
  215. {hap_cli-0.8.5 → hap_cli-0.8.7}/sources/v3-api-schema/remove_member_from_role.yaml +0 -0
  216. {hap_cli-0.8.5 → hap_cli-0.8.7}/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.5
3
+ Version: 0.8.7
4
4
  Summary: CLI harness for MingDAO HAP - Enterprise no-code platform
5
5
  Author: hap-cli
6
6
  License: Apache-2.0
@@ -40,6 +40,15 @@ pip install hap-cli
40
40
  The package ships with the v3 tool schemas it needs, so no extra setup is
41
41
  required after `pip install`.
42
42
 
43
+ ## Prerequisite: enable CLI access for your organization
44
+
45
+ **`hap` can only access an organization's data after the organization has
46
+ enabled CLI access.** Ask an organization administrator to turn on the
47
+ switch under Organization Admin → Security → Data & Access → CLI access
48
+ policy. Commands are blocked until it is enabled; once an administrator
49
+ turns it on, just re-run the command. Use `hap auth list-my-orgs` to see
50
+ each organization's status (`CLI:on/off`).
51
+
43
52
  ## Quick start
44
53
 
45
54
  ### 1. Login
@@ -102,8 +111,9 @@ hap app select APP_ID
102
111
  hap app unselect # clear it
103
112
  ```
104
113
 
105
- `hap auth set-current-org` only changes the default organization. The default app
106
- is managed independently with `hap app select` / `hap app unselect`.
114
+ `hap auth set-current-org` switches the default organization; moving to a
115
+ different organization also clears the default app (apps belong to an
116
+ organization). Pick a new one with `hap app select`.
107
117
 
108
118
  ### 3. Explore worksheets and records
109
119
 
@@ -140,8 +150,8 @@ discover every subcommand.
140
150
  | `auth use NAME` | Switch the environment/account used next |
141
151
  | `auth logout` | Log out the current account (`-p NAME` for a specific one, `-a/--all` for every one) |
142
152
  | `auth whoami` | Show current user, current environment/account, and current organization |
143
- | `auth list-my-orgs` | List every org for the current account (current marked `*`) |
144
- | `auth set-current-org ORG_ID` | Switch the saved current organization |
153
+ | `auth list-my-orgs` | List every org for the current account (current marked `*`; each row shows whether the org allows CLI access, `CLI:on/off`, checked live; omitted where the environment has no such switch) |
154
+ | `auth set-current-org ORG_ID` | Switch the saved current organization (clears the default app when the org changes) |
145
155
 
146
156
  ### app — application management
147
157
 
@@ -285,8 +295,8 @@ discover every subcommand.
285
295
 
286
296
  | Command | Description |
287
297
  |---|---|
288
- | `icon search` | Search icons by Chinese/English keyword (OR across terms, more matches rank higher); no keyword lists all |
289
- | `icon list` | List every icon with its keywords |
298
+ | `icon search` | Search icons by Chinese/English keyword (OR across terms, more matches rank higher); fewer than 10 matches get random suggestions appended; no keyword lists all |
299
+ | `icon list [-n SIZE] [-p PAGE]` | List icons page by page with keywords (50 per page by default) |
290
300
 
291
301
  ### upload — file upload
292
302
 
@@ -330,8 +340,8 @@ Every command that needs an `--app-id` resolves it in this order:
330
340
  2. The default app saved by `hap app select`;
331
341
  3. Otherwise the command exits with an error suggesting `hap app select APP_ID`.
332
342
 
333
- `hap auth set-current-org` changes the default *organization* only it does not
334
- touch the default app.
343
+ `hap auth set-current-org` switches the default *organization*; switching to a
344
+ different organization also clears the default app.
335
345
 
336
346
  ## REPL mode
337
347
 
@@ -11,6 +11,15 @@ pip install hap-cli
11
11
  The package ships with the v3 tool schemas it needs, so no extra setup is
12
12
  required after `pip install`.
13
13
 
14
+ ## Prerequisite: enable CLI access for your organization
15
+
16
+ **`hap` can only access an organization's data after the organization has
17
+ enabled CLI access.** Ask an organization administrator to turn on the
18
+ switch under Organization Admin → Security → Data & Access → CLI access
19
+ policy. Commands are blocked until it is enabled; once an administrator
20
+ turns it on, just re-run the command. Use `hap auth list-my-orgs` to see
21
+ each organization's status (`CLI:on/off`).
22
+
14
23
  ## Quick start
15
24
 
16
25
  ### 1. Login
@@ -73,8 +82,9 @@ hap app select APP_ID
73
82
  hap app unselect # clear it
74
83
  ```
75
84
 
76
- `hap auth set-current-org` only changes the default organization. The default app
77
- is managed independently with `hap app select` / `hap app unselect`.
85
+ `hap auth set-current-org` switches the default organization; moving to a
86
+ different organization also clears the default app (apps belong to an
87
+ organization). Pick a new one with `hap app select`.
78
88
 
79
89
  ### 3. Explore worksheets and records
80
90
 
@@ -111,8 +121,8 @@ discover every subcommand.
111
121
  | `auth use NAME` | Switch the environment/account used next |
112
122
  | `auth logout` | Log out the current account (`-p NAME` for a specific one, `-a/--all` for every one) |
113
123
  | `auth whoami` | Show current user, current environment/account, and current organization |
114
- | `auth list-my-orgs` | List every org for the current account (current marked `*`) |
115
- | `auth set-current-org ORG_ID` | Switch the saved current organization |
124
+ | `auth list-my-orgs` | List every org for the current account (current marked `*`; each row shows whether the org allows CLI access, `CLI:on/off`, checked live; omitted where the environment has no such switch) |
125
+ | `auth set-current-org ORG_ID` | Switch the saved current organization (clears the default app when the org changes) |
116
126
 
117
127
  ### app — application management
118
128
 
@@ -256,8 +266,8 @@ discover every subcommand.
256
266
 
257
267
  | Command | Description |
258
268
  |---|---|
259
- | `icon search` | Search icons by Chinese/English keyword (OR across terms, more matches rank higher); no keyword lists all |
260
- | `icon list` | List every icon with its keywords |
269
+ | `icon search` | Search icons by Chinese/English keyword (OR across terms, more matches rank higher); fewer than 10 matches get random suggestions appended; no keyword lists all |
270
+ | `icon list [-n SIZE] [-p PAGE]` | List icons page by page with keywords (50 per page by default) |
261
271
 
262
272
  ### upload — file upload
263
273
 
@@ -301,8 +311,8 @@ Every command that needs an `--app-id` resolves it in this order:
301
311
  2. The default app saved by `hap app select`;
302
312
  3. Otherwise the command exits with an error suggesting `hap app select APP_ID`.
303
313
 
304
- `hap auth set-current-org` changes the default *organization* only it does not
305
- touch the default app.
314
+ `hap auth set-current-org` switches the default *organization*; switching to a
315
+ different organization also clears the default app.
306
316
 
307
317
  ## REPL mode
308
318
 
@@ -11,6 +11,15 @@ pip install hap-cli
11
11
  The package ships with the v3 tool schemas it needs, so no extra setup is
12
12
  required after `pip install`.
13
13
 
14
+ ## Prerequisite: enable CLI access for your organization
15
+
16
+ **`hap` can only access an organization's data after the organization has
17
+ enabled CLI access.** Ask an organization administrator to turn on the
18
+ switch under Organization Admin → Security → Data & Access → CLI access
19
+ policy. Commands are blocked until it is enabled; once an administrator
20
+ turns it on, just re-run the command. Use `hap auth list-my-orgs` to see
21
+ each organization's status (`CLI:on/off`).
22
+
14
23
  ## Quick start
15
24
 
16
25
  ### 1. Login
@@ -73,8 +82,9 @@ hap app select APP_ID
73
82
  hap app unselect # clear it
74
83
  ```
75
84
 
76
- `hap auth set-current-org` only changes the default organization. The default app
77
- is managed independently with `hap app select` / `hap app unselect`.
85
+ `hap auth set-current-org` switches the default organization; moving to a
86
+ different organization also clears the default app (apps belong to an
87
+ organization). Pick a new one with `hap app select`.
78
88
 
79
89
  ### 3. Explore worksheets and records
80
90
 
@@ -111,8 +121,8 @@ discover every subcommand.
111
121
  | `auth use NAME` | Switch the environment/account used next |
112
122
  | `auth logout` | Log out the current account (`-p NAME` for a specific one, `-a/--all` for every one) |
113
123
  | `auth whoami` | Show current user, current environment/account, and current organization |
114
- | `auth list-my-orgs` | List every org for the current account (current marked `*`) |
115
- | `auth set-current-org ORG_ID` | Switch the saved current organization |
124
+ | `auth list-my-orgs` | List every org for the current account (current marked `*`; each row shows whether the org allows CLI access, `CLI:on/off`, checked live; omitted where the environment has no such switch) |
125
+ | `auth set-current-org ORG_ID` | Switch the saved current organization (clears the default app when the org changes) |
116
126
 
117
127
  ### app — application management
118
128
 
@@ -256,8 +266,8 @@ discover every subcommand.
256
266
 
257
267
  | Command | Description |
258
268
  |---|---|
259
- | `icon search` | Search icons by Chinese/English keyword (OR across terms, more matches rank higher); no keyword lists all |
260
- | `icon list` | List every icon with its keywords |
269
+ | `icon search` | Search icons by Chinese/English keyword (OR across terms, more matches rank higher); fewer than 10 matches get random suggestions appended; no keyword lists all |
270
+ | `icon list [-n SIZE] [-p PAGE]` | List icons page by page with keywords (50 per page by default) |
261
271
 
262
272
  ### upload — file upload
263
273
 
@@ -301,8 +311,8 @@ Every command that needs an `--app-id` resolves it in this order:
301
311
  2. The default app saved by `hap app select`;
302
312
  3. Otherwise the command exits with an error suggesting `hap app select APP_ID`.
303
313
 
304
- `hap auth set-current-org` changes the default *organization* only it does not
305
- touch the default app.
314
+ `hap auth set-current-org` switches the default *organization*; switching to a
315
+ different organization also clears the default app.
306
316
 
307
317
  ## REPL mode
308
318
 
@@ -10,6 +10,10 @@ pip install hap-cli
10
10
 
11
11
  安装包内已附带 CLI 启动需要的 v3 工具 schema,`pip install` 之后无需额外配置。
12
12
 
13
+ ## 使用前提:开启组织的 CLI 访问权限
14
+
15
+ **只有组织开启了 CLI 访问权限,`hap` 才能访问该组织的数据。** 请组织管理员前往「组织管理后台 → 安全 → 数据与访问 → CLI 访问策略」开启允许访问开关。未开启时命令会被拦截;管理员开启后直接重跑命令即可。可用 `hap auth list-my-orgs` 查看各组织的开启状态(`CLI:on/off`)。
16
+
13
17
  ## 快速上手
14
18
 
15
19
  ### 1. 登录
@@ -67,7 +71,7 @@ hap app select APP_ID
67
71
  hap app unselect # 清除默认应用
68
72
  ```
69
73
 
70
- `hap auth set-current-org` 只切换默认组织,不会改写默认应用。默认应用通过 `hap app select` / `hap app unselect` 单独管理。
74
+ `hap auth set-current-org` 切换默认组织;切换到不同组织时会同时清除默认应用(应用从属于组织)。之后用 `hap app select` 重新选择默认应用。
71
75
 
72
76
  ### 3. 浏览工作表与记录
73
77
 
@@ -102,8 +106,8 @@ hap --json worksheet record list WORKSHEET_ID
102
106
  | `auth use NAME` | 切换当前使用的环境/账号 |
103
107
  | `auth logout` | 登出当前账号(`-p NAME` 指定,`-a/--all` 全部) |
104
108
  | `auth whoami` | 当前用户、当前环境/账号与当前组织 |
105
- | `auth list-my-orgs` | 当前账号所属组织(当前组织标 `*`) |
106
- | `auth set-current-org ORG_ID` | 切换默认组织 |
109
+ | `auth list-my-orgs` | 当前账号所属组织(当前组织标 `*`,并实时显示各组织是否开启 CLI 访问权限 `CLI:on/off`,环境不支持该开关时不显示) |
110
+ | `auth set-current-org ORG_ID` | 切换默认组织(切到不同组织时会清除默认应用) |
107
111
 
108
112
  ### app — 应用管理
109
113
 
@@ -236,8 +240,8 @@ hap --json worksheet record list WORKSHEET_ID
236
240
 
237
241
  | 命令 | 说明 |
238
242
  |---|---|
239
- | `icon search` | 按中英文关键词搜索图标(多关键词取并集,命中越多排越前);无关键词列出全部 |
240
- | `icon list` | 列出全部图标及其关键词 |
243
+ | `icon search` | 按中英文关键词搜索图标(多关键词取并集,命中越多排越前);命中不足 10 个时随机补足推荐;无关键词列出全部 |
244
+ | `icon list [-n SIZE] [-p PAGE]` | 分页列出图标及其关键词(默认每页 50 个) |
241
245
 
242
246
  ### upload — 文件上传
243
247
 
@@ -277,7 +281,7 @@ hap --json worksheet record list WORKSHEET_ID
277
281
  2. 否则使用 `hap app select APP_ID` 保存的默认应用;
278
282
  3. 仍为空时报错并提示设置默认应用。
279
283
 
280
- `hap auth set-current-org` 切换的是默认**组织**,**不**会改默认应用。
284
+ `hap auth set-current-org` 切换默认**组织**;切到不同组织时会同时清除默认应用。
281
285
 
282
286
  ## REPL 模式
283
287
 
@@ -1,3 +1,3 @@
1
1
  """CLI harness for MingDAO HAP (hap-cli)."""
2
2
 
3
- __version__ = "0.8.5"
3
+ __version__ = "0.8.7"
@@ -54,7 +54,7 @@ def _paste_flow(ctx, server):
54
54
  _api_host, webui = auth_mod.resolve_server(server)
55
55
  if not ctx.json_mode:
56
56
  click.echo(f"Log in at {webui} on a device with a browser,")
57
- click.echo("then copy the md_pss_id token and paste it below.")
57
+ click.echo("then copy the token and paste it below.")
58
58
  token = click.prompt("Paste token").strip()
59
59
  return auth_mod.verify_token(server, token)
60
60
 
@@ -102,6 +102,21 @@ def _save_and_report(ctx, token, webui, user_info, meta, profile_name):
102
102
  session.save(profile=profile_name)
103
103
  set_active_profile(profile_name)
104
104
 
105
+ # Probe the org CLI-access switch for the org we just saved as
106
+ # current, so the user learns right away that commands will be
107
+ # blocked. Only an explicit "off" verdict prints the warning
108
+ # (404 / network trouble stays silent — same fail-open policy as
109
+ # the request gate). Covers all login paths (browser, paste,
110
+ # --token), unlike the browser success page.
111
+ from hap_cli.core import cli_access
112
+
113
+ access_denied = False
114
+ if cli_access.GATE_ENABLED and current_org.get("projectId"):
115
+ access_denied = (
116
+ cli_access.probe_cli_access(webui, token, current_org["projectId"])
117
+ is False
118
+ )
119
+
105
120
  data = {
106
121
  "status": "ok",
107
122
  "profile": profile_name,
@@ -109,17 +124,24 @@ def _save_and_report(ctx, token, webui, user_info, meta, profile_name):
109
124
  "user": user_info,
110
125
  "current_org": current_org,
111
126
  }
112
- ctx.output(
113
- data,
114
- lambda d: click.echo(
127
+ if access_denied:
128
+ data["cli_access_denied"] = True
129
+
130
+ def _human(_d):
131
+ click.echo(
115
132
  f"Logged in as: {user_info.get('name', '')} "
116
133
  f"({user_info.get('email', '')})\n"
117
134
  f"Saved as: {profile_name}\n"
118
135
  f"Server: {webui}\n"
119
136
  f"Current org: {current_org.get('projectId', '')} "
120
137
  f"{current_org.get('companyName', '')}".rstrip()
121
- ),
122
- )
138
+ )
139
+ if access_denied:
140
+ # Deliberately NOT localized: the surrounding login summary
141
+ # is English-only, so this line stays English too.
142
+ click.echo(f"Error: {cli_access.DENIED_MESSAGE_EN}")
143
+
144
+ ctx.output(data, _human)
123
145
 
124
146
 
125
147
  @auth.command("login")
@@ -156,32 +178,6 @@ def auth_login(ctx, server, timeout, token_opt, profile_opt, force):
156
178
  Use --token to supply a token non-interactively for scripts.
157
179
  """
158
180
  try:
159
- # Shared-credential warm switch: skip the browser when an
160
- # existing session on a sibling host can be reused.
161
- if not token_opt and auth_mod.can_warm_switch_to(server):
162
- target_host = auth_mod._resolve_target_host(server)
163
- if not ctx.json_mode:
164
- click.echo(f"Switching to {target_host} using existing credentials...")
165
- token, webui, user_info, meta, reused = (
166
- auth_mod.shortcut_switch_shared_credential(server)
167
- )
168
- name = resolve_login_profile(profile_opt, webui, force)
169
- _save_and_report(ctx, token, webui, user_info, meta, name)
170
- if not ctx.json_mode and reused:
171
- click.echo("(reused existing token — no browser opened)")
172
- return
173
-
174
- # Cold pre-release: no existing session, but target is meihua.
175
- # The shortcut handles browser-to-prod-then-swap so users still
176
- # land on meihua at the end.
177
- if not token_opt and auth_mod.is_prerelease_login(server):
178
- token, webui, user_info, meta, reused = (
179
- auth_mod.shortcut_switch_shared_credential(server)
180
- )
181
- name = resolve_login_profile(profile_opt, webui, force)
182
- _save_and_report(ctx, token, webui, user_info, meta, name)
183
- return
184
-
185
181
  if token_opt:
186
182
  token, webui, user_info, meta = auth_mod.verify_token(server, token_opt)
187
183
  else:
@@ -316,17 +312,33 @@ def _print_orgs(session, data):
316
312
  pid = p.get("projectId", "")
317
313
  name = p.get("companyName", p.get("name", ""))
318
314
  role = p.get("roleName", "")
319
- marker = "*" if pid and pid == current_org_id else " "
320
- click.echo(f"{marker} {pid} {name} {role}".rstrip())
315
+ # Only render the CLI column when the server gave an explicit
316
+ # verdict; environments without the org switch show no column.
317
+ enabled = p.get("cliAccessEnabled")
318
+ cli_col = ""
319
+ if isinstance(enabled, bool):
320
+ cli_col = "CLI:on" if enabled else "CLI:off"
321
+ click.echo(
322
+ f"{'*' if pid and pid == current_org_id else ' '} "
323
+ f"{pid} {name} {role} {cli_col}".rstrip()
324
+ )
321
325
 
322
326
 
323
327
  @auth.command("list-my-orgs")
324
328
  @pass_context
325
329
  def auth_list_my_orgs(ctx):
326
- """List all organizations the current user belongs to."""
330
+ """List all organizations the current user belongs to.
331
+
332
+ Each row also shows whether the organization currently allows
333
+ CLI access (checked live against the server).
334
+ """
327
335
  try:
336
+ from hap_cli.core import cli_access
337
+
328
338
  session = ctx.get_session()
329
339
  data = auth_mod.list_my_orgs(session)
340
+ if cli_access.GATE_ENABLED:
341
+ cli_access.annotate_orgs_cli_access(session, data)
330
342
  ctx.output(data, lambda d: _print_orgs(session, d))
331
343
  except Exception as e:
332
344
  ctx.handle_error(e)
@@ -336,7 +348,14 @@ def auth_list_my_orgs(ctx):
336
348
  @click.argument("org_id")
337
349
  @pass_context
338
350
  def auth_set_current_org(ctx, org_id):
339
- """Set the saved current organization."""
351
+ """Set the saved current organization.
352
+
353
+ Run 'hap auth list-my-orgs' first to see the organizations you
354
+ belong to and their IDs.
355
+
356
+ Switching to a different organization also clears the saved
357
+ default app — pick a new one with 'hap app select' afterwards.
358
+ """
340
359
  try:
341
360
  session = ctx.get_session()
342
361
  org = auth_mod.switch_org(session, org_id)
@@ -40,25 +40,70 @@ def icon_search(ctx, query, limit):
40
40
  """Search icons by keyword (Chinese or English).
41
41
 
42
42
  Pass one or more keywords; an icon must relate to every keyword to
43
- match. With no keyword, lists the whole catalogue. Use the returned
44
- icon name with the --icon option of app/worksheet creation.
43
+ match. With no keyword, lists the whole catalogue. When fewer than
44
+ 10 icons match, random suggestions top the list up to 10 so you
45
+ always have something to pick from. Use the returned icon name with
46
+ the --icon option of app/worksheet creation.
45
47
  """
46
48
  try:
47
49
  # With no keyword the command acts as "browse all"; the limit
48
50
  # only narrows an actual keyword search.
49
51
  effective_limit = limit if query else None
50
52
  rows = ic_mod.search_icons(list(query), limit=effective_limit)
53
+ if query:
54
+ rows = ic_mod.pad_with_random_icons(
55
+ rows, target=min(10, max(0, limit))
56
+ )
51
57
  ctx.output(rows, _icon_table)
52
58
  except Exception as e:
53
59
  ctx.handle_error(e)
54
60
 
55
61
 
56
62
  @icon.command("list")
63
+ @click.option(
64
+ "--page-size",
65
+ "--size",
66
+ "-n",
67
+ "page_size",
68
+ type=int,
69
+ default=50,
70
+ show_default=True,
71
+ help="Icons per page.",
72
+ )
73
+ @click.option(
74
+ "--page",
75
+ "-p",
76
+ type=int,
77
+ default=1,
78
+ show_default=True,
79
+ help="Page number (1-based).",
80
+ )
57
81
  @pass_context
58
- def icon_list(ctx):
59
- """List every icon in the catalogue with its keywords."""
82
+ def icon_list(ctx, page_size, page):
83
+ """List the icon catalogue page by page with keywords.
84
+
85
+ Shows 50 icons per page by default; use -p/--page to move through
86
+ the catalogue and -n/--page-size to change the page length.
87
+ """
60
88
  try:
61
89
  rows = ic_mod.list_icons()
62
- ctx.output(rows, _icon_table)
90
+ total = len(rows)
91
+ page_size = max(1, page_size)
92
+ pages = max(1, (total + page_size - 1) // page_size)
93
+ page = min(max(1, page), pages)
94
+ start = (page - 1) * page_size
95
+ data = {
96
+ "total": total,
97
+ "page": page,
98
+ "pages": pages,
99
+ "page_size": page_size,
100
+ "icons": rows[start : start + page_size],
101
+ }
102
+
103
+ def show(d):
104
+ _icon_table(d["icons"])
105
+ click.echo(f"Page {d['page']}/{d['pages']} · {d['total']} icons total")
106
+
107
+ ctx.output(data, show)
63
108
  except Exception as e:
64
109
  ctx.handle_error(e)
@@ -253,7 +253,9 @@ def instance_restart(ctx, instance_id, work_id):
253
253
 
254
254
 
255
255
  @instance.command("history")
256
- @click.option("--process-id", default="", help="Filter by process")
256
+ # getHistoryList requires processId server-side (instance.js:60-77 marks
257
+ # it *流程ID); omitting it returns HTTP 400 (bug #036490).
258
+ @click.option("--process-id", required=True, help="Workflow process ID")
257
259
  @click.option("--status", "-s", default=0, type=int,
258
260
  help="Status: 1=running, 2=completed, 3=rejected, 4=failed")
259
261
  @click.option("--keyword", "-k", default="", help="Title search")
@@ -444,7 +444,7 @@ def node_create_code_template(ctx, name, code):
444
444
  @click.option("--fields", "-f", default="", help="Field mapping JSON: [{fieldId,type,fieldValue}]")
445
445
  @click.option("--name", "-n", default="", help="Node name")
446
446
  @click.option("--select-node-id", "-s", default="", help="Source data node ID")
447
- @click.option("--condition", default="", help="Filter conditions JSON")
447
+ @click.option("--condition", default="", help="Filter conditions JSON: [{fieldId, conditionId, value:[...]}] — field type is looked up automatically; AND within a list, wrap lists for OR groups")
448
448
  @click.option("--sorts", default="", help="Sort rules JSON")
449
449
  @pass_context
450
450
  def node_save_action(ctx, process_id, node_id, action_id, app_id, fields,
@@ -465,12 +465,19 @@ def node_save_action(ctx, process_id, node_id, action_id, app_id, fields,
465
465
  try:
466
466
  session = ctx.get_session()
467
467
  fields_list = json.loads(fields) if fields else None
468
- cond_list = json.loads(condition) if condition else None
468
+ filters_list = node_mod.condition_to_filters(
469
+ json.loads(condition) if condition else None)
470
+ if filters_list:
471
+ filters_list = node_mod.fill_condition_field_types(
472
+ session, process_id, node_id, filters_list,
473
+ app_id=app_id, select_node_id=select_node_id,
474
+ action_id=action_id,
475
+ )
469
476
  sorts_list = json.loads(sorts) if sorts else None
470
477
  data = node_mod.save_action_node(
471
478
  session, process_id, node_id, action_id, app_id,
472
479
  fields=fields_list, name=name, select_node_id=select_node_id,
473
- operate_condition=cond_list, sorts=sorts_list,
480
+ filters=filters_list, sorts=sorts_list,
474
481
  )
475
482
  ctx.output(data, lambda d: click.echo("Action node saved."))
476
483
  except json.JSONDecodeError as e:
@@ -489,7 +496,7 @@ def node_save_action(ctx, process_id, node_id, action_id, app_id, fields,
489
496
  @click.option("--fields", "-f", default="", help="Return fields JSON")
490
497
  @click.option("--name", "-n", default="", help="Node name")
491
498
  @click.option("--select-node-id", "-s", default="", help="Source node ID (for 407)")
492
- @click.option("--condition", default="", help="Query conditions JSON")
499
+ @click.option("--condition", default="", help="Filter conditions JSON: [{fieldId, conditionId, value:[...]}] — field type is looked up automatically; AND within a list, wrap lists for OR groups")
493
500
  @click.option("--sorts", default="", help="Sort rules JSON")
494
501
  @click.option("--random", is_flag=True, help="Pick random record")
495
502
  @click.option("--not-found", "execute_type", default=0, type=int,
@@ -515,12 +522,19 @@ def node_save_search(ctx, process_id, node_id, action_id, app_id, fields,
515
522
  try:
516
523
  session = ctx.get_session()
517
524
  fields_list = json.loads(fields) if fields else None
518
- cond_list = json.loads(condition) if condition else None
525
+ filters_list = node_mod.condition_to_filters(
526
+ json.loads(condition) if condition else None)
527
+ if filters_list:
528
+ filters_list = node_mod.fill_condition_field_types(
529
+ session, process_id, node_id, filters_list,
530
+ app_id=app_id, select_node_id=select_node_id,
531
+ action_id=action_id,
532
+ )
519
533
  sorts_list = json.loads(sorts) if sorts else None
520
534
  data = node_mod.save_search_node(
521
535
  session, process_id, node_id, action_id,
522
536
  app_id=app_id, fields=fields_list, name=name,
523
- select_node_id=select_node_id, operate_condition=cond_list,
537
+ select_node_id=select_node_id, filters=filters_list,
524
538
  sorts=sorts_list, random=random, execute_type=execute_type,
525
539
  )
526
540
  ctx.output(data, lambda d: click.echo("Search node saved."))
@@ -540,7 +554,7 @@ def node_save_search(ctx, process_id, node_id, action_id, app_id, fields,
540
554
  @click.option("--fields", "-f", default="", help="Field mapping JSON")
541
555
  @click.option("--name", "-n", default="", help="Node name")
542
556
  @click.option("--select-node-id", "-s", default="", help="Source node ID (for 401)")
543
- @click.option("--condition", default="", help="Filter conditions JSON")
557
+ @click.option("--condition", default="", help="Filter conditions JSON: [{fieldId, conditionId, value:[...]}] — field type is looked up automatically; AND within a list, wrap lists for OR groups")
544
558
  @click.option("--sorts", default="", help="Sort rules JSON")
545
559
  @click.option("--limit", "limit_json", default="", help="Record limit JSON: {fieldValue, fieldNodeId}")
546
560
  @click.option("--random", is_flag=True, help="Pick random records")
@@ -565,13 +579,20 @@ def node_save_get_more(ctx, process_id, node_id, action_id, app_id, fields,
565
579
  try:
566
580
  session = ctx.get_session()
567
581
  fields_list = json.loads(fields) if fields else None
568
- cond_list = json.loads(condition) if condition else None
582
+ filters_list = node_mod.condition_to_filters(
583
+ json.loads(condition) if condition else None)
584
+ if filters_list:
585
+ filters_list = node_mod.fill_condition_field_types(
586
+ session, process_id, node_id, filters_list,
587
+ app_id=app_id, select_node_id=select_node_id,
588
+ action_id=action_id,
589
+ )
569
590
  sorts_list = json.loads(sorts) if sorts else None
570
591
  limit_dict = json.loads(limit_json) if limit_json else None
571
592
  data = node_mod.save_get_more_record_node(
572
593
  session, process_id, node_id, action_id,
573
594
  app_id=app_id, fields=fields_list, name=name,
574
- select_node_id=select_node_id, operate_condition=cond_list,
595
+ select_node_id=select_node_id, filters=filters_list,
575
596
  sorts=sorts_list, number_field_value=limit_dict, random=random,
576
597
  )
577
598
  ctx.output(data, lambda d: click.echo("GetMoreRecord node saved."))
@@ -155,6 +155,10 @@ def record_update(ctx, worksheet_id, row_id, field, fields_json, no_workflow):
155
155
 
156
156
  Pass values either as repeated -f CONTROL_ID=VALUE pairs or as one
157
157
  --fields-json array.
158
+
159
+ A sub-table value is the full list of child rows (each a dict keyed
160
+ by child field name) and replaces the existing rows; an empty list
161
+ clears the sub-table.
158
162
  """
159
163
  if field and fields_json:
160
164
  raise click.UsageError("Pass exactly one of -f or --fields-json.")
@@ -164,7 +168,8 @@ def record_update(ctx, worksheet_id, row_id, field, fields_json, no_workflow):
164
168
  raw = _fields_json_to_raw(fields_json)
165
169
  else:
166
170
  raw = _parse_fields(field)
167
- controls = rec_mod.encode_controls_by_id(session, worksheet_id, raw)
171
+ controls = rec_mod.encode_controls_by_id(
172
+ session, worksheet_id, raw, for_update=True)
168
173
  data = rec_mod.update_record(
169
174
  session, worksheet_id, row_id, controls,
170
175
  trigger_workflow=not no_workflow,
@@ -63,7 +63,7 @@ def workflow_list(ctx, app_id, keyword, enabled, page_size, page):
63
63
  if not aid:
64
64
  raise click.UsageError("App ID required.")
65
65
  result = wf_mod.get_process_list(
66
- session, aid, keyword=keyword,
66
+ session, aid, keyword=keyword, enabled=enabled,
67
67
  page_index=page, page_size=page_size,
68
68
  )
69
69
  ctx.output(
@@ -311,15 +311,22 @@ def workflow_trigger(ctx, process_id, source_id):
311
311
  @click.option("--app-id", "-a", required=True, help="Application ID")
312
312
  @click.option("--trigger-id", default="", help="Trigger ID")
313
313
  @click.option("--title", default="", help="Instance title")
314
+ @click.option("--controls", default="",
315
+ help='Input parameter values JSON: [{controlId, value}]')
314
316
  @pass_context
315
- def workflow_trigger_pbp(ctx, process_id, app_id, trigger_id, title):
317
+ def workflow_trigger_pbp(ctx, process_id, app_id, trigger_id, title,
318
+ controls):
316
319
  """Trigger a PBP (Packaged Business Process) workflow."""
317
320
  try:
318
321
  session = ctx.get_session()
322
+ controls_list = json.loads(controls) if controls else None
319
323
  data = wf_mod.start_process_by_pbp(
320
324
  session, process_id, app_id, trigger_id, title,
325
+ controls=controls_list,
321
326
  )
322
327
  ctx.output(data, lambda d: click.echo(f"PBP triggered: {d}"))
328
+ except json.JSONDecodeError as e:
329
+ ctx.handle_error(click.UsageError(f"Invalid JSON: {e}"))
323
330
  except Exception as e:
324
331
  ctx.handle_error(e)
325
332