hap-cli 0.9.7__tar.gz → 0.9.9__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 (419) hide show
  1. {hap_cli-0.9.7 → hap_cli-0.9.9}/PKG-INFO +1 -1
  2. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/__init__.py +1 -1
  3. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/chat_cmd.py +118 -13
  4. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/post_cmd.py +9 -4
  5. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/post.py +36 -14
  6. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/upload.py +13 -2
  7. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/en/messages.md +1 -1
  8. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/en/post.md +5 -4
  9. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/index.json +2 -2
  10. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/zh-Hans/messages.md +1 -1
  11. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/zh-Hans/post.md +4 -3
  12. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/locale/messages.json +48 -24
  13. hap_cli-0.9.9/hap_cli/tests/test_chat_args_and_tables.py +106 -0
  14. hap_cli-0.9.9/hap_cli/tests/test_command_catalog_in_sync.py +40 -0
  15. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_post_group_friction.py +51 -3
  16. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_upload_mdpublic_parity.py +32 -0
  17. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli.egg-info/PKG-INFO +1 -1
  18. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli.egg-info/SOURCES.txt +2 -0
  19. {hap_cli-0.9.7 → hap_cli-0.9.9}/MANIFEST.in +0 -0
  20. {hap_cli-0.9.7 → hap_cli-0.9.9}/README.md +0 -0
  21. {hap_cli-0.9.7 → hap_cli-0.9.9}/app_live_tests/__init__.py +0 -0
  22. {hap_cli-0.9.7 → hap_cli-0.9.9}/app_live_tests/__main__.py +0 -0
  23. {hap_cli-0.9.7 → hap_cli-0.9.9}/app_live_tests/config.py +0 -0
  24. {hap_cli-0.9.7 → hap_cli-0.9.9}/app_live_tests/fixtures/__init__.py +0 -0
  25. {hap_cli-0.9.7 → hap_cli-0.9.9}/app_live_tests/fixtures/feedback_scenario.py +0 -0
  26. {hap_cli-0.9.7 → hap_cli-0.9.9}/app_live_tests/harness.py +0 -0
  27. {hap_cli-0.9.7 → hap_cli-0.9.9}/app_live_tests/smoke.py +0 -0
  28. {hap_cli-0.9.7 → hap_cli-0.9.9}/app_live_tests/state.py +0 -0
  29. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/README.md +0 -0
  30. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/README_CN.md +0 -0
  31. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/__main__.py +0 -0
  32. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/_entry.py +0 -0
  33. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/__init__.py +0 -0
  34. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/app_cmd.py +0 -0
  35. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/app_creator_cmd.py +0 -0
  36. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/app_editor_cmd.py +0 -0
  37. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/attachment_cmd.py +0 -0
  38. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/auth_cmd.py +0 -0
  39. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/calendar_cmd.py +0 -0
  40. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/chart_cmd.py +0 -0
  41. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/chatbot_cmd.py +0 -0
  42. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/config_cmd.py +0 -0
  43. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/contact_cmd.py +0 -0
  44. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/department_cmd.py +0 -0
  45. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/group_cmd.py +0 -0
  46. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/guide_cmd.py +0 -0
  47. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/icon_cmd.py +0 -0
  48. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/instance_cmd.py +0 -0
  49. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/node_cmd.py +0 -0
  50. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/optionset_cmd.py +0 -0
  51. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/page_cmd.py +0 -0
  52. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/record_cmd.py +0 -0
  53. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/region_cmd.py +0 -0
  54. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/role_cmd.py +0 -0
  55. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/update_cmd.py +0 -0
  56. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/upload_cmd.py +0 -0
  57. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/v3_registry.py +0 -0
  58. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/workflow_cmd.py +0 -0
  59. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/commands/worksheet_cmd.py +0 -0
  60. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/context.py +0 -0
  61. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/__init__.py +0 -0
  62. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/action_spec_adapter.py +0 -0
  63. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app.py +0 -0
  64. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/__init__.py +0 -0
  65. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/_hapmeta/__init__.py +0 -0
  66. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/_hapmeta/control_type_codes.py +0 -0
  67. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/_hapmeta/worksheet_templates.py +0 -0
  68. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/charts.py +0 -0
  69. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/cleanup.py +0 -0
  70. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/compiler.py +0 -0
  71. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/config.py +0 -0
  72. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/design/design.schema.json +0 -0
  73. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/errors.py +0 -0
  74. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/examples/minimal.design.json +0 -0
  75. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/executor.py +0 -0
  76. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/fields.py +0 -0
  77. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/hap.py +0 -0
  78. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/merge.py +0 -0
  79. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/recording/__init__.py +0 -0
  80. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/recording/console.py +0 -0
  81. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/recording/jsonl.py +0 -0
  82. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/recording/mirror.py +0 -0
  83. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/recording/report.py +0 -0
  84. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/schema.py +0 -0
  85. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/seed/INSTRUCTIONS.md +0 -0
  86. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/seed/__init__.py +0 -0
  87. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/seed/cli.py +0 -0
  88. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/seed/executor.py +0 -0
  89. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/seed/resources/attachments.json +0 -0
  90. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/seed/resources/sample.docx +0 -0
  91. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/seed/resources/sample.pdf +0 -0
  92. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/seed/resources/sample_images.json +0 -0
  93. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/seed/template.py +0 -0
  94. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/selftest.py +0 -0
  95. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/smoke.py +0 -0
  96. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/steps.py +0 -0
  97. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/store.py +0 -0
  98. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/validate.py +0 -0
  99. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/app_creator/workflow_dsl.py +0 -0
  100. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/attachment.py +0 -0
  101. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/auth.py +0 -0
  102. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/calendar_mod.py +0 -0
  103. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/chart.py +0 -0
  104. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/chat.py +0 -0
  105. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/chatbot.py +0 -0
  106. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/cli_access.py +0 -0
  107. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/condition_dsl.py +0 -0
  108. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/contact.py +0 -0
  109. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/control_type_codes.py +0 -0
  110. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/department.py +0 -0
  111. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/__init__.py +0 -0
  112. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/_hapmeta/__init__.py +0 -0
  113. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/_hapmeta/control_type_codes.py +0 -0
  114. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/apply.py +0 -0
  115. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/componentlower.py +0 -0
  116. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/editspec/component.schema.json +0 -0
  117. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/editspec/custom-action.schema.json +0 -0
  118. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/editspec/envelope.schema.json +0 -0
  119. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/editspec/field.schema.json +0 -0
  120. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/editspec.py +0 -0
  121. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/errors.py +0 -0
  122. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/fieldlower.py +0 -0
  123. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/jsonschema_mini.py +0 -0
  124. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/models.py +0 -0
  125. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/ops.py +0 -0
  126. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/planner.py +0 -0
  127. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/editor/reader.py +0 -0
  128. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/field_normalizer.py +0 -0
  129. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/field_spec_adapter.py +0 -0
  130. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/filter_translator.py +0 -0
  131. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/filter_v3.py +0 -0
  132. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/flow_node.py +0 -0
  133. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/global_meta.py +0 -0
  134. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/group.py +0 -0
  135. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/guide.py +0 -0
  136. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/icon_index.py +0 -0
  137. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/instance.py +0 -0
  138. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/layout_check.py +0 -0
  139. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/logger.py +0 -0
  140. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/optionset.py +0 -0
  141. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/page.py +0 -0
  142. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/record.py +0 -0
  143. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/record_defaults.py +0 -0
  144. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/record_form_checks.py +0 -0
  145. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/record_lookups.py +0 -0
  146. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/record_rules.py +0 -0
  147. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/relation_scope.py +0 -0
  148. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/relogin.py +0 -0
  149. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/response_crypto.py +0 -0
  150. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/role.py +0 -0
  151. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/role_perm_builder.py +0 -0
  152. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/rule_spec_adapter.py +0 -0
  153. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/session.py +0 -0
  154. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/token_crypto.py +0 -0
  155. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/update.py +0 -0
  156. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/v3/__init__.py +0 -0
  157. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/v3/dispatcher.py +0 -0
  158. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/v3/render.py +0 -0
  159. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/v3/schema.py +0 -0
  160. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/view_spec_adapter.py +0 -0
  161. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/workflow.py +0 -0
  162. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/workflow_node_dsl.py +0 -0
  163. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/worksheet.py +0 -0
  164. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/worksheet_form.py +0 -0
  165. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/worksheet_reference.py +0 -0
  166. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/core/worksheet_templates.py +0 -0
  167. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/en/approval.md +0 -0
  168. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/en/chart.md +0 -0
  169. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/en/overview.md +0 -0
  170. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/en/record.md +0 -0
  171. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/en/setup.md +0 -0
  172. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/en/skills.md +0 -0
  173. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/en/workflow.md +0 -0
  174. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/en/worksheet.md +0 -0
  175. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/zh-Hans/approval.md +0 -0
  176. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/zh-Hans/chart.md +0 -0
  177. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/zh-Hans/overview.md +0 -0
  178. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/zh-Hans/record.md +0 -0
  179. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/zh-Hans/setup.md +0 -0
  180. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/zh-Hans/skills.md +0 -0
  181. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/zh-Hans/workflow.md +0 -0
  182. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/guide/zh-Hans/worksheet.md +0 -0
  183. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/i18n.py +0 -0
  184. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/locale/__init__.py +0 -0
  185. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/locale/messages.schema.json +0 -0
  186. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/__init__.py +0 -0
  187. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/conftest.py +0 -0
  188. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_action_mdpublic_parity.py +0 -0
  189. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_advanced_setting_guard.py +0 -0
  190. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_app_creator.py +0 -0
  191. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_app_editor.py +0 -0
  192. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_app_export_usage.py +0 -0
  193. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_app_light_color.py +0 -0
  194. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_app_section_name.py +0 -0
  195. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_approval_submit_fill_cli.py +0 -0
  196. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_approval_wire.py +0 -0
  197. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_atomic_write.py +0 -0
  198. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_attachment_share.py +0 -0
  199. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_auth_prerelease.py +0 -0
  200. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_batch_add_atomic.py +0 -0
  201. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_bug_036430.py +0 -0
  202. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_bug_036750.py +0 -0
  203. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_calendar_date_range.py +0 -0
  204. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_calendar_discussion_cli.py +0 -0
  205. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_chart.py +0 -0
  206. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_chart_filter_merge.py +0 -0
  207. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_chat_attachment_send.py +0 -0
  208. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_chat_messages_cli.py +0 -0
  209. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_chat_recall_cli.py +0 -0
  210. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_chat_send_socket.py +0 -0
  211. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_cli_access.py +0 -0
  212. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_coded_responses.py +0 -0
  213. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_condition_dsl.py +0 -0
  214. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_condition_dsl_entries.py +0 -0
  215. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_condition_dsl_readback.py +0 -0
  216. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_config_cmd.py +0 -0
  217. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_content_language.py +0 -0
  218. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_control_lookup_guard.py +0 -0
  219. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_core.py +0 -0
  220. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_create_worksheet_partial.py +0 -0
  221. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_destructive_confirm_cli.py +0 -0
  222. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_dsl_existing_node_refs.py +0 -0
  223. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_dsl_multi_record_guard.py +0 -0
  224. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_editor_inline_subtable.py +0 -0
  225. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_engine_core_parity.py +0 -0
  226. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_arg_consistency.py +0 -0
  227. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_bidirectional.py +0 -0
  228. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_discussion_mentions.py +0 -0
  229. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_entry_module.py +0 -0
  230. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_field_record_ref.py +0 -0
  231. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_http_error_body.py +0 -0
  232. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_json_anywhere.py +0 -0
  233. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_json_file_arg.py +0 -0
  234. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_layout_check.py +0 -0
  235. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_node_get_detail.py +0 -0
  236. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_node_summary.py +0 -0
  237. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_post_cursor.py +0 -0
  238. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_publish_reasons.py +0 -0
  239. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_replicate_workflow.py +0 -0
  240. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_save_fields_shape.py +0 -0
  241. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_subgroups.py +0 -0
  242. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_subtable_read.py +0 -0
  243. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_worksheet_references.py +0 -0
  244. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_worksheet_visibility.py +0 -0
  245. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fb_worksheet_workflows.py +0 -0
  246. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_fields_mdpublic_parity.py +0 -0
  247. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_full_e2e.py +0 -0
  248. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g1_chart_parity.py +0 -0
  249. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g1_record_parity.py +0 -0
  250. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g1_upload_parity.py +0 -0
  251. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g1_worksheet_parity.py +0 -0
  252. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g2_coverage_parity.py +0 -0
  253. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g3_workflow_parity.py +0 -0
  254. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g4_approval_parity.py +0 -0
  255. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g5_low_frequency_parity.py +0 -0
  256. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g6_advanced_fields.py +0 -0
  257. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g6_fields_roundtrip.py +0 -0
  258. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g7_misc_gaps.py +0 -0
  259. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g7b_permanent_delete.py +0 -0
  260. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g8_filter_operator.py +0 -0
  261. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g8b_pivot_operators.py +0 -0
  262. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g8c_empty_filter_and_help_truth.py +0 -0
  263. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_g9_appid_resolve.py +0 -0
  264. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_global_meta.py +0 -0
  265. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_guide.py +0 -0
  266. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_guide_sections.py +0 -0
  267. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_i18n.py +0 -0
  268. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_inner_flow_batch_add.py +0 -0
  269. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_instance_envelope.py +0 -0
  270. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_instance_history_cli.py +0 -0
  271. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_integration.py +0 -0
  272. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_integration_approval.py +0 -0
  273. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_integration_approval_actions.py +0 -0
  274. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_integration_calendar.py +0 -0
  275. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_integration_destructive.py +0 -0
  276. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_integration_misc.py +0 -0
  277. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_integration_post.py +0 -0
  278. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_integration_social.py +0 -0
  279. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_integration_v3.py +0 -0
  280. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_integration_workflow.py +0 -0
  281. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_integration_worksheet_extra.py +0 -0
  282. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_jsonschema_mini_copy.py +0 -0
  283. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_member_relation_array_wrap.py +0 -0
  284. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_multi_profile.py +0 -0
  285. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_no_workflow_unsupported.py +0 -0
  286. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_noninteractive_confirm.py +0 -0
  287. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_org_approval_v3_semantic_cli.py +0 -0
  288. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_org_id_cli.py +0 -0
  289. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_org_id_docs.py +0 -0
  290. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_page_filters_group_read.py +0 -0
  291. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_page_filters_group_update.py +0 -0
  292. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_page_save_page_id.py +0 -0
  293. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_parameter_conventions.py +0 -0
  294. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_parameter_mapping_registry.py +0 -0
  295. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_post_attachments.py +0 -0
  296. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_post_scope_cli.py +0 -0
  297. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_record_batch_v3_semantic_cli.py +0 -0
  298. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_record_business_rules.py +0 -0
  299. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_record_defaults.py +0 -0
  300. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_record_doc_id_hidden.py +0 -0
  301. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_record_field_alias.py +0 -0
  302. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_record_form_checks.py +0 -0
  303. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_record_run_action.py +0 -0
  304. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_record_v3_semantic_cli.py +0 -0
  305. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_record_write_fixes.py +0 -0
  306. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_relation_scope.py +0 -0
  307. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_relogin.py +0 -0
  308. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_rmw_mdpublic_parity.py +0 -0
  309. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_role_app_scope.py +0 -0
  310. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_rule_filters_and_field_warning.py +0 -0
  311. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_save_action_silent_drop.py +0 -0
  312. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_save_rule_spec.py +0 -0
  313. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_select_add_option.py +0 -0
  314. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_select_rejects_relation_value.py +0 -0
  315. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_semantic_types_registry.py +0 -0
  316. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_subtable_mdpublic_parity.py +0 -0
  317. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_update.py +0 -0
  318. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_update_mode.py +0 -0
  319. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_upload_allow_down.py +0 -0
  320. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_upload_host_resolution.py +0 -0
  321. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_v3_api_schema_loader.py +0 -0
  322. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_v3_bool_flags.py +0 -0
  323. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_v3_dispatcher.py +0 -0
  324. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_v3_registry_coverage.py +0 -0
  325. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_v3_response_format_json.py +0 -0
  326. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_v3_session.py +0 -0
  327. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_v3_yaml_translation.py +0 -0
  328. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_view_mdpublic_parity.py +0 -0
  329. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_wf_config_keys.py +0 -0
  330. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_wf_inner_scope.py +0 -0
  331. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_wf_json_file_arg.py +0 -0
  332. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_wf_node_delete_missing.py +0 -0
  333. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_wf_save_action_dsl_fields.py +0 -0
  334. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_wf_structure_listing.py +0 -0
  335. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_wf_trigger_outcome.py +0 -0
  336. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_wf_trigger_preserve.py +0 -0
  337. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_wo4_result_handling.py +0 -0
  338. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_workflow_code_node.py +0 -0
  339. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_workflow_condition_field_types.py +0 -0
  340. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_workflow_condition_slots.py +0 -0
  341. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_workflow_delete_cascade.py +0 -0
  342. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_workflow_envelope_errors.py +0 -0
  343. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_workflow_lifecycle_wire.py +0 -0
  344. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_workflow_list_cli.py +0 -0
  345. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_workflow_node_wire.py +0 -0
  346. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_workflow_publish_inner.py +0 -0
  347. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_workflow_read_write_keys.py +0 -0
  348. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_workflow_v3_semantic_cli.py +0 -0
  349. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_worksheet_create_section.py +0 -0
  350. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_worksheet_crud_cli.py +0 -0
  351. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_worksheet_filter_read.py +0 -0
  352. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_worksheet_switch.py +0 -0
  353. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/tests/test_worksheet_v3_semantic_cli.py +0 -0
  354. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/utils/__init__.py +0 -0
  355. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/utils/atomic_write.py +0 -0
  356. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/utils/confirm.py +0 -0
  357. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/utils/formatting.py +0 -0
  358. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/utils/options.py +0 -0
  359. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli/utils/parameter_mapping.py +0 -0
  360. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli.egg-info/dependency_links.txt +0 -0
  361. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli.egg-info/entry_points.txt +0 -0
  362. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli.egg-info/requires.txt +0 -0
  363. {hap_cli-0.9.7 → hap_cli-0.9.9}/hap_cli.egg-info/top_level.txt +0 -0
  364. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/__init__.py +0 -0
  365. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/__main__.py +0 -0
  366. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/_wftest.py +0 -0
  367. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/charts.py +0 -0
  368. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/cleanup.py +0 -0
  369. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/compiler.py +0 -0
  370. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/config.py +0 -0
  371. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/errors.py +0 -0
  372. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/executor.py +0 -0
  373. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/fields.py +0 -0
  374. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/hap.py +0 -0
  375. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/recording/__init__.py +0 -0
  376. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/recording/console.py +0 -0
  377. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/recording/jsonl.py +0 -0
  378. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/recording/mirror.py +0 -0
  379. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/recording/report.py +0 -0
  380. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/schema.py +0 -0
  381. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/seed/__init__.py +0 -0
  382. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/seed/cli.py +0 -0
  383. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/seed/executor.py +0 -0
  384. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/seed/template.py +0 -0
  385. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/selftest.py +0 -0
  386. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/smoke.py +0 -0
  387. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/step.py +0 -0
  388. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/steps.py +0 -0
  389. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/store.py +0 -0
  390. {hap_cli-0.9.7 → hap_cli-0.9.9}/live_tests/workflow_dsl.py +0 -0
  391. {hap_cli-0.9.7 → hap_cli-0.9.9}/setup.cfg +0 -0
  392. {hap_cli-0.9.7 → hap_cli-0.9.9}/setup.py +0 -0
  393. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/INDEX.json +0 -0
  394. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/add_member_to_role.yaml +0 -0
  395. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/batch_delete_records.yaml +0 -0
  396. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/create_optionset.yaml +0 -0
  397. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/create_role.yaml +0 -0
  398. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/delete_optionset.yaml +0 -0
  399. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/delete_record.yaml +0 -0
  400. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/delete_role.yaml +0 -0
  401. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/delete_worksheet.yaml +0 -0
  402. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_app_info.yaml +0 -0
  403. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_app_knowledge_list.yaml +0 -0
  404. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_app_worksheets_list.yaml +0 -0
  405. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_optionset_list.yaml +0 -0
  406. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_record_details.yaml +0 -0
  407. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_record_discussions.yaml +0 -0
  408. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_record_list.yaml +0 -0
  409. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_record_logs.yaml +0 -0
  410. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_record_pivot_data.yaml +0 -0
  411. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_record_relations.yaml +0 -0
  412. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_record_share_link.yaml +0 -0
  413. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_regions.yaml +0 -0
  414. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_role_details.yaml +0 -0
  415. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/get_role_list.yaml +0 -0
  416. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/knowledge_search.yaml +0 -0
  417. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/leave_all_roles.yaml +0 -0
  418. {hap_cli-0.9.7 → hap_cli-0.9.9}/sources/v3-api-schema/remove_member_from_role.yaml +0 -0
  419. {hap_cli-0.9.7 → hap_cli-0.9.9}/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.9.7
3
+ Version: 0.9.9
4
4
  Summary: CLI harness for Mingdao HAP - Enterprise no-code platform
5
5
  Author: hap-cli
6
6
  License: Apache-2.0
@@ -3,7 +3,7 @@
3
3
  import sys as _sys
4
4
  import types as _types
5
5
 
6
- __version__ = "0.9.7"
6
+ __version__ = "0.9.9"
7
7
 
8
8
  # The command tree used to live in hap_cli/hap_cli.py. A module named
9
9
  # after the package it sits in shadows that package: run python with the
@@ -1,6 +1,8 @@
1
1
  """CLI commands for chat and messaging management."""
2
2
 
3
+ import html
3
4
  import json
5
+ import re
4
6
 
5
7
  import click
6
8
 
@@ -73,6 +75,103 @@ def _output_chat_list_table(rows):
73
75
  )
74
76
 
75
77
 
78
+ def _one_line(text: str) -> str:
79
+ """Visible text of a message on one line: tags dropped, entities
80
+ decoded, runs of whitespace collapsed."""
81
+ text = html.unescape(re.sub(r"<[^>]*>", "", text or ""))
82
+ return " ".join(text.split())
83
+
84
+
85
+ def _conversation_preview(msg: dict) -> str:
86
+ body = msg.get("msg") or {}
87
+ text = _one_line(str(body.get("con") or ""))
88
+ files = body.get("files")
89
+ if isinstance(files, dict):
90
+ name = f"{files.get('originalFileName') or ''}{files.get('fileExt') or ''}"
91
+ label = "[image]" if msg.get("type") == 2 else "[file]"
92
+ text = " ".join(x for x in (label, name, text) if x)
93
+ return text
94
+
95
+
96
+ def _output_conversation_table(rows):
97
+ """One row per message of a 1-on-1 or group chat, in the order the
98
+ server returns them (newest first)."""
99
+ output_table(
100
+ [
101
+ {
102
+ "time": str(m.get("time") or "")[:19],
103
+ "from": (m.get("fromAccount") or {}).get("name") or m.get("from", ""),
104
+ "message": _conversation_preview(m),
105
+ "id": m.get("id", ""),
106
+ }
107
+ for m in rows or []
108
+ if isinstance(m, dict)
109
+ ],
110
+ ["time", "from", "message", "id"],
111
+ ["Time", "From", "Message", "Message ID"],
112
+ )
113
+
114
+
115
+ def _output_inbox_table(data):
116
+ rows = (data or {}).get("list") or []
117
+ output_table(
118
+ [
119
+ {
120
+ "time": r.get("createTime", ""),
121
+ "from": (r.get("sender") or {}).get("name")
122
+ or (r.get("app") or {}).get("name", ""),
123
+ "message": _one_line(str(r.get("message") or "")),
124
+ }
125
+ for r in rows
126
+ if isinstance(r, dict)
127
+ ],
128
+ ["time", "from", "message"],
129
+ ["Time", "From", "Message"],
130
+ )
131
+
132
+
133
+ def _output_messages(data):
134
+ if isinstance(data, dict) and "list" in data:
135
+ _output_inbox_table(data)
136
+ else:
137
+ _output_conversation_table(data)
138
+
139
+
140
+ def _output_chat_files(data):
141
+ rows = (data or {}).get("list") or []
142
+ output_table(
143
+ [
144
+ {
145
+ "time": r.get("time", ""),
146
+ "name": r.get("name", ""),
147
+ "size": _file_size(r.get("size")),
148
+ "from": (r.get("createAccount") or {}).get("fullname", ""),
149
+ "fileId": r.get("fileId", ""),
150
+ }
151
+ for r in rows
152
+ if isinstance(r, dict)
153
+ ],
154
+ ["time", "name", "size", "from", "fileId"],
155
+ ["Time", "Name", "Size", "From", "File ID"],
156
+ )
157
+ total = (data or {}).get("allCount")
158
+ if isinstance(total, int) and total > len(rows):
159
+ click.echo(f"Showing {len(rows)} of {total} files. Use -p for the "
160
+ f"next page.", err=True)
161
+
162
+
163
+ def _file_size(value) -> str:
164
+ try:
165
+ size = float(value)
166
+ except (TypeError, ValueError):
167
+ return ""
168
+ for unit in ("B", "KB", "MB", "GB"):
169
+ if size < 1024 or unit == "GB":
170
+ return f"{size:.0f} {unit}" if unit == "B" else f"{size:.1f} {unit}"
171
+ size /= 1024
172
+ return ""
173
+
174
+
76
175
  @click.group(help=t(
77
176
  'Chat and messaging management.\n\n'
78
177
  'To follow a notification back to the app record it belongs to, see '
@@ -97,7 +196,8 @@ def chat_list(ctx, page_size, page):
97
196
 
98
197
 
99
198
  @chat.command("files")
100
- @click.option("--with-user", "with_user", help="Peer accountId for 1-on-1 files")
199
+ @click.option("--account-id", "--with-user", "with_user",
200
+ help="Account id of the person, for the files of your 1-on-1 chat")
101
201
  @click.option("--group-id", "group_id", help="Group id for group chat files")
102
202
  @click.option("--page-size", "-n", default=20, help="Items per page")
103
203
  @click.option("--page", "-p", default=1, help="Page number")
@@ -114,11 +214,11 @@ def chat_list(ctx, page_size, page):
114
214
  def chat_files(ctx, with_user, group_id, page_size, page, keywords, file_type, start, end):
115
215
  """List files shared in a 1-on-1 or group chat.
116
216
 
117
- Provide exactly one of --with-user or --group-id.
217
+ Provide exactly one of --account-id or --group-id.
118
218
  """
119
219
  if bool(with_user) == bool(group_id):
120
220
  ctx.handle_error(click.UsageError(
121
- "Provide exactly one of --with-user or --group-id."
221
+ "Provide exactly one of --account-id or --group-id."
122
222
  ))
123
223
  return
124
224
  try:
@@ -145,13 +245,14 @@ def chat_files(ctx, with_user, group_id, page_size, page, keywords, file_type, s
145
245
  start=start,
146
246
  end=end,
147
247
  )
148
- ctx.output(data, lambda d: output_json(d))
248
+ ctx.output(data, _output_chat_files)
149
249
  except Exception as e:
150
250
  ctx.handle_error(e)
151
251
 
152
252
 
153
253
  @chat.command("messages")
154
- @click.option("--with-user", "with_user", help="Peer accountId for 1-on-1 messages")
254
+ @click.option("--account-id", "--with-user", "with_user",
255
+ help="Account id of the person, for your 1-on-1 chat with them")
155
256
  @click.option("--group-id", "group_id", help="Group id for group chat messages")
156
257
  @click.option(
157
258
  "--category",
@@ -202,7 +303,9 @@ def chat_messages(
202
303
  """Fetch chat message history.
203
304
 
204
305
  Provide exactly one of:
205
- --with-user 1-on-1 chat with a user
306
+
307
+ \b
308
+ --account-id 1-on-1 chat with a person
206
309
  --group-id a group chat
207
310
  --category inbox category (system / post / task / calendar /
208
311
  kc / hr / app / workflow)
@@ -211,7 +314,7 @@ def chat_messages(
211
314
  sources = [bool(with_user), bool(group_id), bool(category), bool(inbox_type)]
212
315
  if sum(sources) != 1:
213
316
  ctx.handle_error(click.UsageError(
214
- "Provide exactly one of --with-user / --group-id / --category / --inbox-type."
317
+ "Provide exactly one of --account-id / --group-id / --category / --inbox-type."
215
318
  ))
216
319
  return
217
320
  try:
@@ -250,13 +353,14 @@ def chat_messages(
250
353
  )
251
354
  if mark_read and category:
252
355
  chat_mod.mark_inbox_read(session, category)
253
- ctx.output(data, lambda d: output_json(d))
356
+ ctx.output(data, _output_messages)
254
357
  except Exception as e:
255
358
  ctx.handle_error(e)
256
359
 
257
360
 
258
361
  @chat.command("send-to-one")
259
- @click.option("--to", "-t", multiple=True, help="Target user account ID (can repeat)")
362
+ @click.option("--account-id", "--to", "-t", "to", multiple=True,
363
+ help="Account id of the person to message (repeatable)")
260
364
  @click.option("--message", "-m", default="", help="Message text")
261
365
  @click.option(
262
366
  "--file", "-f", "files", multiple=True,
@@ -282,7 +386,7 @@ def chat_send_to_one(ctx, to, message, files, dry_run):
282
386
  """
283
387
  if not to:
284
388
  ctx.handle_error(click.UsageError(
285
- "Provide at least one --to <accountId>."
389
+ "Provide at least one --account-id."
286
390
  ))
287
391
  return
288
392
  if not message and not files:
@@ -446,8 +550,9 @@ def chat_card_detail(ctx, task, post, calendar, kcfile, worksheet, worksheetrow)
446
550
  @chat.command("recall")
447
551
  @click.argument("message_id")
448
552
  @click.option("--group-id", "group_id", default="", help="Group id the message is in")
449
- @click.option("--with-user", "with_user", default="",
450
- help="Peer accountId for a 1-on-1 message")
553
+ @click.option("--account-id", "--with-user", "with_user", default="",
554
+ help="Account id of the person, for a message in your 1-on-1 "
555
+ "chat with them")
451
556
  @click.option("--time", "msg_time", default="",
452
557
  help="Send time of the message. Looked up from the conversation "
453
558
  "when omitted.")
@@ -465,7 +570,7 @@ def chat_recall(ctx, message_id, group_id, with_user, msg_time, as_admin, dry_ru
465
570
  cannot be undone.
466
571
  """
467
572
  if bool(group_id) == bool(with_user):
468
- raise click.UsageError("Pass exactly one of --group-id or --with-user.")
573
+ raise click.UsageError("Pass exactly one of --group-id or --account-id.")
469
574
  try:
470
575
  session = ctx.get_session()
471
576
  found = None
@@ -778,8 +778,8 @@ def post_create(ctx, org_id, message, post_type, files, share_group_ids,
778
778
  Files given with --file are uploaded and attached to the post.
779
779
 
780
780
  In the message, #name# files the post under the category (topic) of
781
- that name, and [aid]<accountId>[/aid] mentions a person — get the id
782
- with `hap contact resolve <name>`. --dry-run lists both, with the
781
+ that name, and user:<accountId> followed by a space mentions and
782
+ notifies a person — get the id with `hap contact resolve <name>`. --dry-run lists both, with the
783
783
  mentioned names, before anything is published. Details in
784
784
  `hap guide post tags`.
785
785
  """
@@ -796,7 +796,8 @@ def post_create(ctx, org_id, message, post_type, files, share_group_ids,
796
796
  ) or [f"org:{org_id or '<current>'} (everyone, default)"]
797
797
  preview = {"audience": audience,
798
798
  "cardToGroups": list(card_group_ids),
799
- "message": message, "files": list(files),
799
+ "message": post_mod.mention_syntax(message),
800
+ "files": list(files),
800
801
  "categories": post_mod.extract_topics(message),
801
802
  "mentions": _preview_mentions(ctx, org_id, message),
802
803
  "published": False}
@@ -915,7 +916,11 @@ def post_delete(ctx, post_id, yes):
915
916
  )
916
917
  @pass_context
917
918
  def post_comment(ctx, post_id, message, reply_id, reply_account_id, files):
918
- """Add a comment to a post, optionally with files attached."""
919
+ """Add a comment to a post, optionally with files attached.
920
+
921
+ Mention someone with user:<accountId> followed by a space; they are
922
+ notified. Get the id with `hap contact resolve <name>`.
923
+ """
919
924
  try:
920
925
  session = ctx.get_session()
921
926
  attachments = (post_mod.upload_post_files(
@@ -262,14 +262,36 @@ def upload_post_files(
262
262
 
263
263
 
264
264
  # What the feed composer writes into a post body (MDPublic
265
- # src/components/MentionsInput/index.jsx). The post composer opens it
266
- # without a sourceType, so a person is `[aid]<accountId>[/aid]`
267
- # (mentionItemSyntax, :75-76) and a topic is `#name#`, half- or full-width
268
- # `#` (categoryLetterArr, :19; :308). The server files the post under the
269
- # category of that name, creating it when new, and reads it back as
270
- # `categories` — there is no category field on AddPost itself.
265
+ # src/components/MentionsInput/index.jsx). A topic is `#name#`, half- or
266
+ # full-width `#` (categoryLetterArr, :19; :308). The server files the post
267
+ # under the category of that name, creating it when new, and reads it back
268
+ # as `categories` — there is no category field on AddPost itself.
269
+ #
270
+ # A person is `user:<accountId>`: posts and post comments open the
271
+ # composer with sourceType POST, whose mentionItemSyntax is
272
+ # `<type>:<id>` (:75-78), and a captured AddPost / AddPostComment from the
273
+ # web feed (2026-10-12) carries exactly `user:<id> `. The server turns that
274
+ # into the stored `[aid]<id>[/aid]` marker *and* notifies the person.
275
+ # Sending `[aid]…[/aid]` directly renders as a mention but notifies nobody,
276
+ # so callers that learned the stored form are rewritten — the post editor
277
+ # does the same when it loads a post back (EditPostDialog.jsx:94).
271
278
  _TOPIC_RE = re.compile(r"[##]([^##\n]+?)[##]")
272
- _MENTION_RE = re.compile(r"\[aid\]([^\[\]]+?)\[/aid\]")
279
+ _MENTION_RE = re.compile(r"(?<![0-9A-Za-z_])user:([0-9A-Za-z-]+)")
280
+ _STORED_MENTION_RE = re.compile(r"\[aid\]\s*([0-9A-Za-z-]+)\s*\[/aid\]")
281
+
282
+
283
+ def mention_syntax(message: str) -> str:
284
+ """Rewrite stored-form ``[aid]<id>[/aid]`` mentions to ``user:<id>``.
285
+
286
+ A space follows each rewritten mention unless whitespace already does,
287
+ matching the composer, which leaves one after the picked name."""
288
+ text = message or ""
289
+
290
+ def _sub(m: "re.Match[str]") -> str:
291
+ follow = text[m.end():m.end() + 1]
292
+ return f"user:{m.group(1)}" + ("" if not follow or follow.isspace() else " ")
293
+
294
+ return _STORED_MENTION_RE.sub(_sub, text)
273
295
 
274
296
 
275
297
  def extract_topics(message: str) -> list[str]:
@@ -283,11 +305,11 @@ def extract_topics(message: str) -> list[str]:
283
305
 
284
306
 
285
307
  def extract_mentions(message: str) -> list[str]:
286
- """Account ids written as ``[aid]<id>[/aid]`` in a post body, unique."""
308
+ """Account ids mentioned in a post body (``user:<id>``, or the stored
309
+ ``[aid]<id>[/aid]`` form), in order, unique."""
287
310
  seen: list[str] = []
288
- for account_id in _MENTION_RE.findall(message or ""):
289
- account_id = account_id.strip()
290
- if account_id and account_id not in seen:
311
+ for account_id in _MENTION_RE.findall(mention_syntax(message)):
312
+ if account_id not in seen:
291
313
  seen.append(account_id)
292
314
  return seen
293
315
 
@@ -363,7 +385,7 @@ def add_post(
363
385
  data: dict[str, Any] = {
364
386
  "projectId": project_id,
365
387
  "postType": post_type,
366
- "postMsg": message,
388
+ "postMsg": mention_syntax(message),
367
389
  "scope": scope,
368
390
  }
369
391
  if attachments:
@@ -384,7 +406,7 @@ def edit_post(
384
406
  doesn't have the previous text we omit it (the server accepts
385
407
  either shape, but the frontend always sends the old text).
386
408
  """
387
- data: dict[str, Any] = {"postId": post_id, "postMsg": message}
409
+ data: dict[str, Any] = {"postId": post_id, "postMsg": mention_syntax(message)}
388
410
  if old_message:
389
411
  data["oldPostMsg"] = old_message
390
412
  return _require_post_success(
@@ -413,7 +435,7 @@ def add_comment(
413
435
  string form as on a post (MDPublic src/pages/feed/components/post/
414
436
  comment/postCommentInput.jsx:181-192; pd-openweb identical).
415
437
  """
416
- data: dict[str, Any] = {"postID": post_id, "message": message}
438
+ data: dict[str, Any] = {"postID": post_id, "message": mention_syntax(message)}
417
439
  if reply_id:
418
440
  data["replyID"] = reply_id
419
441
  if reply_account_id:
@@ -28,7 +28,7 @@ import re
28
28
  import time
29
29
  from datetime import datetime, timezone
30
30
  from typing import Any, Callable, Optional
31
- from urllib.parse import parse_qs, quote, urlparse
31
+ from urllib.parse import parse_qs, quote, unquote, urlparse
32
32
 
33
33
  import requests
34
34
 
@@ -267,6 +267,17 @@ def _encode_original_name(stem: str) -> str:
267
267
  return quote(stem, safe="")
268
268
 
269
269
 
270
+ def _decode_original_name(echoed: Any, fallback: str) -> str:
271
+ """The store echoes ``x:originalFileName`` exactly as posted — still
272
+ percent-encoded — and the uploader decodes it before handing the file
273
+ on (MDPublic createUploader.js:452). Passing the echo through as-is
274
+ left names like "HDP-%E5%B9%BF%E5%91%8A40s" on posts, chat files and
275
+ record attachments."""
276
+ if not echoed:
277
+ return fallback
278
+ return unquote(str(echoed))
279
+
280
+
270
281
  def _name_and_ext(source: str, *, name: str = "") -> tuple[str, str]:
271
282
  """Derive (originalName-without-ext, ext-with-dot) from a name or path/url.
272
283
 
@@ -368,7 +379,7 @@ def upload_bytes(
368
379
  "filePath": up.get("filePath"),
369
380
  "fileName": up.get("fileName"),
370
381
  "fileExt": up.get("fileExt"),
371
- "originalFileName": up.get("originalFileName"),
382
+ "originalFileName": _decode_original_name(up.get("originalFileName"), original),
372
383
  "key": up.get("key") or token.get("key"),
373
384
  "url": token.get("url"),
374
385
  # The signed URL above stops working at this instant — see
@@ -30,7 +30,7 @@ hap --json chat messages --category app # or workflow, etc.
30
30
  with `viewId`, `comment.recordName` and `comment.entityName`.
31
31
  - Workflow **cc / participant** notifications have the `appId` / `worksheetId` / `rowId`
32
32
  resolved out of the record link for you.
33
- - One-to-one and group chats do not use `--category`; use `--with-user <accountId>` or
33
+ - One-to-one and group chats do not use `--category`; use `--account-id <accountId>` or
34
34
  `--group-id <groupId>` (the id is the conversation's `value`).
35
35
 
36
36
  **3. Read the record and its discussion**
@@ -92,19 +92,20 @@ remove it too, recall that message with
92
92
  minutes of sending; a group admin can recall a member's message with no limit).
93
93
 
94
94
  ## 3. Categories and mentions in the body
95
- <!-- hook: #name# in the body sets the post's category; [aid]accountId[/aid] mentions a person; --dry-run previews both. -->
95
+ <!-- hook: #name# in the body sets the post's category; user:<accountId> mentions and notifies a person; --dry-run previews both. -->
96
96
  <!-- alias: tags -->
97
97
 
98
98
  There is no category option: **the category comes from the body.** Writing
99
99
  `#name#` (for example `#今日工作#`) files the post under the category of that
100
100
  name, creating it if it is new. List existing ones with `hap post topics`.
101
101
 
102
- To mention someone, write `[aid]<accountId>[/aid]` where the `@name` should
103
- go. Get the id from the person's name first:
102
+ To mention someone, write `user:<accountId>` followed by a space where the
103
+ `@name` should go — the person is notified. The same works in
104
+ `hap post comment`. Get the id from the person's name first:
104
105
 
105
106
  ```bash
106
107
  hap contact resolve 刘禹 # candidates[].id is the accountId
107
- hap post create -m "#今日工作# 今天和 [aid]<accountId>[/aid] 对齐了方案" --dry-run
108
+ hap post create -m "#今日工作# 今天和 user:<accountId> 对齐了方案" --dry-run
108
109
  ```
109
110
 
110
111
  A published post's audience cannot be changed, so check with `--dry-run`
@@ -51,8 +51,8 @@
51
51
  "zh-Hans": "发动态与发布范围"
52
52
  },
53
53
  "summary": {
54
- "en": "Audience decides who can see a post, and you cannot read it back off an existing one; #name# in the body sets the category, [aid]…[/aid] mentions someone.",
55
- "zh-Hans": "发布范围决定谁能看到,且无法从旧动态读出来;正文 #名称# 决定分类,[aid]…[/aid] 提及某人。"
54
+ "en": "Audience decides who can see a post, and you cannot read it back off an existing one; #name# in the body sets the category, user:<accountId> notifies a person.",
55
+ "zh-Hans": "发布范围决定谁能看到,且无法从旧动态读出来;正文 #名称# 决定分类,user:<accountId> 提及并通知某人。"
56
56
  }
57
57
  },
58
58
  {
@@ -29,7 +29,7 @@ hap --json chat messages --category app # 或 workflow 等
29
29
  `comment.recordName`、`comment.entityName`。
30
30
  - 工作流**抄送 / 参与者**类通知会把记录链接里的 `appId` / `worksheetId` / `rowId`
31
31
  一并解析出来。
32
- - 单聊 / 群聊不走 `--category`,用 `--with-user <accountId>` 或 `--group-id <groupId>`
32
+ - 单聊 / 群聊不走 `--category`,用 `--account-id <accountId>` 或 `--group-id <groupId>`
33
33
  (id 取会话的 `value`)。
34
34
 
35
35
  **3. 拿三元组直接读记录和讨论**
@@ -80,17 +80,18 @@ hap post create -m "内容" --to-group 9ccde712-xxxx --card-to-group 7f694ec7-xx
80
80
  撤回那条卡片消息(自己的消息限发送后 5 分钟内,群管理员撤回他人消息不限时)。
81
81
 
82
82
  ## 3. 正文里的分类与 @提及
83
- <!-- hook: 正文 #名称# 定分类,[aid]id[/aid] 提及某人,--dry-run 可预览 -->
83
+ <!-- hook: 正文 #名称# 定分类,user:id 提及并通知某人,--dry-run 可预览 -->
84
84
  <!-- alias: tags -->
85
85
 
86
86
  没有设置分类的选项:**分类由正文决定。** 正文里写 `#名称#`(例如 `#今日工作#`),
87
87
  动态就会归到同名分类下,分类不存在时会自动新建。已有分类用 `hap post topics` 查。
88
88
 
89
- 要 @ 某人,在想出现「@姓名」的位置写 `[aid]<accountId>[/aid]`。先用姓名查出 id:
89
+ 要 @ 某人,在想出现「@姓名」的位置写 `user:<accountId>`,后面跟一个空格,对方会收到提醒。
90
+ `hap post comment` 里写法相同。先用姓名查出 id:
90
91
 
91
92
  ```bash
92
93
  hap contact resolve 刘禹 # candidates[].id 就是 accountId
93
- hap post create -m "#今日工作# 今天和 [aid]<accountId>[/aid] 对齐了方案" --dry-run
94
+ hap post create -m "#今日工作# 今天和 user:<accountId> 对齐了方案" --dry-run
94
95
  ```
95
96
 
96
97
  动态发出后范围无法再改,所以先用 `--dry-run` 检查:它会列出分类,以及每个
@@ -3015,6 +3015,30 @@
3015
3015
  "en": "Output in JSON format",
3016
3016
  "zh-Hans": "以 JSON 格式输出"
3017
3017
  },
3018
+ "attachment download": {
3019
+ "en": "Download a file attached to a worksheet record.\n\nFILE_ID is listed in an attachment field or a record operation log.\nExisting local files are never overwritten.",
3020
+ "zh-Hans": "下载工作表记录里的附件。\n\nFILE_ID 可以在附件字段或记录操作日志中找到。不会覆盖本地已有的文件。"
3021
+ },
3022
+ "attachment download --control-id": {
3023
+ "en": "Attachment field containing the file.",
3024
+ "zh-Hans": "附件所在的附件字段。"
3025
+ },
3026
+ "attachment download --json": {
3027
+ "en": "Output in JSON format",
3028
+ "zh-Hans": "以 JSON 格式输出"
3029
+ },
3030
+ "attachment download --output": {
3031
+ "en": "Save as this path. By default, uses the attachment name.",
3032
+ "zh-Hans": "保存到此路径。默认使用附件原名。"
3033
+ },
3034
+ "attachment download --row-id": {
3035
+ "en": "Record containing the attachment.",
3036
+ "zh-Hans": "附件所在的记录。"
3037
+ },
3038
+ "attachment download --worksheet-id": {
3039
+ "en": "Worksheet containing the record.",
3040
+ "zh-Hans": "记录所在的工作表。"
3041
+ },
3018
3042
  "attachment share": {
3019
3043
  "en": "Create a link to a stored file that you can pass on.\n\n\b\n hap attachment share https://doc.example.com/doc/20260830/abc.html\n hap attachment share doc/20260830/abc.html --hours 168\n hap attachment share --file-id <id>\n\nADDRESS is the file's link — a link that has already stopped working\nis fine, paste it as-is — or just the path part of it.",
3020
3044
  "zh-Hans": "为已存储的文件创建可转发的链接。\n\n\b\n hap attachment share https://doc.example.com/doc/20260830/abc.html\n hap attachment share doc/20260830/abc.html --hours 168\n hap attachment share --file-id <id>\n\nADDRESS 是文件的链接——已经失效的链接也可以,原样粘贴即可——或者只传链接中的路径部分。"
@@ -3432,8 +3456,12 @@
3432
3456
  "zh-Hans": "工作表记录,格式 'wsId>rowId',以 '|' 分隔"
3433
3457
  },
3434
3458
  "chat files": {
3435
- "en": "List files shared in a 1-on-1 or group chat.\n\nProvide exactly one of --with-user or --group-id.",
3436
- "zh-Hans": "列出单聊或群聊中共享的文件。\n\n--with-user 与 --group-id 必须且只能提供一个"
3459
+ "en": "List files shared in a 1-on-1 or group chat.\n\nProvide exactly one of --account-id or --group-id.",
3460
+ "zh-Hans": "列出单聊或群聊中共享的文件。\n\n--account-id 与 --group-id 必须且只能提供一个。"
3461
+ },
3462
+ "chat files --account-id": {
3463
+ "en": "Account id of the person, for the files of your 1-on-1 chat",
3464
+ "zh-Hans": "对方的账号 ID,列出你和此人单聊中的文件"
3437
3465
  },
3438
3466
  "chat files --end": {
3439
3467
  "en": "End timestamp (inclusive)",
@@ -3467,10 +3495,6 @@
3467
3495
  "en": "Start timestamp (inclusive)",
3468
3496
  "zh-Hans": "开始时间戳(含)"
3469
3497
  },
3470
- "chat files --with-user": {
3471
- "en": "Peer accountId for 1-on-1 files",
3472
- "zh-Hans": "单聊文件的对方 accountId"
3473
- },
3474
3498
  "chat list": {
3475
3499
  "en": "List recent chat sessions.",
3476
3500
  "zh-Hans": "列出最近的聊天会话"
@@ -3488,8 +3512,12 @@
3488
3512
  "zh-Hans": "每页条数"
3489
3513
  },
3490
3514
  "chat messages": {
3491
- "en": "Fetch chat message history.\n\nProvide exactly one of:\n --with-user 1-on-1 chat with a user\n --group-id a group chat\n --category inbox category (system / post / task / calendar /\n kc / hr / app / workflow)\n --inbox-type raw inbox type code for advanced filters",
3492
- "zh-Hans": "获取聊天消息历史。\n\n以下选项必须且只能提供一个:\n --with-user 与某用户的单聊\n --group-id 群聊\n --category 收件箱分类(system / post / task / calendar /\n kc / hr / app / workflow)\n --inbox-type 原始收件箱类型代码,用于高级筛选"
3515
+ "en": "Fetch chat message history.\n\nProvide exactly one of:\n\n\b\n --account-id 1-on-1 chat with a person\n --group-id a group chat\n --category inbox category (system / post / task / calendar /\n kc / hr / app / workflow)\n --inbox-type raw inbox type code for advanced filters",
3516
+ "zh-Hans": "获取聊天消息历史。\n\n以下选项必须且只能提供一个:\n\n\b\n --account-id 与某人的单聊\n --group-id 群聊\n --category 收件箱分类(system / post / task / calendar /\n kc / hr / app / workflow)\n --inbox-type 原始收件箱类型代码,用于高级筛选"
3517
+ },
3518
+ "chat messages --account-id": {
3519
+ "en": "Account id of the person, for your 1-on-1 chat with them",
3520
+ "zh-Hans": "对方的账号 ID,查看你和此人的单聊"
3493
3521
  },
3494
3522
  "chat messages --category": {
3495
3523
  "en": "Inbox category: system, post, task, calendar, kc, hr, app, workflow",
@@ -3531,14 +3559,14 @@
3531
3559
  "en": "Anchor timestamp, e.g. '2026-04-07 19:06:53.038' (paginate around this)",
3532
3560
  "zh-Hans": "锚点时间戳,例如 '2026-04-07 19:06:53.038'(以此为基准分页)"
3533
3561
  },
3534
- "chat messages --with-user": {
3535
- "en": "Peer accountId for 1-on-1 messages",
3536
- "zh-Hans": "单聊消息的对方 accountId"
3537
- },
3538
3562
  "chat recall": {
3539
3563
  "en": "Recall a message you sent.\n\nYou can recall your own message within 5 minutes of sending it; a group\nadmin can recall another member's message with no time limit. A recall\ncannot be undone.",
3540
3564
  "zh-Hans": "撤回自己发送的消息。自己的消息限发送后 5 分钟内撤回;群管理员撤回其他成员的消息不限时间。撤回后无法恢复。"
3541
3565
  },
3566
+ "chat recall --account-id": {
3567
+ "en": "Account id of the person, for a message in your 1-on-1 chat with them",
3568
+ "zh-Hans": "对方的账号 ID,撤回你和此人单聊中的消息"
3569
+ },
3542
3570
  "chat recall --as-admin": {
3543
3571
  "en": "Recall as a group admin. Admins may recall another member's message; ordinary recall only covers your own.",
3544
3572
  "zh-Hans": "以群管理员身份撤回。管理员可撤回其他成员的消息;普通撤回只能撤回自己的。"
@@ -3559,10 +3587,6 @@
3559
3587
  "en": "Send time of the message. Looked up from the conversation when omitted.",
3560
3588
  "zh-Hans": "消息的发送时间。省略时自动从会话记录中查找。"
3561
3589
  },
3562
- "chat recall --with-user": {
3563
- "en": "Peer accountId for a 1-on-1 message",
3564
- "zh-Hans": "单聊消息的对方 accountId"
3565
- },
3566
3590
  "chat send-to-group": {
3567
3591
  "en": "Send a message, optionally with files, to a group chat.\n\n\b\n hap chat send-to-group -g <groupId> -m \"spec attached\" -f ./spec.pdf\n\nText and each file arrive as separate messages, in that order. An\n@-mention applies to the text line, so it needs --message.",
3568
3592
  "zh-Hans": "向群聊发送消息,可附带文件。\n\n\b\n hap chat send-to-group -g <groupId> -m \"spec attached\" -f ./spec.pdf\n\n文本和每个文件会依次作为独立消息送达。@提及作用于文本行,因此需要 --message"
@@ -3599,6 +3623,10 @@
3599
3623
  "en": "Send a message, optionally with files, to one or more users (1-on-1).\n\n\b\n hap chat send-to-one -t <accountId> -m \"spec attached\" -f ./spec.pdf\n\nText and each file arrive as separate messages, in that order.\n\nTo message yourself, send to the file-transfer assistant with\n-t file-transfer. Your own account id is not a valid target.",
3600
3624
  "zh-Hans": "向一个或多个用户发送消息(单聊),可附带文件。\n\n hap chat send-to-one -t <accountId> -m \"spec attached\" -f ./spec.pdf\n\n文本和每个文件会依次作为独立消息送达。\n\n给自己发消息请发到文件传输助手:-t file-transfer。自己的账号 ID 不是有效目标。"
3601
3625
  },
3626
+ "chat send-to-one --account-id": {
3627
+ "en": "Account id of the person to message (repeatable)",
3628
+ "zh-Hans": "接收消息的人的账号 ID(可重复)"
3629
+ },
3602
3630
  "chat send-to-one --dry-run": {
3603
3631
  "en": "Show what would be sent, without uploading or sending anything.",
3604
3632
  "zh-Hans": "仅显示将要发送的内容,不上传也不发送"
@@ -3615,10 +3643,6 @@
3615
3643
  "en": "Message text",
3616
3644
  "zh-Hans": "消息文本"
3617
3645
  },
3618
- "chat send-to-one --to": {
3619
- "en": "Target user account ID (can repeat)",
3620
- "zh-Hans": "目标用户账号 ID(可重复)"
3621
- },
3622
3646
  "completion": {
3623
3647
  "en": "Alias of `hap config completion`.",
3624
3648
  "zh-Hans": "`hap config completion` 的别名"
@@ -4468,8 +4492,8 @@
4468
4492
  "zh-Hans": "以 JSON 格式输出"
4469
4493
  },
4470
4494
  "post comment": {
4471
- "en": "Add a comment to a post, optionally with files attached.",
4472
- "zh-Hans": "为动态添加评论,可同时附带文件。"
4495
+ "en": "Add a comment to a post, optionally with files attached.\n\nMention someone with user:<accountId> followed by a space; they are\nnotified. Get the id with `hap contact resolve <name>`.",
4496
+ "zh-Hans": "为动态添加评论,可同时附带文件。\n\n要 @ 某人,写 user:<accountId> 并在后面跟一个空格,对方会收到提醒。用 `hap contact resolve <姓名>` 查 id。"
4473
4497
  },
4474
4498
  "post comment --file": {
4475
4499
  "en": "Attach a file: a local path or an http(s) address. Repeat for several. Videos, pictures and documents all work.",
@@ -4512,8 +4536,8 @@
4512
4536
  "zh-Hans": "以 JSON 格式输出"
4513
4537
  },
4514
4538
  "post create": {
4515
- "en": "Create a new post in the given organization.\n\nAudience is set with --to-group / --to-org and defaults to everyone in\n--org-id when neither is given. Who can see a post is covered in\n`hap guide post audience`; the group-chat card is `hap guide post card`.\nFiles given with --file are uploaded and attached to the post.\n\nIn the message, #name# files the post under the category (topic) of\nthat name, and [aid]<accountId>[/aid] mentions a person — get the id\nwith `hap contact resolve <name>`. --dry-run lists both, with the\nmentioned names, before anything is published. Details in\n`hap guide post tags`.",
4516
- "zh-Hans": "在指定组织中发布一条新动态。\n\n发布范围用 --to-group / --to-org 指定,都不给时默认发给 --org-id 组织的全体同事。谁能看到动态见 `hap guide post audience`;群聊卡片见 `hap guide post card`。用 --file 指定的文件会上传并附加到动态上。\n\n正文里写 #名称# 会把动态归到同名分类(话题)下,写 [aid]<accountId>[/aid] 会提及某人——用 `hap contact resolve <姓名>` 查 id。--dry-run 会在发布前列出这两项以及被提及人的姓名。详见 `hap guide post tags`。"
4539
+ "en": "Create a new post in the given organization.\n\nAudience is set with --to-group / --to-org and defaults to everyone in\n--org-id when neither is given. Who can see a post is covered in\n`hap guide post audience`; the group-chat card is `hap guide post card`.\nFiles given with --file are uploaded and attached to the post.\n\nIn the message, #name# files the post under the category (topic) of\nthat name, and user:<accountId> followed by a space mentions and\nnotifies a person — get the id with `hap contact resolve <name>`. --dry-run lists both, with the\nmentioned names, before anything is published. Details in\n`hap guide post tags`.",
4540
+ "zh-Hans": "在指定组织中发布一条新动态。\n\n发布范围用 --to-group / --to-org 指定,都不给时默认发给 --org-id 组织的全体同事。谁能看到动态见 `hap guide post audience`;群聊卡片见 `hap guide post card`。用 --file 指定的文件会上传并附加到动态上。\n\n正文里写 #名称# 会把动态归到同名分类(话题)下,写 user:<accountId> 并在后面跟一个空格会提及并提醒某人——用 `hap contact resolve <姓名>` 查 id。--dry-run 会在发布前列出这两项以及被提及人的姓名。详见 `hap guide post tags`。"
4517
4541
  },
4518
4542
  "post create --card-to-group": {
4519
4543
  "en": "After publishing, also send a card linking to the post into this group chat (repeatable). This is a chat message and does not change who can see the post.",