hap-cli 0.9.8__tar.gz → 0.9.10__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.8 → hap_cli-0.9.10}/MANIFEST.in +6 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/PKG-INFO +1 -1
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/__init__.py +1 -1
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/chat_cmd.py +118 -13
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/v3_registry.py +41 -1
- hap_cli-0.9.10/hap_cli/core/record_discussions.py +137 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/upload.py +13 -2
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/en/messages.md +1 -1
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/zh-Hans/messages.md +1 -1
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/locale/messages.json +44 -20
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli.egg-info/PKG-INFO +1 -1
- hap_cli-0.9.10/hap_cli.egg-info/SOURCES.txt +211 -0
- hap_cli-0.9.10/hap_cli.egg-info/top_level.txt +1 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/setup.py +18 -7
- hap_cli-0.9.8/app_live_tests/__init__.py +0 -11
- hap_cli-0.9.8/app_live_tests/__main__.py +0 -32
- hap_cli-0.9.8/app_live_tests/config.py +0 -20
- hap_cli-0.9.8/app_live_tests/fixtures/__init__.py +0 -1
- hap_cli-0.9.8/app_live_tests/fixtures/feedback_scenario.py +0 -256
- hap_cli-0.9.8/app_live_tests/harness.py +0 -76
- hap_cli-0.9.8/app_live_tests/smoke.py +0 -4937
- hap_cli-0.9.8/app_live_tests/state.py +0 -91
- hap_cli-0.9.8/hap_cli/tests/__init__.py +0 -1
- hap_cli-0.9.8/hap_cli/tests/conftest.py +0 -234
- hap_cli-0.9.8/hap_cli/tests/test_action_mdpublic_parity.py +0 -289
- hap_cli-0.9.8/hap_cli/tests/test_advanced_setting_guard.py +0 -514
- hap_cli-0.9.8/hap_cli/tests/test_app_creator.py +0 -119
- hap_cli-0.9.8/hap_cli/tests/test_app_editor.py +0 -304
- hap_cli-0.9.8/hap_cli/tests/test_app_export_usage.py +0 -224
- hap_cli-0.9.8/hap_cli/tests/test_app_light_color.py +0 -42
- hap_cli-0.9.8/hap_cli/tests/test_app_section_name.py +0 -97
- hap_cli-0.9.8/hap_cli/tests/test_approval_submit_fill_cli.py +0 -143
- hap_cli-0.9.8/hap_cli/tests/test_approval_wire.py +0 -259
- hap_cli-0.9.8/hap_cli/tests/test_atomic_write.py +0 -202
- hap_cli-0.9.8/hap_cli/tests/test_attachment_share.py +0 -434
- hap_cli-0.9.8/hap_cli/tests/test_auth_prerelease.py +0 -154
- hap_cli-0.9.8/hap_cli/tests/test_batch_add_atomic.py +0 -381
- hap_cli-0.9.8/hap_cli/tests/test_bug_036430.py +0 -167
- hap_cli-0.9.8/hap_cli/tests/test_bug_036750.py +0 -130
- hap_cli-0.9.8/hap_cli/tests/test_calendar_date_range.py +0 -51
- hap_cli-0.9.8/hap_cli/tests/test_calendar_discussion_cli.py +0 -89
- hap_cli-0.9.8/hap_cli/tests/test_chart.py +0 -433
- hap_cli-0.9.8/hap_cli/tests/test_chart_filter_merge.py +0 -200
- hap_cli-0.9.8/hap_cli/tests/test_chat_attachment_send.py +0 -501
- hap_cli-0.9.8/hap_cli/tests/test_chat_messages_cli.py +0 -28
- hap_cli-0.9.8/hap_cli/tests/test_chat_recall_cli.py +0 -161
- hap_cli-0.9.8/hap_cli/tests/test_chat_send_socket.py +0 -122
- hap_cli-0.9.8/hap_cli/tests/test_cli_access.py +0 -738
- hap_cli-0.9.8/hap_cli/tests/test_coded_responses.py +0 -152
- hap_cli-0.9.8/hap_cli/tests/test_condition_dsl.py +0 -451
- hap_cli-0.9.8/hap_cli/tests/test_condition_dsl_entries.py +0 -239
- hap_cli-0.9.8/hap_cli/tests/test_condition_dsl_readback.py +0 -131
- hap_cli-0.9.8/hap_cli/tests/test_config_cmd.py +0 -217
- hap_cli-0.9.8/hap_cli/tests/test_content_language.py +0 -120
- hap_cli-0.9.8/hap_cli/tests/test_control_lookup_guard.py +0 -179
- hap_cli-0.9.8/hap_cli/tests/test_core.py +0 -11508
- hap_cli-0.9.8/hap_cli/tests/test_create_worksheet_partial.py +0 -231
- hap_cli-0.9.8/hap_cli/tests/test_destructive_confirm_cli.py +0 -178
- hap_cli-0.9.8/hap_cli/tests/test_dsl_existing_node_refs.py +0 -372
- hap_cli-0.9.8/hap_cli/tests/test_dsl_multi_record_guard.py +0 -444
- hap_cli-0.9.8/hap_cli/tests/test_editor_inline_subtable.py +0 -239
- hap_cli-0.9.8/hap_cli/tests/test_engine_core_parity.py +0 -121
- hap_cli-0.9.8/hap_cli/tests/test_fb_arg_consistency.py +0 -236
- hap_cli-0.9.8/hap_cli/tests/test_fb_bidirectional.py +0 -155
- hap_cli-0.9.8/hap_cli/tests/test_fb_discussion_mentions.py +0 -227
- hap_cli-0.9.8/hap_cli/tests/test_fb_entry_module.py +0 -122
- hap_cli-0.9.8/hap_cli/tests/test_fb_field_record_ref.py +0 -380
- hap_cli-0.9.8/hap_cli/tests/test_fb_http_error_body.py +0 -85
- hap_cli-0.9.8/hap_cli/tests/test_fb_json_anywhere.py +0 -123
- hap_cli-0.9.8/hap_cli/tests/test_fb_json_file_arg.py +0 -65
- hap_cli-0.9.8/hap_cli/tests/test_fb_layout_check.py +0 -206
- hap_cli-0.9.8/hap_cli/tests/test_fb_node_get_detail.py +0 -188
- hap_cli-0.9.8/hap_cli/tests/test_fb_node_summary.py +0 -226
- hap_cli-0.9.8/hap_cli/tests/test_fb_post_cursor.py +0 -119
- hap_cli-0.9.8/hap_cli/tests/test_fb_publish_reasons.py +0 -193
- hap_cli-0.9.8/hap_cli/tests/test_fb_replicate_workflow.py +0 -587
- hap_cli-0.9.8/hap_cli/tests/test_fb_save_fields_shape.py +0 -167
- hap_cli-0.9.8/hap_cli/tests/test_fb_subgroups.py +0 -73
- hap_cli-0.9.8/hap_cli/tests/test_fb_subtable_read.py +0 -281
- hap_cli-0.9.8/hap_cli/tests/test_fb_worksheet_references.py +0 -262
- hap_cli-0.9.8/hap_cli/tests/test_fb_worksheet_visibility.py +0 -133
- hap_cli-0.9.8/hap_cli/tests/test_fb_worksheet_workflows.py +0 -159
- hap_cli-0.9.8/hap_cli/tests/test_fields_mdpublic_parity.py +0 -335
- hap_cli-0.9.8/hap_cli/tests/test_full_e2e.py +0 -179
- hap_cli-0.9.8/hap_cli/tests/test_g1_chart_parity.py +0 -200
- hap_cli-0.9.8/hap_cli/tests/test_g1_record_parity.py +0 -206
- hap_cli-0.9.8/hap_cli/tests/test_g1_upload_parity.py +0 -163
- hap_cli-0.9.8/hap_cli/tests/test_g1_worksheet_parity.py +0 -237
- hap_cli-0.9.8/hap_cli/tests/test_g2_coverage_parity.py +0 -484
- hap_cli-0.9.8/hap_cli/tests/test_g3_workflow_parity.py +0 -348
- hap_cli-0.9.8/hap_cli/tests/test_g4_approval_parity.py +0 -403
- hap_cli-0.9.8/hap_cli/tests/test_g5_low_frequency_parity.py +0 -500
- hap_cli-0.9.8/hap_cli/tests/test_g6_advanced_fields.py +0 -465
- hap_cli-0.9.8/hap_cli/tests/test_g6_fields_roundtrip.py +0 -102
- hap_cli-0.9.8/hap_cli/tests/test_g7_misc_gaps.py +0 -342
- hap_cli-0.9.8/hap_cli/tests/test_g7b_permanent_delete.py +0 -348
- hap_cli-0.9.8/hap_cli/tests/test_g8_filter_operator.py +0 -305
- hap_cli-0.9.8/hap_cli/tests/test_g8b_pivot_operators.py +0 -106
- hap_cli-0.9.8/hap_cli/tests/test_g8c_empty_filter_and_help_truth.py +0 -329
- hap_cli-0.9.8/hap_cli/tests/test_g9_appid_resolve.py +0 -166
- hap_cli-0.9.8/hap_cli/tests/test_global_meta.py +0 -309
- hap_cli-0.9.8/hap_cli/tests/test_guide.py +0 -364
- hap_cli-0.9.8/hap_cli/tests/test_guide_sections.py +0 -322
- hap_cli-0.9.8/hap_cli/tests/test_i18n.py +0 -423
- hap_cli-0.9.8/hap_cli/tests/test_inner_flow_batch_add.py +0 -151
- hap_cli-0.9.8/hap_cli/tests/test_instance_envelope.py +0 -127
- hap_cli-0.9.8/hap_cli/tests/test_instance_history_cli.py +0 -89
- hap_cli-0.9.8/hap_cli/tests/test_integration.py +0 -866
- hap_cli-0.9.8/hap_cli/tests/test_integration_approval.py +0 -320
- hap_cli-0.9.8/hap_cli/tests/test_integration_approval_actions.py +0 -261
- hap_cli-0.9.8/hap_cli/tests/test_integration_calendar.py +0 -283
- hap_cli-0.9.8/hap_cli/tests/test_integration_destructive.py +0 -357
- hap_cli-0.9.8/hap_cli/tests/test_integration_misc.py +0 -171
- hap_cli-0.9.8/hap_cli/tests/test_integration_post.py +0 -118
- hap_cli-0.9.8/hap_cli/tests/test_integration_social.py +0 -191
- hap_cli-0.9.8/hap_cli/tests/test_integration_v3.py +0 -177
- hap_cli-0.9.8/hap_cli/tests/test_integration_workflow.py +0 -145
- hap_cli-0.9.8/hap_cli/tests/test_integration_worksheet_extra.py +0 -154
- hap_cli-0.9.8/hap_cli/tests/test_jsonschema_mini_copy.py +0 -84
- hap_cli-0.9.8/hap_cli/tests/test_member_relation_array_wrap.py +0 -103
- hap_cli-0.9.8/hap_cli/tests/test_multi_profile.py +0 -434
- hap_cli-0.9.8/hap_cli/tests/test_no_workflow_unsupported.py +0 -92
- hap_cli-0.9.8/hap_cli/tests/test_noninteractive_confirm.py +0 -153
- hap_cli-0.9.8/hap_cli/tests/test_org_approval_v3_semantic_cli.py +0 -266
- hap_cli-0.9.8/hap_cli/tests/test_org_id_cli.py +0 -123
- hap_cli-0.9.8/hap_cli/tests/test_org_id_docs.py +0 -35
- hap_cli-0.9.8/hap_cli/tests/test_page_filters_group_read.py +0 -243
- hap_cli-0.9.8/hap_cli/tests/test_page_filters_group_update.py +0 -290
- hap_cli-0.9.8/hap_cli/tests/test_page_save_page_id.py +0 -76
- hap_cli-0.9.8/hap_cli/tests/test_parameter_conventions.py +0 -41
- hap_cli-0.9.8/hap_cli/tests/test_parameter_mapping_registry.py +0 -96
- hap_cli-0.9.8/hap_cli/tests/test_post_attachments.py +0 -182
- hap_cli-0.9.8/hap_cli/tests/test_post_group_friction.py +0 -205
- hap_cli-0.9.8/hap_cli/tests/test_post_scope_cli.py +0 -203
- hap_cli-0.9.8/hap_cli/tests/test_record_batch_v3_semantic_cli.py +0 -279
- hap_cli-0.9.8/hap_cli/tests/test_record_business_rules.py +0 -999
- hap_cli-0.9.8/hap_cli/tests/test_record_defaults.py +0 -723
- hap_cli-0.9.8/hap_cli/tests/test_record_doc_id_hidden.py +0 -199
- hap_cli-0.9.8/hap_cli/tests/test_record_field_alias.py +0 -146
- hap_cli-0.9.8/hap_cli/tests/test_record_form_checks.py +0 -481
- hap_cli-0.9.8/hap_cli/tests/test_record_run_action.py +0 -345
- hap_cli-0.9.8/hap_cli/tests/test_record_v3_semantic_cli.py +0 -96
- hap_cli-0.9.8/hap_cli/tests/test_record_write_fixes.py +0 -125
- hap_cli-0.9.8/hap_cli/tests/test_relation_scope.py +0 -440
- hap_cli-0.9.8/hap_cli/tests/test_relogin.py +0 -234
- hap_cli-0.9.8/hap_cli/tests/test_rmw_mdpublic_parity.py +0 -183
- hap_cli-0.9.8/hap_cli/tests/test_role_app_scope.py +0 -101
- hap_cli-0.9.8/hap_cli/tests/test_rule_filters_and_field_warning.py +0 -199
- hap_cli-0.9.8/hap_cli/tests/test_save_action_silent_drop.py +0 -66
- hap_cli-0.9.8/hap_cli/tests/test_save_rule_spec.py +0 -274
- hap_cli-0.9.8/hap_cli/tests/test_select_add_option.py +0 -78
- hap_cli-0.9.8/hap_cli/tests/test_select_rejects_relation_value.py +0 -182
- hap_cli-0.9.8/hap_cli/tests/test_semantic_types_registry.py +0 -92
- hap_cli-0.9.8/hap_cli/tests/test_subtable_mdpublic_parity.py +0 -82
- hap_cli-0.9.8/hap_cli/tests/test_update.py +0 -424
- hap_cli-0.9.8/hap_cli/tests/test_update_mode.py +0 -90
- hap_cli-0.9.8/hap_cli/tests/test_upload_allow_down.py +0 -118
- hap_cli-0.9.8/hap_cli/tests/test_upload_host_resolution.py +0 -93
- hap_cli-0.9.8/hap_cli/tests/test_upload_mdpublic_parity.py +0 -105
- hap_cli-0.9.8/hap_cli/tests/test_v3_api_schema_loader.py +0 -359
- hap_cli-0.9.8/hap_cli/tests/test_v3_bool_flags.py +0 -195
- hap_cli-0.9.8/hap_cli/tests/test_v3_dispatcher.py +0 -410
- hap_cli-0.9.8/hap_cli/tests/test_v3_registry_coverage.py +0 -139
- hap_cli-0.9.8/hap_cli/tests/test_v3_response_format_json.py +0 -276
- hap_cli-0.9.8/hap_cli/tests/test_v3_session.py +0 -332
- hap_cli-0.9.8/hap_cli/tests/test_v3_yaml_translation.py +0 -322
- hap_cli-0.9.8/hap_cli/tests/test_view_mdpublic_parity.py +0 -197
- hap_cli-0.9.8/hap_cli/tests/test_wf_config_keys.py +0 -153
- hap_cli-0.9.8/hap_cli/tests/test_wf_inner_scope.py +0 -155
- hap_cli-0.9.8/hap_cli/tests/test_wf_json_file_arg.py +0 -86
- hap_cli-0.9.8/hap_cli/tests/test_wf_node_delete_missing.py +0 -98
- hap_cli-0.9.8/hap_cli/tests/test_wf_save_action_dsl_fields.py +0 -184
- hap_cli-0.9.8/hap_cli/tests/test_wf_structure_listing.py +0 -79
- hap_cli-0.9.8/hap_cli/tests/test_wf_trigger_outcome.py +0 -72
- hap_cli-0.9.8/hap_cli/tests/test_wf_trigger_preserve.py +0 -99
- hap_cli-0.9.8/hap_cli/tests/test_wo4_result_handling.py +0 -184
- hap_cli-0.9.8/hap_cli/tests/test_workflow_code_node.py +0 -324
- hap_cli-0.9.8/hap_cli/tests/test_workflow_condition_field_types.py +0 -360
- hap_cli-0.9.8/hap_cli/tests/test_workflow_condition_slots.py +0 -180
- hap_cli-0.9.8/hap_cli/tests/test_workflow_delete_cascade.py +0 -137
- hap_cli-0.9.8/hap_cli/tests/test_workflow_envelope_errors.py +0 -112
- hap_cli-0.9.8/hap_cli/tests/test_workflow_lifecycle_wire.py +0 -179
- hap_cli-0.9.8/hap_cli/tests/test_workflow_list_cli.py +0 -73
- hap_cli-0.9.8/hap_cli/tests/test_workflow_node_wire.py +0 -349
- hap_cli-0.9.8/hap_cli/tests/test_workflow_publish_inner.py +0 -349
- hap_cli-0.9.8/hap_cli/tests/test_workflow_read_write_keys.py +0 -71
- hap_cli-0.9.8/hap_cli/tests/test_workflow_v3_semantic_cli.py +0 -668
- hap_cli-0.9.8/hap_cli/tests/test_worksheet_create_section.py +0 -91
- hap_cli-0.9.8/hap_cli/tests/test_worksheet_crud_cli.py +0 -79
- hap_cli-0.9.8/hap_cli/tests/test_worksheet_filter_read.py +0 -203
- hap_cli-0.9.8/hap_cli/tests/test_worksheet_switch.py +0 -186
- hap_cli-0.9.8/hap_cli/tests/test_worksheet_v3_semantic_cli.py +0 -378
- hap_cli-0.9.8/hap_cli.egg-info/SOURCES.txt +0 -415
- hap_cli-0.9.8/hap_cli.egg-info/top_level.txt +0 -3
- hap_cli-0.9.8/live_tests/__init__.py +0 -16
- hap_cli-0.9.8/live_tests/__main__.py +0 -39
- hap_cli-0.9.8/live_tests/_wftest.py +0 -72
- hap_cli-0.9.8/live_tests/charts.py +0 -454
- hap_cli-0.9.8/live_tests/cleanup.py +0 -67
- hap_cli-0.9.8/live_tests/compiler.py +0 -129
- hap_cli-0.9.8/live_tests/config.py +0 -33
- hap_cli-0.9.8/live_tests/errors.py +0 -51
- hap_cli-0.9.8/live_tests/executor.py +0 -152
- hap_cli-0.9.8/live_tests/fields.py +0 -430
- hap_cli-0.9.8/live_tests/hap.py +0 -147
- hap_cli-0.9.8/live_tests/recording/__init__.py +0 -4
- hap_cli-0.9.8/live_tests/recording/console.py +0 -59
- hap_cli-0.9.8/live_tests/recording/jsonl.py +0 -41
- hap_cli-0.9.8/live_tests/recording/mirror.py +0 -45
- hap_cli-0.9.8/live_tests/recording/report.py +0 -127
- hap_cli-0.9.8/live_tests/schema.py +0 -223
- hap_cli-0.9.8/live_tests/seed/__init__.py +0 -21
- hap_cli-0.9.8/live_tests/seed/cli.py +0 -81
- hap_cli-0.9.8/live_tests/seed/executor.py +0 -264
- hap_cli-0.9.8/live_tests/seed/template.py +0 -154
- hap_cli-0.9.8/live_tests/selftest.py +0 -272
- hap_cli-0.9.8/live_tests/smoke.py +0 -123
- hap_cli-0.9.8/live_tests/step.py +0 -86
- hap_cli-0.9.8/live_tests/steps.py +0 -1125
- hap_cli-0.9.8/live_tests/store.py +0 -332
- hap_cli-0.9.8/live_tests/workflow_dsl.py +0 -456
- {hap_cli-0.9.8 → hap_cli-0.9.10}/README.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/README.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/README_CN.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/__main__.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/_entry.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/__init__.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/app_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/app_creator_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/app_editor_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/attachment_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/auth_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/calendar_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/chart_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/chatbot_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/config_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/contact_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/department_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/group_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/guide_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/icon_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/instance_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/node_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/optionset_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/page_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/post_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/record_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/region_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/role_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/update_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/upload_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/workflow_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/commands/worksheet_cmd.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/context.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/__init__.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/action_spec_adapter.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/__init__.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/_hapmeta/__init__.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/_hapmeta/control_type_codes.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/_hapmeta/worksheet_templates.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/charts.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/cleanup.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/compiler.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/config.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/design/design.schema.json +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/errors.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/examples/minimal.design.json +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/executor.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/fields.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/hap.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/merge.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/recording/__init__.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/recording/console.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/recording/jsonl.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/recording/mirror.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/recording/report.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/schema.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/seed/INSTRUCTIONS.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/seed/__init__.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/seed/cli.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/seed/executor.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/seed/resources/attachments.json +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/seed/resources/sample.docx +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/seed/resources/sample.pdf +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/seed/resources/sample_images.json +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/seed/template.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/selftest.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/smoke.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/steps.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/store.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/validate.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/app_creator/workflow_dsl.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/attachment.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/auth.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/calendar_mod.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/chart.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/chat.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/chatbot.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/cli_access.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/condition_dsl.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/contact.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/control_type_codes.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/department.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/__init__.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/_hapmeta/__init__.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/_hapmeta/control_type_codes.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/apply.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/componentlower.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/editspec/component.schema.json +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/editspec/custom-action.schema.json +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/editspec/envelope.schema.json +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/editspec/field.schema.json +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/editspec.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/errors.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/fieldlower.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/jsonschema_mini.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/models.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/ops.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/planner.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/editor/reader.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/field_normalizer.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/field_spec_adapter.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/filter_translator.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/filter_v3.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/flow_node.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/global_meta.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/group.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/guide.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/icon_index.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/instance.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/layout_check.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/logger.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/optionset.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/page.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/post.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/record.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/record_defaults.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/record_form_checks.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/record_lookups.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/record_rules.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/relation_scope.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/relogin.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/response_crypto.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/role.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/role_perm_builder.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/rule_spec_adapter.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/session.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/token_crypto.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/update.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/v3/__init__.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/v3/dispatcher.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/v3/render.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/v3/schema.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/view_spec_adapter.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/workflow.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/workflow_node_dsl.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/worksheet.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/worksheet_form.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/worksheet_reference.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/core/worksheet_templates.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/en/approval.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/en/chart.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/en/overview.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/en/post.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/en/record.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/en/setup.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/en/skills.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/en/workflow.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/en/worksheet.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/index.json +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/zh-Hans/approval.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/zh-Hans/chart.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/zh-Hans/overview.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/zh-Hans/post.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/zh-Hans/record.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/zh-Hans/setup.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/zh-Hans/skills.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/zh-Hans/workflow.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/guide/zh-Hans/worksheet.md +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/i18n.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/locale/__init__.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/locale/messages.schema.json +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/utils/__init__.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/utils/atomic_write.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/utils/confirm.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/utils/formatting.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/utils/options.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli/utils/parameter_mapping.py +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli.egg-info/dependency_links.txt +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli.egg-info/entry_points.txt +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/hap_cli.egg-info/requires.txt +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/setup.cfg +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/INDEX.json +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/add_member_to_role.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/batch_delete_records.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/create_optionset.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/create_role.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/delete_optionset.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/delete_record.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/delete_role.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/delete_worksheet.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_app_info.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_app_knowledge_list.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_app_worksheets_list.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_optionset_list.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_record_details.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_record_discussions.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_record_list.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_record_logs.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_record_pivot_data.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_record_relations.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_record_share_link.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_regions.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_role_details.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/get_role_list.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/knowledge_search.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/leave_all_roles.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/remove_member_from_role.yaml +0 -0
- {hap_cli-0.9.8 → hap_cli-0.9.10}/sources/v3-api-schema/update_optionset.yaml +0 -0
|
@@ -13,3 +13,9 @@ include hap_cli/README_CN.md
|
|
|
13
13
|
recursive-include hap_cli/locale *.json
|
|
14
14
|
include hap_cli/guide/index.json
|
|
15
15
|
recursive-include hap_cli/guide *.md
|
|
16
|
+
|
|
17
|
+
# Development-only trees stay out of the sdist too (see setup.py _PACKAGES).
|
|
18
|
+
prune hap_cli/tests
|
|
19
|
+
prune live_tests
|
|
20
|
+
prune app_live_tests
|
|
21
|
+
global-exclude __pycache__ *.py[cod]
|
|
@@ -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",
|
|
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 --
|
|
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 --
|
|
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,
|
|
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",
|
|
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
|
-
|
|
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 --
|
|
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,
|
|
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,
|
|
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 --
|
|
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="
|
|
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 --
|
|
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
|
|
@@ -21,6 +21,8 @@ re-implementation on legacy endpoints.
|
|
|
21
21
|
|
|
22
22
|
from __future__ import annotations
|
|
23
23
|
|
|
24
|
+
import logging
|
|
25
|
+
|
|
24
26
|
import click
|
|
25
27
|
|
|
26
28
|
from hap_cli.commands.app_cmd import app
|
|
@@ -34,8 +36,11 @@ from hap_cli.core.v3.render import render_v3_response
|
|
|
34
36
|
from hap_cli.core import worksheet as _ws_mod
|
|
35
37
|
from hap_cli.core import workflow as _wf_mod
|
|
36
38
|
from hap_cli.core import record_lookups as _lookups
|
|
39
|
+
from hap_cli.core import record_discussions as _discussions
|
|
37
40
|
from hap_cli.i18n import t
|
|
38
41
|
|
|
42
|
+
_logger = logging.getLogger("hap_cli.record")
|
|
43
|
+
|
|
39
44
|
|
|
40
45
|
def _drop(group, *names):
|
|
41
46
|
"""Remove legacy commands from a Click group before re-registering.
|
|
@@ -324,7 +329,42 @@ register_v3(record, "get", tool="get_record_details", subtable_guard=True)
|
|
|
324
329
|
# (record_cmd.py) — not V3.
|
|
325
330
|
register_v3(record, "delete", tool="batch_delete_records", # multi-id via batch
|
|
326
331
|
confirm="Delete the selected record(s) from worksheet {worksheet_id}?")
|
|
327
|
-
|
|
332
|
+
def _record_discussions_mentions(ctx, response, options):
|
|
333
|
+
"""Show mentions as @name, in both the JSON and the md form.
|
|
334
|
+
|
|
335
|
+
How the two forms differ, and why md may cost a second read, is in
|
|
336
|
+
``hap_cli.core.record_discussions``."""
|
|
337
|
+
payload = response.get("data") if isinstance(response, dict) else None
|
|
338
|
+
if not isinstance(payload, dict):
|
|
339
|
+
return response
|
|
340
|
+
discussions = payload.get("discussions")
|
|
341
|
+
if isinstance(discussions, list):
|
|
342
|
+
_discussions.render_json(discussions)
|
|
343
|
+
return response
|
|
344
|
+
if not isinstance(discussions, str):
|
|
345
|
+
return response
|
|
346
|
+
names = _discussions.names_from_md(discussions)
|
|
347
|
+
if any(i not in names for i in _discussions.mentioned_ids(discussions)):
|
|
348
|
+
params = click.get_current_context().params
|
|
349
|
+
query = {
|
|
350
|
+
"pageIndex": params.get("page_index"),
|
|
351
|
+
"pageSize": params.get("page_size"),
|
|
352
|
+
"search": params.get("search"),
|
|
353
|
+
"onlyWithAttachments": params.get("only_with_attachments"),
|
|
354
|
+
}
|
|
355
|
+
try:
|
|
356
|
+
names.update(_discussions.fetch_names(
|
|
357
|
+
ctx.get_session(), params.get("worksheet_id") or "",
|
|
358
|
+
params.get("row_id") or "", app_id=_resolve_list_app_id(ctx),
|
|
359
|
+
query={k: v for k, v in query.items() if v not in (None, "")}))
|
|
360
|
+
except Exception as exc:
|
|
361
|
+
_logger.warning("Could not look up mentioned names: %s", exc)
|
|
362
|
+
payload["discussions"] = _discussions.render_md(discussions, names)
|
|
363
|
+
return response
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
register_v3(record, "discussions", tool="get_record_discussions",
|
|
367
|
+
post_process=_record_discussions_mentions)
|
|
328
368
|
register_v3(record, "logs", tool="get_record_logs")
|
|
329
369
|
register_v3(record, "relations", tool="get_record_relations")
|
|
330
370
|
register_v3(record, "pivot", tool="get_record_pivot_data",
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""Readable record discussions: mention markers rendered as ``@name``.
|
|
2
|
+
|
|
3
|
+
A discussion stores its mentions inside the text: ``[aid]<accountId>[/aid]``
|
|
4
|
+
per person (external portal users have ids like ``a#6805…``) and
|
|
5
|
+
``[all]atAll[/all]`` for everyone. The web renders them through
|
|
6
|
+
``createLinksForMessage`` (MDPublic src/components/comment/utils/
|
|
7
|
+
createLinksForMessage.js:86-109): a person becomes ``@<name>`` and the
|
|
8
|
+
everyone marker becomes ``@`` + AT_ALL_TEXT[WORKSHEETROW] = "全体参与者"
|
|
9
|
+
(src/components/comment/config.js:22). An id it cannot name stays as-is.
|
|
10
|
+
|
|
11
|
+
The V3 discussions endpoint answers JSON with a ``mentions`` list that
|
|
12
|
+
names every ``[aid]`` in the message, so the JSON form is rendered from
|
|
13
|
+
the response alone. Its ``md`` form drops that list and writes each author
|
|
14
|
+
as ``{"AccountId":…,"FullNmae":…}`` (sic — a server-side typo), so the md
|
|
15
|
+
form is rendered from a name map the caller supplies.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
import re
|
|
22
|
+
from typing import Any, Iterable
|
|
23
|
+
|
|
24
|
+
AT_ALL_TEXT = "全体参与者"
|
|
25
|
+
|
|
26
|
+
_AID_RE = re.compile(r"\[aid\]([^\[\]]+?)\[/aid\]")
|
|
27
|
+
_ALL_RE = re.compile(r"\[all\]atAll\[/all\]", re.IGNORECASE)
|
|
28
|
+
# One author as the md form writes it; tolerant of the server ever fixing
|
|
29
|
+
# the misspelt key.
|
|
30
|
+
_MD_AUTHOR_RE = re.compile(
|
|
31
|
+
r'\{"AccountId":"([^"]*)","(?:FullNmae|FullName)":"((?:[^"\\]|\\.)*)"\}')
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def render_markers(text: str, names: dict[str, str]) -> str:
|
|
35
|
+
"""Replace mention markers with ``@name``; unknown ids stay visible."""
|
|
36
|
+
if not text:
|
|
37
|
+
return text or ""
|
|
38
|
+
|
|
39
|
+
def _person(m: re.Match) -> str:
|
|
40
|
+
name = names.get(m.group(1).strip())
|
|
41
|
+
return f"@{name}" if name else m.group(0)
|
|
42
|
+
|
|
43
|
+
return _AID_RE.sub(_person, _ALL_RE.sub(f"@{AT_ALL_TEXT}", text))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def mentioned_ids(text: str) -> list[str]:
|
|
47
|
+
seen: list[str] = []
|
|
48
|
+
for aid in _AID_RE.findall(text or ""):
|
|
49
|
+
aid = aid.strip()
|
|
50
|
+
if aid not in seen:
|
|
51
|
+
seen.append(aid)
|
|
52
|
+
return seen
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _people(item: dict) -> Iterable[dict]:
|
|
56
|
+
for key in ("_createdBy", "replyToAuthor"):
|
|
57
|
+
if isinstance(item.get(key), dict):
|
|
58
|
+
yield item[key]
|
|
59
|
+
for person in item.get("mentions") or []:
|
|
60
|
+
if isinstance(person, dict):
|
|
61
|
+
yield person
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def names_from_json(discussions: Any) -> dict[str, str]:
|
|
65
|
+
"""Account id → name from every author, reply target and mention."""
|
|
66
|
+
names: dict[str, str] = {}
|
|
67
|
+
for item in discussions or []:
|
|
68
|
+
if not isinstance(item, dict):
|
|
69
|
+
continue
|
|
70
|
+
for person in _people(item):
|
|
71
|
+
aid = person.get("accountId")
|
|
72
|
+
name = person.get("fullname") or person.get("name")
|
|
73
|
+
if aid and name:
|
|
74
|
+
names[aid] = name
|
|
75
|
+
return names
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def render_json(discussions: Any) -> Any:
|
|
79
|
+
"""Render each discussion's ``message`` in place.
|
|
80
|
+
|
|
81
|
+
The stored text moves to ``rawMessage``; ``mentionsEveryone`` is set
|
|
82
|
+
when the message mentions everyone. The server's ``mentions`` list
|
|
83
|
+
(id and name of each person mentioned) is left as it is."""
|
|
84
|
+
if not isinstance(discussions, list):
|
|
85
|
+
return discussions
|
|
86
|
+
names = names_from_json(discussions)
|
|
87
|
+
for item in discussions:
|
|
88
|
+
if not isinstance(item, dict) or not isinstance(item.get("message"), str):
|
|
89
|
+
continue
|
|
90
|
+
raw = item["message"]
|
|
91
|
+
rendered = render_markers(raw, names)
|
|
92
|
+
if rendered != raw:
|
|
93
|
+
item["rawMessage"] = raw
|
|
94
|
+
item["message"] = rendered
|
|
95
|
+
if _ALL_RE.search(raw):
|
|
96
|
+
item["mentionsEveryone"] = True
|
|
97
|
+
return discussions
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def names_from_md(text: str) -> dict[str, str]:
|
|
101
|
+
names: dict[str, str] = {}
|
|
102
|
+
for aid, name in _MD_AUTHOR_RE.findall(text or ""):
|
|
103
|
+
if aid and name:
|
|
104
|
+
names[aid] = _unescape(name)
|
|
105
|
+
return names
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _unescape(value: str) -> str:
|
|
109
|
+
try:
|
|
110
|
+
return json.loads(f'"{value}"')
|
|
111
|
+
except ValueError:
|
|
112
|
+
return value
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def render_md(text: str, names: dict[str, str]) -> str:
|
|
116
|
+
"""Write authors as plain names and mentions as ``@name``."""
|
|
117
|
+
if not isinstance(text, str):
|
|
118
|
+
return text
|
|
119
|
+
text = _MD_AUTHOR_RE.sub(lambda m: _unescape(m.group(2)), text)
|
|
120
|
+
return render_markers(text, names)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
DISCUSSIONS_PATH = "/v3/app/worksheets/{worksheet_id}/rows/{row_id}/discussions"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def fetch_names(
|
|
127
|
+
session: Any, worksheet_id: str, row_id: str, *, app_id: str,
|
|
128
|
+
query: dict[str, Any],
|
|
129
|
+
) -> dict[str, str]:
|
|
130
|
+
"""Names for the md form: the same page asked for again as JSON, whose
|
|
131
|
+
``mentions`` list names everyone the md text only gives ids for."""
|
|
132
|
+
params = dict(query, responseFormat="json")
|
|
133
|
+
response = session.v3_call(
|
|
134
|
+
"GET", DISCUSSIONS_PATH, app_id=app_id, query=params,
|
|
135
|
+
path_params={"worksheet_id": worksheet_id, "row_id": row_id})
|
|
136
|
+
data = response.get("data") if isinstance(response, dict) else None
|
|
137
|
+
return names_from_json((data or {}).get("discussions"))
|
|
@@ -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 `--
|
|
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**
|
|
@@ -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`,用 `--
|
|
32
|
+
- 单聊 / 群聊不走 `--category`,用 `--account-id <accountId>` 或 `--group-id <groupId>`
|
|
33
33
|
(id 取会话的 `value`)。
|
|
34
34
|
|
|
35
35
|
**3. 拿三元组直接读记录和讨论**
|
|
@@ -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 --
|
|
3436
|
-
"zh-Hans": "列出单聊或群聊中共享的文件。\n\n--
|
|
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 --
|
|
3492
|
-
"zh-Hans": "获取聊天消息历史。\n\n以下选项必须且只能提供一个:\n --
|
|
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` 的别名"
|