hap-cli 0.9.4__tar.gz → 0.9.6__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.
- {hap_cli-0.9.4 → hap_cli-0.9.6}/PKG-INFO +2 -1
- {hap_cli-0.9.4/hap_cli → hap_cli-0.9.6}/README.md +1 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6/hap_cli}/README.md +1 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/README_CN.md +1 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/__init__.py +1 -1
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/config_cmd.py +42 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/post_cmd.py +57 -7
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/context.py +26 -1
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/chat.py +36 -19
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/post.py +58 -10
- hap_cli-0.9.6/hap_cli/core/relogin.py +255 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/session.py +50 -1
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/upload.py +21 -10
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/en/post.md +2 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/zh-Hans/post.md +2 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/locale/messages.json +30 -6
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/conftest.py +12 -0
- hap_cli-0.9.6/hap_cli/tests/test_post_attachments.py +182 -0
- hap_cli-0.9.6/hap_cli/tests/test_relogin.py +234 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli.egg-info/PKG-INFO +2 -1
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli.egg-info/SOURCES.txt +3 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/MANIFEST.in +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/app_live_tests/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/app_live_tests/__main__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/app_live_tests/config.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/app_live_tests/fixtures/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/app_live_tests/fixtures/feedback_scenario.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/app_live_tests/harness.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/app_live_tests/smoke.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/app_live_tests/state.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/__main__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/_entry.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/app_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/app_creator_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/app_editor_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/attachment_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/auth_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/calendar_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/chart_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/chat_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/chatbot_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/contact_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/department_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/group_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/guide_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/icon_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/instance_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/node_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/optionset_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/page_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/record_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/region_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/role_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/update_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/upload_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/v3_registry.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/workflow_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/commands/worksheet_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/action_spec_adapter.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/_hapmeta/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/_hapmeta/control_type_codes.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/_hapmeta/worksheet_templates.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/charts.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/cleanup.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/compiler.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/config.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/design/design.schema.json +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/errors.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/examples/minimal.design.json +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/executor.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/fields.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/hap.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/merge.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/recording/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/recording/console.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/recording/jsonl.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/recording/mirror.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/recording/report.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/schema.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/seed/INSTRUCTIONS.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/seed/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/seed/cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/seed/executor.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/seed/resources/attachments.json +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/seed/resources/sample.docx +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/seed/resources/sample.pdf +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/seed/resources/sample_images.json +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/seed/template.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/selftest.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/smoke.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/steps.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/store.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/validate.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/app_creator/workflow_dsl.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/attachment.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/auth.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/calendar_mod.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/chart.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/chatbot.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/cli_access.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/condition_dsl.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/contact.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/control_type_codes.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/department.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/_hapmeta/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/_hapmeta/control_type_codes.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/apply.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/componentlower.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/editspec/component.schema.json +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/editspec/custom-action.schema.json +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/editspec/envelope.schema.json +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/editspec/field.schema.json +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/editspec.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/errors.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/fieldlower.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/jsonschema_mini.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/models.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/ops.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/planner.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/editor/reader.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/field_normalizer.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/field_spec_adapter.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/filter_translator.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/filter_v3.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/flow_node.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/global_meta.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/group.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/guide.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/icon_index.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/instance.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/layout_check.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/logger.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/optionset.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/page.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/record.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/record_defaults.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/record_form_checks.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/record_lookups.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/record_rules.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/relation_scope.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/response_crypto.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/role.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/role_perm_builder.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/rule_spec_adapter.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/token_crypto.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/update.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/v3/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/v3/dispatcher.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/v3/render.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/v3/schema.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/view_spec_adapter.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/workflow.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/workflow_node_dsl.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/worksheet.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/worksheet_form.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/worksheet_reference.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/core/worksheet_templates.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/en/approval.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/en/chart.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/en/messages.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/en/overview.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/en/record.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/en/setup.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/en/skills.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/en/workflow.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/en/worksheet.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/index.json +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/zh-Hans/approval.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/zh-Hans/chart.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/zh-Hans/messages.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/zh-Hans/overview.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/zh-Hans/record.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/zh-Hans/setup.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/zh-Hans/skills.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/zh-Hans/workflow.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/guide/zh-Hans/worksheet.md +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/i18n.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/locale/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/locale/messages.schema.json +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_action_mdpublic_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_advanced_setting_guard.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_app_creator.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_app_editor.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_app_export_usage.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_app_light_color.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_app_section_name.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_approval_submit_fill_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_approval_wire.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_atomic_write.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_attachment_share.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_auth_prerelease.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_batch_add_atomic.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_bug_036430.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_bug_036750.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_calendar_date_range.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_calendar_discussion_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_chart.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_chart_filter_merge.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_chat_attachment_send.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_chat_messages_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_chat_recall_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_chat_send_socket.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_cli_access.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_coded_responses.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_condition_dsl.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_condition_dsl_entries.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_condition_dsl_readback.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_config_cmd.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_content_language.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_control_lookup_guard.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_core.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_create_worksheet_partial.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_destructive_confirm_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_dsl_existing_node_refs.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_dsl_multi_record_guard.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_editor_inline_subtable.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_engine_core_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_arg_consistency.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_bidirectional.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_discussion_mentions.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_entry_module.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_field_record_ref.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_http_error_body.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_json_anywhere.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_json_file_arg.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_layout_check.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_node_get_detail.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_node_summary.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_post_cursor.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_publish_reasons.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_replicate_workflow.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_save_fields_shape.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_subgroups.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_subtable_read.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_worksheet_references.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_worksheet_visibility.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fb_worksheet_workflows.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_fields_mdpublic_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_full_e2e.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g1_chart_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g1_record_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g1_upload_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g1_worksheet_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g2_coverage_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g3_workflow_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g4_approval_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g5_low_frequency_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g6_advanced_fields.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g6_fields_roundtrip.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g7_misc_gaps.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g7b_permanent_delete.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g8_filter_operator.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g8b_pivot_operators.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g8c_empty_filter_and_help_truth.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_g9_appid_resolve.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_global_meta.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_guide.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_guide_sections.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_i18n.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_inner_flow_batch_add.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_instance_envelope.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_instance_history_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_integration.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_integration_approval.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_integration_approval_actions.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_integration_calendar.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_integration_destructive.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_integration_misc.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_integration_post.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_integration_social.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_integration_v3.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_integration_workflow.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_integration_worksheet_extra.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_jsonschema_mini_copy.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_member_relation_array_wrap.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_multi_profile.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_no_workflow_unsupported.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_noninteractive_confirm.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_org_approval_v3_semantic_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_org_id_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_org_id_docs.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_page_filters_group_read.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_page_filters_group_update.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_page_save_page_id.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_parameter_conventions.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_parameter_mapping_registry.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_post_scope_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_record_batch_v3_semantic_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_record_business_rules.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_record_defaults.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_record_doc_id_hidden.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_record_field_alias.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_record_form_checks.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_record_run_action.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_record_v3_semantic_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_record_write_fixes.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_relation_scope.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_rmw_mdpublic_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_role_app_scope.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_rule_filters_and_field_warning.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_save_action_silent_drop.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_save_rule_spec.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_select_add_option.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_select_rejects_relation_value.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_semantic_types_registry.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_subtable_mdpublic_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_update.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_update_mode.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_upload_allow_down.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_upload_host_resolution.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_upload_mdpublic_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_v3_api_schema_loader.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_v3_bool_flags.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_v3_dispatcher.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_v3_registry_coverage.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_v3_response_format_json.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_v3_session.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_v3_yaml_translation.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_view_mdpublic_parity.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_wf_config_keys.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_wf_inner_scope.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_wf_json_file_arg.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_wf_node_delete_missing.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_wf_save_action_dsl_fields.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_wf_structure_listing.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_wf_trigger_outcome.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_wf_trigger_preserve.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_wo4_result_handling.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_workflow_code_node.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_workflow_condition_field_types.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_workflow_condition_slots.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_workflow_delete_cascade.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_workflow_envelope_errors.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_workflow_lifecycle_wire.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_workflow_list_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_workflow_node_wire.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_workflow_publish_inner.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_workflow_read_write_keys.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_workflow_v3_semantic_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_worksheet_create_section.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_worksheet_crud_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_worksheet_filter_read.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_worksheet_switch.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/tests/test_worksheet_v3_semantic_cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/utils/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/utils/atomic_write.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/utils/confirm.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/utils/formatting.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/utils/options.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli/utils/parameter_mapping.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli.egg-info/dependency_links.txt +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli.egg-info/entry_points.txt +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli.egg-info/requires.txt +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/hap_cli.egg-info/top_level.txt +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/__main__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/_wftest.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/charts.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/cleanup.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/compiler.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/config.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/errors.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/executor.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/fields.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/hap.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/recording/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/recording/console.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/recording/jsonl.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/recording/mirror.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/recording/report.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/schema.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/seed/__init__.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/seed/cli.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/seed/executor.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/seed/template.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/selftest.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/smoke.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/step.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/steps.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/store.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/live_tests/workflow_dsl.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/setup.cfg +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/setup.py +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/INDEX.json +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/add_member_to_role.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/batch_delete_records.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/create_optionset.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/create_role.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/delete_optionset.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/delete_record.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/delete_role.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/delete_worksheet.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_app_info.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_app_knowledge_list.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_app_worksheets_list.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_optionset_list.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_record_details.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_record_discussions.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_record_list.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_record_logs.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_record_pivot_data.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_record_relations.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_record_share_link.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_regions.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_role_details.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/get_role_list.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/knowledge_search.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/leave_all_roles.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/sources/v3-api-schema/remove_member_from_role.yaml +0 -0
- {hap_cli-0.9.4 → hap_cli-0.9.6}/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.
|
|
3
|
+
Version: 0.9.6
|
|
4
4
|
Summary: CLI harness for Mingdao HAP - Enterprise no-code platform
|
|
5
5
|
Author: hap-cli
|
|
6
6
|
License: Apache-2.0
|
|
@@ -339,6 +339,7 @@ discover every subcommand.
|
|
|
339
339
|
| `config completion [bash\|zsh\|fish] [--install]` | Enable `<Tab>` completion |
|
|
340
340
|
| `config language [LANG]` | Switch UI language (`en` / `zh-Hans`, or `auto` to follow the account language) |
|
|
341
341
|
| `config update [auto\|notify\|off]` | Self-upgrade mode; `notify` only reports, `off` never checks |
|
|
342
|
+
| `config auto-login [on\|off]` | Renew an expired login in the browser (one click on Authorize) and carry on; `off` stops with "not logged in" |
|
|
342
343
|
| `config log on / off / status` | Toggle and inspect API logging |
|
|
343
344
|
| `config log level LEVEL` | `DEBUG / INFO / WARNING / ERROR / CRITICAL` |
|
|
344
345
|
| `config log view [--lines N] [--no-follow]` | Tail the log file |
|
|
@@ -310,6 +310,7 @@ discover every subcommand.
|
|
|
310
310
|
| `config completion [bash\|zsh\|fish] [--install]` | Enable `<Tab>` completion |
|
|
311
311
|
| `config language [LANG]` | Switch UI language (`en` / `zh-Hans`, or `auto` to follow the account language) |
|
|
312
312
|
| `config update [auto\|notify\|off]` | Self-upgrade mode; `notify` only reports, `off` never checks |
|
|
313
|
+
| `config auto-login [on\|off]` | Renew an expired login in the browser (one click on Authorize) and carry on; `off` stops with "not logged in" |
|
|
313
314
|
| `config log on / off / status` | Toggle and inspect API logging |
|
|
314
315
|
| `config log level LEVEL` | `DEBUG / INFO / WARNING / ERROR / CRITICAL` |
|
|
315
316
|
| `config log view [--lines N] [--no-follow]` | Tail the log file |
|
|
@@ -310,6 +310,7 @@ discover every subcommand.
|
|
|
310
310
|
| `config completion [bash\|zsh\|fish] [--install]` | Enable `<Tab>` completion |
|
|
311
311
|
| `config language [LANG]` | Switch UI language (`en` / `zh-Hans`, or `auto` to follow the account language) |
|
|
312
312
|
| `config update [auto\|notify\|off]` | Self-upgrade mode; `notify` only reports, `off` never checks |
|
|
313
|
+
| `config auto-login [on\|off]` | Renew an expired login in the browser (one click on Authorize) and carry on; `off` stops with "not logged in" |
|
|
313
314
|
| `config log on / off / status` | Toggle and inspect API logging |
|
|
314
315
|
| `config log level LEVEL` | `DEBUG / INFO / WARNING / ERROR / CRITICAL` |
|
|
315
316
|
| `config log view [--lines N] [--no-follow]` | Tail the log file |
|
|
@@ -289,6 +289,7 @@ hap --json worksheet record list WORKSHEET_ID
|
|
|
289
289
|
| `config completion [bash\|zsh\|fish] [--install]` | 启用 `<Tab>` 补全 |
|
|
290
290
|
| `config language [LANG]` | 切换显示语言(`en` / `zh-Hans`;`auto` 跟随登录账号的语言) |
|
|
291
291
|
| `config update [auto\|notify\|off]` | 自动升级开关;`notify` 只提示不安装,`off` 不检查 |
|
|
292
|
+
| `config auto-login [on\|off]` | 登录过期时自动打开浏览器授权页,点一下「授权」命令继续执行;`off` 则直接报未登录 |
|
|
292
293
|
| `config log on / off / status` | 日志开关与状态 |
|
|
293
294
|
| `config log level LEVEL` | 设置日志级别(`DEBUG/INFO/WARNING/ERROR/CRITICAL`) |
|
|
294
295
|
| `config log view [--lines N] [--no-follow]` | 跟踪日志文件 |
|
|
@@ -126,6 +126,7 @@ def config_completion(shell, install):
|
|
|
126
126
|
@pass_context
|
|
127
127
|
def config_show(ctx):
|
|
128
128
|
"""Display current harness configuration."""
|
|
129
|
+
from hap_cli.core.relogin import get_mode as get_auto_login_mode
|
|
129
130
|
from hap_cli.core.update import get_update_mode
|
|
130
131
|
|
|
131
132
|
log_cfg = load_logging_config()
|
|
@@ -136,6 +137,7 @@ def config_show(ctx):
|
|
|
136
137
|
"file": str(resolve_log_path(log_cfg)),
|
|
137
138
|
},
|
|
138
139
|
"update": get_update_mode(),
|
|
140
|
+
"auto_login": get_auto_login_mode(),
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
def _human(d):
|
|
@@ -144,6 +146,7 @@ def config_show(ctx):
|
|
|
144
146
|
click.echo(f" level : {d['logging']['level']}")
|
|
145
147
|
click.echo(f" file : {d['logging']['file']}")
|
|
146
148
|
click.echo(f"update : {d['update']}")
|
|
149
|
+
click.echo(f"auto-login: {d['auto_login']}")
|
|
147
150
|
|
|
148
151
|
ctx.output(data, _human)
|
|
149
152
|
|
|
@@ -253,6 +256,45 @@ def config_update(ctx, mode):
|
|
|
253
256
|
click.echo(f"Self-update set to: {mode}")
|
|
254
257
|
|
|
255
258
|
|
|
259
|
+
# ── `hap config auto-login` ───────────────────────────────────────────────
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
@config.command("auto-login")
|
|
263
|
+
@click.argument("mode", required=False, type=click.Choice(["on", "off"]))
|
|
264
|
+
@pass_context
|
|
265
|
+
def config_auto_login(ctx, mode):
|
|
266
|
+
"""Control whether an expired login is renewed in the browser.
|
|
267
|
+
|
|
268
|
+
\b
|
|
269
|
+
on when a command finds your login expired, open the browser
|
|
270
|
+
authorization page, wait for you to click Authorize, then
|
|
271
|
+
carry on (default)
|
|
272
|
+
off stop with a "not logged in" error instead
|
|
273
|
+
|
|
274
|
+
Without an argument, shows the current setting. It never applies over
|
|
275
|
+
SSH, in CI, or where no browser can be shown. Setting the environment
|
|
276
|
+
variable HAP_AUTO_LOGIN=0 turns it off for one shell.
|
|
277
|
+
"""
|
|
278
|
+
from hap_cli.core.relogin import CONFIG_KEY, get_mode
|
|
279
|
+
from hap_cli.core.session import save_config
|
|
280
|
+
|
|
281
|
+
if mode is None:
|
|
282
|
+
current = get_mode()
|
|
283
|
+
if ctx.json_mode:
|
|
284
|
+
from hap_cli.utils.formatting import output_json
|
|
285
|
+
output_json({"auto_login": current})
|
|
286
|
+
else:
|
|
287
|
+
click.echo(f"Auto-login: {current}")
|
|
288
|
+
return
|
|
289
|
+
|
|
290
|
+
save_config({CONFIG_KEY: mode})
|
|
291
|
+
if ctx.json_mode:
|
|
292
|
+
from hap_cli.utils.formatting import output_json
|
|
293
|
+
output_json({"status": "ok", "auto_login": mode})
|
|
294
|
+
else:
|
|
295
|
+
click.echo(f"Auto-login set to: {mode}")
|
|
296
|
+
|
|
297
|
+
|
|
256
298
|
# ── `hap config language` ─────────────────────────────────────────────────
|
|
257
299
|
|
|
258
300
|
|
|
@@ -131,6 +131,19 @@ def _resolve_markers(
|
|
|
131
131
|
return out
|
|
132
132
|
|
|
133
133
|
|
|
134
|
+
def _simplify_attachments(items: Any) -> list[dict[str, Any]]:
|
|
135
|
+
out = []
|
|
136
|
+
for a in items or []:
|
|
137
|
+
if not isinstance(a, dict):
|
|
138
|
+
continue
|
|
139
|
+
out.append({
|
|
140
|
+
"id": a.get("fileID"),
|
|
141
|
+
"name": f"{a.get('originalFilename') or ''}{a.get('ext') or ''}",
|
|
142
|
+
"size": a.get("filesize"),
|
|
143
|
+
})
|
|
144
|
+
return out
|
|
145
|
+
|
|
146
|
+
|
|
134
147
|
def _simplify_comment(c: dict[str, Any]) -> dict[str, Any]:
|
|
135
148
|
text = _resolve_markers(
|
|
136
149
|
c.get("message") or "",
|
|
@@ -152,6 +165,9 @@ def _simplify_comment(c: dict[str, Any]) -> dict[str, Any]:
|
|
|
152
165
|
}
|
|
153
166
|
if c.get("withAttachment") and str(c["withAttachment"]) != "0":
|
|
154
167
|
out["has_attachment"] = True
|
|
168
|
+
files = _simplify_attachments(c.get("attachments"))
|
|
169
|
+
if files:
|
|
170
|
+
out["attachments"] = files
|
|
155
171
|
return out
|
|
156
172
|
|
|
157
173
|
|
|
@@ -203,6 +219,9 @@ def _simplify_post(p: dict[str, Any]) -> dict[str, Any]:
|
|
|
203
219
|
m_groups = [_simplify_group_ref(g) for g in (p.get("rGroupList") or [])]
|
|
204
220
|
if m_groups:
|
|
205
221
|
out["mentioned_groups"] = m_groups
|
|
222
|
+
files = _simplify_attachments(p.get("attachments"))
|
|
223
|
+
if files:
|
|
224
|
+
out["attachments"] = files
|
|
206
225
|
return out
|
|
207
226
|
|
|
208
227
|
|
|
@@ -377,6 +396,8 @@ def _render_post_detail(detail: dict[str, Any]) -> None:
|
|
|
377
396
|
click.echo("")
|
|
378
397
|
for line in (detail.get("text") or "").splitlines() or [""]:
|
|
379
398
|
click.echo(f" {line}")
|
|
399
|
+
for f in detail.get("attachments") or []:
|
|
400
|
+
click.echo(f" 📎 {f.get('name')}")
|
|
380
401
|
click.echo("")
|
|
381
402
|
|
|
382
403
|
stats = (
|
|
@@ -414,6 +435,8 @@ def _render_post_detail(detail: dict[str, Any]) -> None:
|
|
|
414
435
|
click.echo(header)
|
|
415
436
|
for line in (c.get("text") or "").splitlines() or [""]:
|
|
416
437
|
click.echo(f" {line}")
|
|
438
|
+
for f in c.get("attachments") or []:
|
|
439
|
+
click.echo(f" 📎 {f.get('name')}")
|
|
417
440
|
click.echo("")
|
|
418
441
|
|
|
419
442
|
|
|
@@ -669,7 +692,13 @@ def post_get(ctx, post_id):
|
|
|
669
692
|
default=0,
|
|
670
693
|
type=int,
|
|
671
694
|
show_default=True,
|
|
672
|
-
help="Post type
|
|
695
|
+
help="Post type. Leave at 0 (text); adding --file makes it an "
|
|
696
|
+
"attachment post on its own.",
|
|
697
|
+
)
|
|
698
|
+
@click.option(
|
|
699
|
+
"--file", "-f", "files", multiple=True,
|
|
700
|
+
help="Attach a file: a local path or an http(s) address. Repeat for "
|
|
701
|
+
"several. Videos, pictures and documents all work.",
|
|
673
702
|
)
|
|
674
703
|
@click.option(
|
|
675
704
|
"--to-group",
|
|
@@ -694,15 +723,20 @@ def post_get(ctx, post_id):
|
|
|
694
723
|
@click.option("--dry-run", is_flag=True,
|
|
695
724
|
help="Show the audience and what would be sent, without publishing.")
|
|
696
725
|
@pass_context
|
|
697
|
-
def post_create(ctx, org_id, message, post_type,
|
|
698
|
-
legacy_group_ids, legacy_org_ids,
|
|
726
|
+
def post_create(ctx, org_id, message, post_type, files, share_group_ids,
|
|
727
|
+
share_org_ids, legacy_group_ids, legacy_org_ids,
|
|
728
|
+
card_group_ids, dry_run):
|
|
699
729
|
"""Create a new post in the given organization.
|
|
700
730
|
|
|
701
731
|
Audience is set with --to-group / --to-org and defaults to everyone in
|
|
702
732
|
--org-id when neither is given. Who can see a post is covered in
|
|
703
733
|
`hap guide post audience`; the group-chat card is `hap guide post card`.
|
|
734
|
+
Files given with --file are uploaded and attached to the post.
|
|
704
735
|
"""
|
|
705
736
|
try:
|
|
737
|
+
if post_type == post_mod.POST_TYPE_ATTACHMENT and not files:
|
|
738
|
+
raise click.UsageError(
|
|
739
|
+
"An attachment post needs at least one --file.")
|
|
706
740
|
share_group_ids = tuple(share_group_ids) + tuple(legacy_group_ids)
|
|
707
741
|
share_org_ids = tuple(share_org_ids) + tuple(legacy_org_ids)
|
|
708
742
|
if dry_run:
|
|
@@ -712,11 +746,14 @@ def post_create(ctx, org_id, message, post_type, share_group_ids, share_org_ids,
|
|
|
712
746
|
) or [f"org:{org_id or '<current>'} (everyone, default)"]
|
|
713
747
|
ctx.output(
|
|
714
748
|
{"audience": audience, "cardToGroups": list(card_group_ids),
|
|
715
|
-
"message": message, "
|
|
749
|
+
"message": message, "files": list(files),
|
|
750
|
+
"published": False},
|
|
716
751
|
lambda d: click.echo(
|
|
717
752
|
"Would publish to: " + ", ".join(d["audience"])
|
|
718
753
|
+ (f"; card to groups: {', '.join(d['cardToGroups'])}"
|
|
719
|
-
if d["cardToGroups"] else "")
|
|
754
|
+
if d["cardToGroups"] else "")
|
|
755
|
+
+ (f"; files: {', '.join(d['files'])}"
|
|
756
|
+
if d["files"] else "")),
|
|
720
757
|
)
|
|
721
758
|
return
|
|
722
759
|
session = ctx.get_session()
|
|
@@ -741,6 +778,8 @@ def post_create(ctx, org_id, message, post_type, share_group_ids, share_org_ids,
|
|
|
741
778
|
+ ". Pick a group whose feed is on, or send a card to the "
|
|
742
779
|
"chat instead with --card-to-group.")
|
|
743
780
|
pid = require_api_project_id(session, org_id)
|
|
781
|
+
attachments = (post_mod.upload_post_files(session, list(files))
|
|
782
|
+
if files else None)
|
|
744
783
|
raw = post_mod.add_post(
|
|
745
784
|
session,
|
|
746
785
|
project_id=pid,
|
|
@@ -748,6 +787,7 @@ def post_create(ctx, org_id, message, post_type, share_group_ids, share_org_ids,
|
|
|
748
787
|
post_type=post_type,
|
|
749
788
|
share_group_ids=list(share_group_ids) or None,
|
|
750
789
|
share_project_ids=list(share_org_ids) or None,
|
|
790
|
+
attachments=attachments,
|
|
751
791
|
)
|
|
752
792
|
post_obj = raw.get("post") if isinstance(raw, dict) else None
|
|
753
793
|
summary = _simplify_post(post_obj) if post_obj else {"raw": raw}
|
|
@@ -821,14 +861,22 @@ def post_delete(ctx, post_id, yes):
|
|
|
821
861
|
default="",
|
|
822
862
|
help="Member id being replied to (optional; pairs with --reply-id)",
|
|
823
863
|
)
|
|
864
|
+
@click.option(
|
|
865
|
+
"--file", "-f", "files", multiple=True,
|
|
866
|
+
help="Attach a file: a local path or an http(s) address. Repeat for "
|
|
867
|
+
"several. Videos, pictures and documents all work.",
|
|
868
|
+
)
|
|
824
869
|
@pass_context
|
|
825
|
-
def post_comment(ctx, post_id, message, reply_id, reply_account_id):
|
|
826
|
-
"""Add a comment to a post."""
|
|
870
|
+
def post_comment(ctx, post_id, message, reply_id, reply_account_id, files):
|
|
871
|
+
"""Add a comment to a post, optionally with files attached."""
|
|
827
872
|
try:
|
|
828
873
|
session = ctx.get_session()
|
|
874
|
+
attachments = (post_mod.upload_post_files(session, list(files))
|
|
875
|
+
if files else None)
|
|
829
876
|
raw = post_mod.add_comment(
|
|
830
877
|
session, post_id, message,
|
|
831
878
|
reply_id=reply_id, reply_account_id=reply_account_id,
|
|
879
|
+
attachments=attachments,
|
|
832
880
|
)
|
|
833
881
|
comment_obj = raw.get("comment") if isinstance(raw, dict) else None
|
|
834
882
|
summary = _simplify_comment(comment_obj) if comment_obj else {"raw": raw}
|
|
@@ -864,6 +912,8 @@ def post_comments(ctx, post_id):
|
|
|
864
912
|
click.echo(header)
|
|
865
913
|
for line in (c.get("text") or "").splitlines() or [""]:
|
|
866
914
|
click.echo(f" {line}")
|
|
915
|
+
for f in c.get("attachments") or []:
|
|
916
|
+
click.echo(f" 📎 {f.get('name')}")
|
|
867
917
|
click.echo(f" id: {c.get('id')}")
|
|
868
918
|
click.echo("")
|
|
869
919
|
ctx.output(comments, _render)
|
|
@@ -20,6 +20,27 @@ NOT_LOGGED_IN_HINT = (
|
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
def _relogin_notice(login_url: str, timeout: int) -> None:
|
|
24
|
+
"""Tell the user an authorization page is waiting for one click.
|
|
25
|
+
|
|
26
|
+
Written to stderr so ``--json`` output on stdout stays parseable; the
|
|
27
|
+
desktop notification is for callers (AI agents) whose terminal output
|
|
28
|
+
the user only sees after the command ends.
|
|
29
|
+
"""
|
|
30
|
+
from hap_cli.core.relogin import desktop_notify
|
|
31
|
+
from hap_cli.i18n import t
|
|
32
|
+
|
|
33
|
+
click.echo(
|
|
34
|
+
t("Your HAP login has expired. A browser page is open — click "
|
|
35
|
+
"Authorize (授权) to continue (waiting up to {seconds}s).").format(
|
|
36
|
+
seconds=timeout),
|
|
37
|
+
err=True,
|
|
38
|
+
)
|
|
39
|
+
click.echo(f" {login_url}", err=True)
|
|
40
|
+
desktop_notify(t("Login expired — click Authorize (授权) in the browser "
|
|
41
|
+
"to let the command continue."))
|
|
42
|
+
|
|
43
|
+
|
|
23
44
|
class Context:
|
|
24
45
|
"""Shared CLI context."""
|
|
25
46
|
|
|
@@ -43,6 +64,7 @@ class Context:
|
|
|
43
64
|
"""
|
|
44
65
|
if self.session is None:
|
|
45
66
|
self.session = Session.load(self.profile)
|
|
67
|
+
self.session.relogin_notice = _relogin_notice
|
|
46
68
|
# One-time migration for sessions logged in before account_id
|
|
47
69
|
# was persisted. Some HAP controllers (notably
|
|
48
70
|
# Invitation/InviteUser) silently degrade when the AccountId
|
|
@@ -55,7 +77,10 @@ class Context:
|
|
|
55
77
|
):
|
|
56
78
|
self.session._lazy_resolve_account_id()
|
|
57
79
|
if require_auth and not self.session.auth_token:
|
|
58
|
-
|
|
80
|
+
# A saved environment without a token: authorize it again in
|
|
81
|
+
# the browser rather than stopping the command.
|
|
82
|
+
if not (self.session.login_url and self.session.recover_auth()):
|
|
83
|
+
raise SessionError("Not logged in. Run 'hap auth login' first.")
|
|
59
84
|
return self.session
|
|
60
85
|
|
|
61
86
|
def output(self, data, table_fn=None):
|
|
@@ -48,26 +48,43 @@ def _chatmq_get(
|
|
|
48
48
|
# mirror the other transport hooks.
|
|
49
49
|
from hap_cli.core import cli_access
|
|
50
50
|
|
|
51
|
+
from hap_cli.core.session import AuthenticationError
|
|
52
|
+
|
|
51
53
|
cli_access.ensure_before_request(session, url)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
54
|
+
|
|
55
|
+
def _send():
|
|
56
|
+
headers = {
|
|
57
|
+
"Authorization": f"md_pss_id {session.auth_token}",
|
|
58
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
59
|
+
"User-Agent": hap_user_agent(),
|
|
60
|
+
}
|
|
61
|
+
auth_for_log = redact_authorization(headers["Authorization"])
|
|
62
|
+
logger.info(
|
|
63
|
+
"HAP GET %s params=%s Authorization=%s",
|
|
64
|
+
url,
|
|
65
|
+
format_body_for_log(params) or "{}",
|
|
66
|
+
auth_for_log,
|
|
67
|
+
)
|
|
68
|
+
response = requests.get(url, params=params, headers=headers, timeout=timeout)
|
|
69
|
+
logger.info(
|
|
70
|
+
"HAP GET %s -> %d %s",
|
|
71
|
+
url,
|
|
72
|
+
response.status_code,
|
|
73
|
+
format_response_for_log(getattr(response, "text", "") or ""),
|
|
74
|
+
)
|
|
75
|
+
return response
|
|
76
|
+
|
|
77
|
+
response = _send()
|
|
78
|
+
# An expired login gets the same one-shot browser re-authorization as
|
|
79
|
+
# the main transport (Session._post); the read is then resent once.
|
|
80
|
+
if response.status_code == 401:
|
|
81
|
+
if not session.recover_auth():
|
|
82
|
+
raise AuthenticationError(
|
|
83
|
+
"Authentication failed (HTTP 401). "
|
|
84
|
+
"Your session token is missing, invalid, or expired.",
|
|
85
|
+
status_code=401,
|
|
86
|
+
)
|
|
87
|
+
response = _send()
|
|
71
88
|
response.raise_for_status()
|
|
72
89
|
return response.json()
|
|
73
90
|
|
|
@@ -24,6 +24,7 @@ Response envelopes (from a live probe on SaaS):
|
|
|
24
24
|
* ``GetPostDetail`` → bare post object (with ``success: "1"``)
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
|
+
import json
|
|
27
28
|
import logging
|
|
28
29
|
from typing import Any, Optional
|
|
29
30
|
|
|
@@ -219,6 +220,40 @@ def get_post_detail(session: Session, post_id: str) -> dict[str, Any]:
|
|
|
219
220
|
return session.api_call("Post", "GetPostDetail", {"postId": post_id})
|
|
220
221
|
|
|
221
222
|
|
|
223
|
+
# postType of a post carrying uploaded files ("pic and doc"). The feed's
|
|
224
|
+
# own types: 0 text, 1 link, 2 picture, 3 document, 7 vote, 9 attachments
|
|
225
|
+
# (MDPublic src/pages/feed/components/post/postComponent/factory.jsx:18-41,
|
|
226
|
+
# createFeed/index.js:18-22).
|
|
227
|
+
POST_TYPE_ATTACHMENT = 9
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def _attachment_fields(attachments: list[dict[str, Any]]) -> dict[str, str]:
|
|
231
|
+
"""The two attachment keys, as JSON strings — the server takes strings
|
|
232
|
+
here, not arrays. Knowledge-center references are not supported, so
|
|
233
|
+
that list is always empty, as the composer sends it when none are
|
|
234
|
+
picked."""
|
|
235
|
+
return {
|
|
236
|
+
"attachments": json.dumps(attachments, ensure_ascii=False),
|
|
237
|
+
"knowledgeAttach": "[]",
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def upload_post_files(session: Session, sources: list[str]) -> list[dict[str, Any]]:
|
|
242
|
+
"""Upload local paths / http(s) addresses and return attachment items
|
|
243
|
+
for :func:`add_post` / :func:`add_comment`.
|
|
244
|
+
|
|
245
|
+
No organization is named for the upload credential: the feed mounts
|
|
246
|
+
its uploader without a projectId (MDPublic createFeed/
|
|
247
|
+
CreateFeedContent.jsx:124-136), same as chat does here.
|
|
248
|
+
"""
|
|
249
|
+
from hap_cli.core import upload as upload_mod
|
|
250
|
+
|
|
251
|
+
descriptors = upload_mod.upload_files(
|
|
252
|
+
session, upload_mod.source_descriptors(list(sources)))
|
|
253
|
+
logger.info("post: uploaded %d attachment(s)", len(descriptors))
|
|
254
|
+
return upload_mod.attachment_items(descriptors)
|
|
255
|
+
|
|
256
|
+
|
|
222
257
|
def add_post(
|
|
223
258
|
session: Session,
|
|
224
259
|
project_id: str,
|
|
@@ -228,9 +263,16 @@ def add_post(
|
|
|
228
263
|
share_group_ids: Optional[list[str]] = None,
|
|
229
264
|
share_project_ids: Optional[list[str]] = None,
|
|
230
265
|
radio_project_ids: str = "",
|
|
266
|
+
attachments: Optional[list[dict[str, Any]]] = None,
|
|
231
267
|
) -> dict[str, Any]:
|
|
232
268
|
"""Create a post via ``Post.AddPost``.
|
|
233
269
|
|
|
270
|
+
``attachments`` are uploaded-file items (see :func:`upload_post_files`).
|
|
271
|
+
Files make it an attachment post — ``postType`` 9 — and travel as JSON
|
|
272
|
+
strings next to an empty knowledge-center list, exactly as the feed's
|
|
273
|
+
composer sends them (MDPublic src/pages/feed/components/createFeed/
|
|
274
|
+
index.js:18-22 and :163-180; pd-openweb identical).
|
|
275
|
+
|
|
234
276
|
``scope`` is a ``PostShareScopeReq`` object — not an int — and it is
|
|
235
277
|
what decides **who can see the post**. The frontend
|
|
236
278
|
(``pd-openweb/src/pages/feed/components/createFeed/index.js``) posts
|
|
@@ -261,15 +303,16 @@ def add_post(
|
|
|
261
303
|
"shareGroupIds": groups,
|
|
262
304
|
"shareProjectIds": orgs,
|
|
263
305
|
}
|
|
264
|
-
|
|
265
|
-
"
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
306
|
+
data: dict[str, Any] = {
|
|
307
|
+
"projectId": project_id,
|
|
308
|
+
"postType": post_type,
|
|
309
|
+
"postMsg": message,
|
|
310
|
+
"scope": scope,
|
|
311
|
+
}
|
|
312
|
+
if attachments:
|
|
313
|
+
data["postType"] = POST_TYPE_ATTACHMENT
|
|
314
|
+
data.update(_attachment_fields(attachments))
|
|
315
|
+
return session.api_call("Post", "AddPost", data)
|
|
273
316
|
|
|
274
317
|
|
|
275
318
|
def edit_post(
|
|
@@ -304,17 +347,22 @@ def add_comment(
|
|
|
304
347
|
message: str,
|
|
305
348
|
reply_id: str = "",
|
|
306
349
|
reply_account_id: str = "",
|
|
350
|
+
attachments: Optional[list[dict[str, Any]]] = None,
|
|
307
351
|
) -> dict[str, Any]:
|
|
308
352
|
"""Add a comment via ``Post.AddPostComment``.
|
|
309
353
|
|
|
310
354
|
Uses ``postID`` / ``replyID`` (capital ID) to match the documented
|
|
311
|
-
spelling in ``src/api/post.js``.
|
|
355
|
+
spelling in ``src/api/post.js``. ``attachments`` go in the same JSON
|
|
356
|
+
string form as on a post (MDPublic src/pages/feed/components/post/
|
|
357
|
+
comment/postCommentInput.jsx:181-192; pd-openweb identical).
|
|
312
358
|
"""
|
|
313
359
|
data: dict[str, Any] = {"postID": post_id, "message": message}
|
|
314
360
|
if reply_id:
|
|
315
361
|
data["replyID"] = reply_id
|
|
316
362
|
if reply_account_id:
|
|
317
363
|
data["replyAccountId"] = reply_account_id
|
|
364
|
+
if attachments:
|
|
365
|
+
data.update(_attachment_fields(attachments))
|
|
318
366
|
return _require_post_success(
|
|
319
367
|
session.api_call("Post", "AddPostComment", data), action="comment")
|
|
320
368
|
|