python-hwpx-automation 7.3.1__tar.gz → 7.3.3__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.
- {python_hwpx_automation-7.3.1/src/python_hwpx_automation.egg-info → python_hwpx_automation-7.3.3}/PKG-INFO +13 -16
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/README.md +12 -15
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/pyproject.toml +1 -1
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/content.py +18 -2
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/document.py +2 -3
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/transactions.py +15 -3
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/errors.py +54 -1
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/agent_document.py +5 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/read_export.py +14 -10
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/identity.json +10 -10
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/mixed_form.py +3 -1
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/report_parser.py +19 -7
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/_hancom_open_rate.ps1 +27 -5
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/_refresh_hwpx_mac.applescript +4 -1
- python_hwpx_automation-7.3.3/src/hwpx_automation/office/rendering/_render_hwpx.ps1 +148 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/_render_hwpx_mac.applescript +197 -12
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/cli.py +8 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/mac_session.py +12 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/oracle.py +248 -42
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/worker.py +5 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/context.py +49 -3
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/form_fields.py +3 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/package_validation.py +1 -1
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/planning.py +1 -1
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/read_query.py +21 -16
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/save_policy.py +3 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/transactions.py +1 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/runtime.py +26 -3
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/storage.py +116 -10
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/upstream.py +56 -2
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3/src/python_hwpx_automation.egg-info}/PKG-INFO +13 -16
- python_hwpx_automation-7.3.1/src/hwpx_automation/office/rendering/_render_hwpx.ps1 +0 -72
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/LICENSE +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/MANIFEST.in +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/NOTICE +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/setup.cfg +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/__init__.pyi +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/__main__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/agent_document.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/api.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/blind_eval.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/capabilities.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/compat.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/configuration.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/context.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/diff.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/formatting.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/handles.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/locations.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/locator.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/plan.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/resources.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/search.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/txn.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/document_state.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/execution_lock.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/fastmcp_adapter.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/form_fill.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/form_output_models.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/_shared.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/authoring.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/content_edit.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/form_fill.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/layout_style.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/quality_render.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/specialized.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/tracked_changes.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/handlers/workflow.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/hwp_converter.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/hwp_support.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/hwpx_ops.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/identity.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ingest_adapters.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/markdown_plan.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/mcp_cli.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/metadata/tools_meta.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/mutation_models.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/network_policy.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/_batch_publication.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/_batch_verification.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/_text_scope.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/bundle.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/catalog.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/dump.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/mapping.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/model.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/native.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/blueprint/replay.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/catalog.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/cli.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/commands.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/document.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/form_plan.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/model.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/path.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/query.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/agent/story.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/advanced_generators.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/builder/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/builder/core.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/builder/report.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/_support.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/composer.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/harvest.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/plan.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profile.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/body.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/heading.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/info_table.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/application_form/fragments/title.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/application_form/profile.json +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/application_form/template.hwpx +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/body.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/heading.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/home_notice/fragments/title.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/home_notice/profile.json +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/home_notice/template.hwpx +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/body.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/heading.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/info_table.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/official_notice/fragments/title.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/official_notice/profile.json +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/official_notice/template.hwpx +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/body.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/heading.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/info_table.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/report/fragments/title.xml +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/report/profile.json +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/profiles/report/template.hwpx +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/design/validator.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/presets/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/presets/proposal.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/style_profile.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/authoring/template_analyzer.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/charting/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/compliance/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/compliance/official_lint.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/compliance/pii.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/document_ops/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/document_ops/comparison.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/document_ops/mail_merge.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/document_ops/redline.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/evalplan/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/evalplan/runtime.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/exam/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/exam/compose.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/exam/ir.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/exam/measure.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/exam/parser.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/exam/profile.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/classification.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fill_residue.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/apply.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/engine.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/measure.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/policy.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/report.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/seal.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/fit/wordbox.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/guidance.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/quality.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/split_run.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/form_fill/template_formfit.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/house_style/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/house_style/composition.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/house_style/data/bank.json +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/house_style/data/genres.json +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/house_style/gianmun.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/house_style/org_chart.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/quality/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/quality/page_guard.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/__main__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/block_splits.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/detectors.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/diff.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/fixture_corpus.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/page_qa.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/qa_contracts.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/rendering/qa_metrics.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/utilities/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/office/utilities/table_compute.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/_border_fill.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/composition.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/content_layout.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/media.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/memo_style.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/preview_export.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/ops_services/tables.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/preview_output_models.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/public-modules.json +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/py.typed +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/quality.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/quality_generation.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/resources.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/runtime_services.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/server.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/tool_bindings.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/tool_contract.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/utils/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/utils/helpers.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/utils/read_budget.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/visual_qa.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/__init__.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/adapters.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/dispatcher.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/evidence_lineage.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/models.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/policy.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/render_contracts.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/render_metrics.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/render_queue.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/render_security.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/render_transport.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/rendering.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/service.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/state_machine.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workflow/store.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/workspace.py +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/python_hwpx_automation.egg-info/SOURCES.txt +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/python_hwpx_automation.egg-info/dependency_links.txt +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/python_hwpx_automation.egg-info/entry_points.txt +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/python_hwpx_automation.egg-info/requires.txt +0 -0
- {python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/python_hwpx_automation.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-hwpx-automation
|
|
3
|
-
Version: 7.3.
|
|
3
|
+
Version: 7.3.3
|
|
4
4
|
Summary: Task-oriented HWPX document automation for Python, with an optional MCP adapter.
|
|
5
5
|
Author: Kohkyuhyun
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -74,12 +74,10 @@ Dynamic: license-file
|
|
|
74
74
|
|
|
75
75
|
<!-- release-state: release-approved -->
|
|
76
76
|
> [!NOTE]
|
|
77
|
-
> 발행이 승인된 7.3.
|
|
78
|
-
> 공개 트레인: `python-hwpx 6.
|
|
79
|
-
> [발행·설치 영수증](docs/releases/2026-09-22-trustworthy-edit-engine.md)
|
|
77
|
+
> 발행이 승인된 7.3.3 후보 (release-approved; 원격 발행 대기): `python-hwpx 6.6.0 → python-hwpx-automation 7.3.3 → hwpx-plugin 2.4.0` (`5e5c23651f92785a`).
|
|
78
|
+
> 공개 트레인: `python-hwpx 6.6.0 → python-hwpx-automation 7.3.1 → hwpx-plugin 2.4.0`.
|
|
80
79
|
> 공개 좌표는 core·automation PyPI와 plugin GitHub
|
|
81
80
|
> Release·marketplace·실제 marketplace 설치 관찰 후에만 승격합니다.
|
|
82
|
-
> [릴리스 runbook](docs/release-runbook.md)
|
|
83
81
|
|
|
84
82
|
[python-hwpx](https://github.com/airmang/python-hwpx) 엔진 위에서 문서 저작·
|
|
85
83
|
양식 채움·시험지 조판·안전한 에이전트 워크플로를 제공하는 응용 계층입니다.
|
|
@@ -133,7 +131,7 @@ Gemini CLI는 `~/.gemini/settings.json`, Cursor·Windsurf는 각 에디터의 MC
|
|
|
133
131
|
"command": "uvx",
|
|
134
132
|
"args": [
|
|
135
133
|
"--from",
|
|
136
|
-
"python-hwpx-automation[mcp]==7.
|
|
134
|
+
"python-hwpx-automation[mcp]==7.3.1",
|
|
137
135
|
"hwpx-automation-mcp"
|
|
138
136
|
],
|
|
139
137
|
"env": {
|
|
@@ -152,10 +150,10 @@ Gemini CLI는 `~/.gemini/settings.json`, Cursor·Windsurf는 각 에디터의 MC
|
|
|
152
150
|
|
|
153
151
|
> 비-HWPX 문서(PDF/DOCX/XLSX/HTML/TXT)를 `document_to_markdown`으로 읽으려면
|
|
154
152
|
> `pip install "python-hwpx-automation[ingest]"`로 MarkItDown adapter를 함께
|
|
155
|
-
> 설치합니다. 요구 사항: `Python >= 3.10` · `python-hwpx >= 5.0
|
|
153
|
+
> 설치합니다. 요구 사항: `Python >= 3.10` · `python-hwpx >= 6.5.0`.
|
|
156
154
|
|
|
157
|
-
기존 `hwpx-mcp-server` 배포·import·콘솔·설정 키도
|
|
158
|
-
전체 목록과 유지 규칙: [
|
|
155
|
+
기존 `hwpx-mcp-server` 배포·import·콘솔·설정 키도 그대로 동작합니다 —
|
|
156
|
+
전체 목록과 유지 규칙: [호환 표면](docs/compatibility-6x.md)
|
|
159
157
|
|
|
160
158
|
## 한컴으로 PDF 렌더하기
|
|
161
159
|
|
|
@@ -164,7 +162,7 @@ PDF와 쪽 PNG로 렌더합니다. 별도 환경에서 실행하므로 호출하
|
|
|
164
162
|
고정 버전을 건드리지 않습니다.
|
|
165
163
|
|
|
166
164
|
```bash
|
|
167
|
-
uvx --from "python-hwpx-automation[oracle]==7.3.
|
|
165
|
+
uvx --from "python-hwpx-automation[oracle]==7.3.3" \
|
|
168
166
|
hwpx render-pdf in.hwpx out.pdf --png out/page --json
|
|
169
167
|
```
|
|
170
168
|
|
|
@@ -185,7 +183,8 @@ JSON 결과·종료 코드·플랫폼 요구 사항: [render-pdf](docs/render-pd
|
|
|
185
183
|
|
|
186
184
|
## 안전하게 쓰는 법
|
|
187
185
|
|
|
188
|
-
처음부터 모든 도구를 외울 필요는 없습니다.
|
|
186
|
+
처음부터 모든 도구를 외울 필요는 없습니다. 기존 문서 수정은 [조회·대상 확정·보존 저장·검증 안내](docs/existing-edit-navigation.md)를,
|
|
187
|
+
새 문서는 document-plan을 먼저 봅니다. 보통 이렇게 흘러갑니다.
|
|
189
188
|
|
|
190
189
|
1. **읽기** — `get_document_info` → `get_document_outline`/`get_document_text` → `find_text`, `get_table_map`으로 필요한 부분만 파악합니다. (저장하지 않음)
|
|
191
190
|
2. **안전 수정** — `copy_document`로 사본을 만들고, 가장 작은 변경(`search_and_replace`, `set_table_cell_text`, `apply_document_commands`)을 적용한 뒤 다시 읽어 확인하고, 검토가 끝난 사본을 전달합니다.
|
|
@@ -198,7 +197,7 @@ JSON 결과·종료 코드·플랫폼 요구 사항: [render-pdf](docs/render-pd
|
|
|
198
197
|
열림안전을 검사하고, 게이트가 실패하면 아무것도 쓰지 않습니다. capability
|
|
199
198
|
handshake는 core/automation/plugin 버전+해시 skew를 fail-closed로 차단합니다.
|
|
200
199
|
보안 상세: [하드닝 가이드](docs/hardening_guide_ko.md) · 옛 이름과의 호환
|
|
201
|
-
식별자: [
|
|
200
|
+
식별자: [호환 표면](docs/compatibility-6x.md)
|
|
202
201
|
|
|
203
202
|
> **위치 계약** — `paragraph_index`는 본문 직속 문단의 0-based 인덱스입니다. 표 안 문단은 여기 섞지 않고
|
|
204
203
|
> `{"kind":"table_cell_paragraph","table_index":0,"row":0,"col":1,"cell_paragraph_index":0}` 같은 `location`
|
|
@@ -219,10 +218,10 @@ handshake는 core/automation/plugin 버전+해시 skew를 fail-closed로 차단
|
|
|
219
218
|
| `HWPX_AUTOMATION_WORKFLOW_STORE` | durable workflow SQLite 경로. 기존 `HWPX_WORKFLOW_STORE`보다 우선 | 기존 6.x 상태 경로 |
|
|
220
219
|
| `LOG_LEVEL` | 로그 레벨 | `INFO` |
|
|
221
220
|
|
|
222
|
-
동일 suffix의 기존 `HWPX_MCP_*` 키는
|
|
221
|
+
동일 suffix의 기존 `HWPX_MCP_*` 키는 fallback으로 유지되며, 두 키가
|
|
223
222
|
함께 있으면 `HWPX_AUTOMATION_*`이 우선합니다. render·workflow·oracle·plugin
|
|
224
223
|
연동용 보존 키 전체 목록과 workflow DB 경로 규칙은
|
|
225
|
-
[
|
|
224
|
+
[호환 표면](docs/compatibility-6x.md)에 있습니다.
|
|
226
225
|
|
|
227
226
|
경로는 기본적으로 workspace 밖 traversal과 symlink escape를 거부하고, URL 입력은 HTTPS·공개 IP만
|
|
228
227
|
허용합니다. 원자 rename을 제공하지 않는 호스트의 동시성 주의사항은 [하드닝 가이드](docs/hardening_guide_ko.md)를 보세요.
|
|
@@ -253,5 +252,3 @@ python scripts/run_conformance.py run \
|
|
|
253
252
|
## License · Maintainer
|
|
254
253
|
|
|
255
254
|
Apache-2.0 ([LICENSE](LICENSE) · [NOTICE](NOTICE)) — **Kohkyuhyun** [@airmang](https://github.com/airmang) · [kokyuhyun@hotmail.com](mailto:kokyuhyun@hotmail.com)
|
|
256
|
-
|
|
257
|
-
기존 문서 수정은 [조회·대상 확정·보존 저장·검증 안내](docs/existing-edit-navigation.md)를 먼저 확인하세요. 새 문서는 document-plan, 에이전트 연결은 선택 MCP와 호스트 플러그인을 사용합니다.
|
|
@@ -14,12 +14,10 @@
|
|
|
14
14
|
|
|
15
15
|
<!-- release-state: release-approved -->
|
|
16
16
|
> [!NOTE]
|
|
17
|
-
> 발행이 승인된 7.3.
|
|
18
|
-
> 공개 트레인: `python-hwpx 6.
|
|
19
|
-
> [발행·설치 영수증](docs/releases/2026-09-22-trustworthy-edit-engine.md)
|
|
17
|
+
> 발행이 승인된 7.3.3 후보 (release-approved; 원격 발행 대기): `python-hwpx 6.6.0 → python-hwpx-automation 7.3.3 → hwpx-plugin 2.4.0` (`5e5c23651f92785a`).
|
|
18
|
+
> 공개 트레인: `python-hwpx 6.6.0 → python-hwpx-automation 7.3.1 → hwpx-plugin 2.4.0`.
|
|
20
19
|
> 공개 좌표는 core·automation PyPI와 plugin GitHub
|
|
21
20
|
> Release·marketplace·실제 marketplace 설치 관찰 후에만 승격합니다.
|
|
22
|
-
> [릴리스 runbook](docs/release-runbook.md)
|
|
23
21
|
|
|
24
22
|
[python-hwpx](https://github.com/airmang/python-hwpx) 엔진 위에서 문서 저작·
|
|
25
23
|
양식 채움·시험지 조판·안전한 에이전트 워크플로를 제공하는 응용 계층입니다.
|
|
@@ -73,7 +71,7 @@ Gemini CLI는 `~/.gemini/settings.json`, Cursor·Windsurf는 각 에디터의 MC
|
|
|
73
71
|
"command": "uvx",
|
|
74
72
|
"args": [
|
|
75
73
|
"--from",
|
|
76
|
-
"python-hwpx-automation[mcp]==7.
|
|
74
|
+
"python-hwpx-automation[mcp]==7.3.1",
|
|
77
75
|
"hwpx-automation-mcp"
|
|
78
76
|
],
|
|
79
77
|
"env": {
|
|
@@ -92,10 +90,10 @@ Gemini CLI는 `~/.gemini/settings.json`, Cursor·Windsurf는 각 에디터의 MC
|
|
|
92
90
|
|
|
93
91
|
> 비-HWPX 문서(PDF/DOCX/XLSX/HTML/TXT)를 `document_to_markdown`으로 읽으려면
|
|
94
92
|
> `pip install "python-hwpx-automation[ingest]"`로 MarkItDown adapter를 함께
|
|
95
|
-
> 설치합니다. 요구 사항: `Python >= 3.10` · `python-hwpx >= 5.0
|
|
93
|
+
> 설치합니다. 요구 사항: `Python >= 3.10` · `python-hwpx >= 6.5.0`.
|
|
96
94
|
|
|
97
|
-
기존 `hwpx-mcp-server` 배포·import·콘솔·설정 키도
|
|
98
|
-
전체 목록과 유지 규칙: [
|
|
95
|
+
기존 `hwpx-mcp-server` 배포·import·콘솔·설정 키도 그대로 동작합니다 —
|
|
96
|
+
전체 목록과 유지 규칙: [호환 표면](docs/compatibility-6x.md)
|
|
99
97
|
|
|
100
98
|
## 한컴으로 PDF 렌더하기
|
|
101
99
|
|
|
@@ -104,7 +102,7 @@ PDF와 쪽 PNG로 렌더합니다. 별도 환경에서 실행하므로 호출하
|
|
|
104
102
|
고정 버전을 건드리지 않습니다.
|
|
105
103
|
|
|
106
104
|
```bash
|
|
107
|
-
uvx --from "python-hwpx-automation[oracle]==7.3.
|
|
105
|
+
uvx --from "python-hwpx-automation[oracle]==7.3.3" \
|
|
108
106
|
hwpx render-pdf in.hwpx out.pdf --png out/page --json
|
|
109
107
|
```
|
|
110
108
|
|
|
@@ -125,7 +123,8 @@ JSON 결과·종료 코드·플랫폼 요구 사항: [render-pdf](docs/render-pd
|
|
|
125
123
|
|
|
126
124
|
## 안전하게 쓰는 법
|
|
127
125
|
|
|
128
|
-
처음부터 모든 도구를 외울 필요는 없습니다.
|
|
126
|
+
처음부터 모든 도구를 외울 필요는 없습니다. 기존 문서 수정은 [조회·대상 확정·보존 저장·검증 안내](docs/existing-edit-navigation.md)를,
|
|
127
|
+
새 문서는 document-plan을 먼저 봅니다. 보통 이렇게 흘러갑니다.
|
|
129
128
|
|
|
130
129
|
1. **읽기** — `get_document_info` → `get_document_outline`/`get_document_text` → `find_text`, `get_table_map`으로 필요한 부분만 파악합니다. (저장하지 않음)
|
|
131
130
|
2. **안전 수정** — `copy_document`로 사본을 만들고, 가장 작은 변경(`search_and_replace`, `set_table_cell_text`, `apply_document_commands`)을 적용한 뒤 다시 읽어 확인하고, 검토가 끝난 사본을 전달합니다.
|
|
@@ -138,7 +137,7 @@ JSON 결과·종료 코드·플랫폼 요구 사항: [render-pdf](docs/render-pd
|
|
|
138
137
|
열림안전을 검사하고, 게이트가 실패하면 아무것도 쓰지 않습니다. capability
|
|
139
138
|
handshake는 core/automation/plugin 버전+해시 skew를 fail-closed로 차단합니다.
|
|
140
139
|
보안 상세: [하드닝 가이드](docs/hardening_guide_ko.md) · 옛 이름과의 호환
|
|
141
|
-
식별자: [
|
|
140
|
+
식별자: [호환 표면](docs/compatibility-6x.md)
|
|
142
141
|
|
|
143
142
|
> **위치 계약** — `paragraph_index`는 본문 직속 문단의 0-based 인덱스입니다. 표 안 문단은 여기 섞지 않고
|
|
144
143
|
> `{"kind":"table_cell_paragraph","table_index":0,"row":0,"col":1,"cell_paragraph_index":0}` 같은 `location`
|
|
@@ -159,10 +158,10 @@ handshake는 core/automation/plugin 버전+해시 skew를 fail-closed로 차단
|
|
|
159
158
|
| `HWPX_AUTOMATION_WORKFLOW_STORE` | durable workflow SQLite 경로. 기존 `HWPX_WORKFLOW_STORE`보다 우선 | 기존 6.x 상태 경로 |
|
|
160
159
|
| `LOG_LEVEL` | 로그 레벨 | `INFO` |
|
|
161
160
|
|
|
162
|
-
동일 suffix의 기존 `HWPX_MCP_*` 키는
|
|
161
|
+
동일 suffix의 기존 `HWPX_MCP_*` 키는 fallback으로 유지되며, 두 키가
|
|
163
162
|
함께 있으면 `HWPX_AUTOMATION_*`이 우선합니다. render·workflow·oracle·plugin
|
|
164
163
|
연동용 보존 키 전체 목록과 workflow DB 경로 규칙은
|
|
165
|
-
[
|
|
164
|
+
[호환 표면](docs/compatibility-6x.md)에 있습니다.
|
|
166
165
|
|
|
167
166
|
경로는 기본적으로 workspace 밖 traversal과 symlink escape를 거부하고, URL 입력은 HTTPS·공개 IP만
|
|
168
167
|
허용합니다. 원자 rename을 제공하지 않는 호스트의 동시성 주의사항은 [하드닝 가이드](docs/hardening_guide_ko.md)를 보세요.
|
|
@@ -193,5 +192,3 @@ python scripts/run_conformance.py run \
|
|
|
193
192
|
## License · Maintainer
|
|
194
193
|
|
|
195
194
|
Apache-2.0 ([LICENSE](LICENSE) · [NOTICE](NOTICE)) — **Kohkyuhyun** [@airmang](https://github.com/airmang) · [kokyuhyun@hotmail.com](mailto:kokyuhyun@hotmail.com)
|
|
196
|
-
|
|
197
|
-
기존 문서 수정은 [조회·대상 확정·보존 저장·검증 안내](docs/existing-edit-navigation.md)를 먼저 확인하세요. 새 문서는 document-plan, 에이전트 연결은 선택 MCP와 호스트 플러그인을 사용합니다.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-hwpx-automation"
|
|
7
|
-
version = "7.3.
|
|
7
|
+
version = "7.3.3"
|
|
8
8
|
description = "Task-oriented HWPX document automation for Python, with an optional MCP adapter."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Kohkyuhyun" }]
|
{python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/content.py
RENAMED
|
@@ -14,8 +14,15 @@ from uuid import uuid4
|
|
|
14
14
|
from xml.etree import ElementTree as ET
|
|
15
15
|
|
|
16
16
|
from ..compat import patch_python_hwpx
|
|
17
|
-
from ..storage import build_hwpx_open_safety_report
|
|
18
|
-
from ..upstream import
|
|
17
|
+
from ..storage import build_hwpx_open_safety_report, open_local_document
|
|
18
|
+
from ..upstream import (
|
|
19
|
+
HP_NS as _HP_NS,
|
|
20
|
+
HwpxDocument,
|
|
21
|
+
is_hwp5_source,
|
|
22
|
+
is_hwp5_target,
|
|
23
|
+
repair_pathological_text_spacing,
|
|
24
|
+
)
|
|
25
|
+
from .document import save_doc
|
|
19
26
|
from .formatting import resolve_style_id
|
|
20
27
|
from .locations import resolve_paragraph_reference
|
|
21
28
|
|
|
@@ -500,6 +507,15 @@ def copy_document_file(source: str, destination: str = None) -> str:
|
|
|
500
507
|
destination = f"{stem}_copy.{ext}"
|
|
501
508
|
source_path = Path(source)
|
|
502
509
|
destination_path = Path(destination)
|
|
510
|
+
if is_hwp5_source(source_path) != is_hwp5_target(destination_path):
|
|
511
|
+
# The destination extension picks the format, so a copy between .hwp
|
|
512
|
+
# and .hwpx is written through the document model, not byte-copied.
|
|
513
|
+
document = open_local_document(source_path, role="copy source")
|
|
514
|
+
try:
|
|
515
|
+
save_doc(document, str(destination_path))
|
|
516
|
+
finally:
|
|
517
|
+
document.close()
|
|
518
|
+
return str(destination_path)
|
|
503
519
|
if source_path.suffix.lower() != ".hwpx" and destination_path.suffix.lower() != ".hwpx":
|
|
504
520
|
shutil.copy2(source_path, destination_path)
|
|
505
521
|
return str(destination_path)
|
{python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/core/document.py
RENAMED
|
@@ -5,7 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
7
|
from ..configuration import env_value
|
|
8
|
-
from ..storage import LocalDocumentStorage,
|
|
8
|
+
from ..storage import LocalDocumentStorage, open_local_document
|
|
9
9
|
from ..upstream import HwpxDocument, blank_document_template_bytes, open_document
|
|
10
10
|
|
|
11
11
|
|
|
@@ -18,8 +18,7 @@ def _local_storage() -> LocalDocumentStorage:
|
|
|
18
18
|
def open_doc(path: str) -> HwpxDocument:
|
|
19
19
|
if not os.path.exists(path):
|
|
20
20
|
raise FileNotFoundError(f"파일을 찾을 수 없습니다: {path}")
|
|
21
|
-
|
|
22
|
-
return open_document(path)
|
|
21
|
+
return open_local_document(Path(path), role="local HWPX open")
|
|
23
22
|
|
|
24
23
|
|
|
25
24
|
def save_doc(doc: HwpxDocument, path: str, *, quality: Any = None) -> dict[str, Any]:
|
|
@@ -12,8 +12,12 @@ from pathlib import Path
|
|
|
12
12
|
from typing import Any, Iterable
|
|
13
13
|
|
|
14
14
|
from .. import quality as quality_contract
|
|
15
|
-
from ..storage import
|
|
16
|
-
|
|
15
|
+
from ..storage import (
|
|
16
|
+
build_hwpx_verification_report,
|
|
17
|
+
require_hwpx_editor_open_safe,
|
|
18
|
+
require_native_hwp5,
|
|
19
|
+
)
|
|
20
|
+
from ..upstream import HwpxDocument, hwp5_document_bytes, is_hwp5_target, open_document
|
|
17
21
|
|
|
18
22
|
_MAX_SUMMARY_ITEMS = 20
|
|
19
23
|
_MAX_SNIPPET = 80
|
|
@@ -341,9 +345,13 @@ def save_dry_run(
|
|
|
341
345
|
document: HwpxDocument, target: str | Path, *, quality: Any = None
|
|
342
346
|
) -> dict[str, Any]:
|
|
343
347
|
target_path = Path(target)
|
|
348
|
+
hwp_target = is_hwp5_target(target_path)
|
|
349
|
+
if hwp_target:
|
|
350
|
+
require_native_hwp5()
|
|
351
|
+
# The gate checks HWPX parts, so an .hwp target is staged as HWPX.
|
|
344
352
|
fd, tmp_name = tempfile.mkstemp(
|
|
345
353
|
prefix=f".{target_path.stem}.dry-run.",
|
|
346
|
-
suffix=target_path.suffix or ".hwpx",
|
|
354
|
+
suffix=".hwpx" if hwp_target else (target_path.suffix or ".hwpx"),
|
|
347
355
|
dir=str(target_path.parent),
|
|
348
356
|
)
|
|
349
357
|
tmp_path = Path(tmp_name)
|
|
@@ -366,6 +374,10 @@ def save_dry_run(
|
|
|
366
374
|
"dry-run HWPX failed open-safety verification: "
|
|
367
375
|
+ verification["openSafety"]["summary"]
|
|
368
376
|
)
|
|
377
|
+
if hwp_target:
|
|
378
|
+
# Raises Hwp5Error (hwp5-write-unsupported) as the real save would.
|
|
379
|
+
hwp5_document_bytes(document)
|
|
380
|
+
verification["format"] = "hwp"
|
|
369
381
|
diff = semantic_diff(target_path, tmp_path) if target_path.exists() else None
|
|
370
382
|
verification["filePath"] = str(target_path)
|
|
371
383
|
verification["dryRunTempDeleted"] = True
|
|
@@ -73,6 +73,7 @@ DEFAULT_ERROR_SUGGESTIONS: dict[str, str] = {
|
|
|
73
73
|
"EMPTY_MATCH": "찾을 텍스트나 앵커 조건을 실제 문서 내용에 맞게 수정하세요.",
|
|
74
74
|
"HWP_CONVERSION_FAILED": "원본 HWP가 손상되지 않았는지 확인하고 변환 로그의 원인을 기준으로 다시 시도하세요.",
|
|
75
75
|
"HWP_TEXT_EXTRACT_FAILED": "HWP 파일을 다른 뷰어에서 열어 유효성을 확인한 뒤 텍스트 추출을 다시 실행하세요.",
|
|
76
|
+
"HWPX_PACKAGE_REQUIRED": "copy_document로 .hwpx 사본을 만들어 이 도구를 쓰고, .hwp가 필요하면 결과를 copy_document로 .hwp 경로에 복사하세요. search_and_replace·set_table_cell_text 같은 문서 편집 도구는 .hwp를 그대로 편집합니다.",
|
|
76
77
|
"IDEMPOTENT_REPLAY": "이미 적용된 planId입니다. 최신 preview/plan을 새로 만든 뒤 apply를 다시 호출하세요.",
|
|
77
78
|
"MEMO_NOT_FOUND": "list_memos 또는 문서 리소스에서 memoId를 다시 확인한 뒤 호출하세요.",
|
|
78
79
|
"MISSING_NODE": "대상 섹션, 문단, 표, 셀이 아직 존재하는지 조회한 뒤 새 앵커로 다시 실행하세요.",
|
|
@@ -81,7 +82,10 @@ DEFAULT_ERROR_SUGGESTIONS: dict[str, str] = {
|
|
|
81
82
|
"PIPELINE_ERROR": "details.pipelineCode와 hint를 확인한 뒤 preview부터 다시 생성하세요.",
|
|
82
83
|
"PLAN_RECORD_MISSING": "preview_edit 또는 plan_edit으로 planId를 새로 발급받은 뒤 apply를 다시 호출하세요.",
|
|
83
84
|
"PREVIEW_REQUIRED": "preview_edit으로 변경 내용을 확인한 뒤 반환된 planId로 apply_edit을 호출하세요.",
|
|
84
|
-
"
|
|
85
|
+
"HWP_DOCUMENT_UNREADABLE": "한/글에서 문서를 열어 다시 저장한 뒤 사용하세요. details.hwp5Code가 원인입니다.",
|
|
86
|
+
"HWP_ENCRYPTED_DOCUMENT": "한/글에서 문서 암호·배포용 보호를 풀고 다시 저장한 뒤 사용하세요. DRM 문서는 열 수 없습니다.",
|
|
87
|
+
"HWP_WRITE_UNSUPPORTED": "HWP 5.0으로 쓸 수 없는 내용이 있습니다. 출력 경로를 .hwpx로 지정해 저장하세요.",
|
|
88
|
+
"READ_ONLY_HWP_DOCUMENT": "python-hwpx 6.6.0 이상을 설치하면 .hwp 문서를 그대로 열고 편집·저장할 수 있습니다.",
|
|
85
89
|
"RENDER_PREVIEW_INVALID_MODE": "mode는 'pages' 또는 'long'으로 지정한 뒤 다시 실행하세요.",
|
|
86
90
|
"RENDER_PREVIEW_INVALID_SCREENSHOT_MODE": "screenshot은 'auto', 'require', 'off' 중 하나로 지정하세요.",
|
|
87
91
|
"RENDER_PREVIEW_UNAVAILABLE": "matching python-hwpx 버전을 설치하고 MCP 서버를 새로 시작한 뒤 다시 실행하세요.",
|
|
@@ -175,3 +179,52 @@ def build_error_payload(
|
|
|
175
179
|
suggestion=suggestion
|
|
176
180
|
or suggestion_for_error(code, details=details, hint=hint),
|
|
177
181
|
).model_dump(exclude_none=True, by_alias=True)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class HwpDocumentError(RuntimeError):
|
|
185
|
+
"""An ``.hwp`` request the installed engine cannot carry out."""
|
|
186
|
+
|
|
187
|
+
def __init__(
|
|
188
|
+
self, message: str, *, code: str, details: Optional[Dict[str, Any]] = None
|
|
189
|
+
) -> None:
|
|
190
|
+
super().__init__(message)
|
|
191
|
+
self.code = code
|
|
192
|
+
self.message = message
|
|
193
|
+
self.details = details
|
|
194
|
+
|
|
195
|
+
def to_payload(self) -> Dict[str, Any]:
|
|
196
|
+
return build_error_payload(
|
|
197
|
+
code=self.code, message=self.message, details=self.details
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
_HWP5_ENCRYPTED_CODES = frozenset({"hwp5-password", "hwp5-distribution", "hwp5-drm"})
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def hwp5_error_payload(exc: BaseException) -> Optional[Dict[str, Any]]:
|
|
205
|
+
"""The MCP error for python-hwpx's ``Hwp5Error``; None for any other exception.
|
|
206
|
+
|
|
207
|
+
Matched by its ``hwp5-*`` code so this module needs no core import.
|
|
208
|
+
"""
|
|
209
|
+
|
|
210
|
+
hwp5_code = getattr(exc, "code", None)
|
|
211
|
+
if not isinstance(hwp5_code, str) or not hwp5_code.startswith("hwp5-"):
|
|
212
|
+
return None
|
|
213
|
+
details = {"hwp5Code": hwp5_code}
|
|
214
|
+
if hwp5_code == "hwp5-write-unsupported":
|
|
215
|
+
return build_error_payload(
|
|
216
|
+
code="HWP_WRITE_UNSUPPORTED",
|
|
217
|
+
message="문서에 HWP 5.0(.hwp)으로 쓸 수 없는 내용이 있어 아무것도 저장하지 않았습니다.",
|
|
218
|
+
details=details,
|
|
219
|
+
)
|
|
220
|
+
if hwp5_code in _HWP5_ENCRYPTED_CODES:
|
|
221
|
+
return build_error_payload(
|
|
222
|
+
code="HWP_ENCRYPTED_DOCUMENT",
|
|
223
|
+
message="암호·배포용·DRM으로 보호된 HWP 문서는 열 수 없습니다.",
|
|
224
|
+
details=details,
|
|
225
|
+
)
|
|
226
|
+
return build_error_payload(
|
|
227
|
+
code="HWP_DOCUMENT_UNREADABLE",
|
|
228
|
+
message="HWP 5.0(.hwp) 문서를 읽을 수 없습니다.",
|
|
229
|
+
details=details,
|
|
230
|
+
)
|
|
@@ -9,6 +9,8 @@ from typing import Any
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
from ..document_state import document_state_payload
|
|
12
|
+
from ..errors import HwpDocumentError
|
|
13
|
+
from ..storage import require_hwpx_package
|
|
12
14
|
from ..agent_document import (
|
|
13
15
|
AgentChildLimit,
|
|
14
16
|
AgentCommandList,
|
|
@@ -100,6 +102,7 @@ def apply_document_commands(
|
|
|
100
102
|
try:
|
|
101
103
|
resolved_input = resolve_path(filename)
|
|
102
104
|
resolved_output = resolve_path(output)
|
|
105
|
+
require_hwpx_package(resolved_input, output=resolved_output)
|
|
103
106
|
quality_contract.assert_write_capability()
|
|
104
107
|
store = ScopedIdempotencyStore(
|
|
105
108
|
RUNTIME_SERVICES.idempotency_cache,
|
|
@@ -132,6 +135,8 @@ def apply_document_commands(
|
|
|
132
135
|
if Path(state_path).exists():
|
|
133
136
|
payload.update(document_state_payload(state_path))
|
|
134
137
|
return payload
|
|
138
|
+
except HwpDocumentError:
|
|
139
|
+
raise
|
|
135
140
|
except Exception as exc:
|
|
136
141
|
return agent_batch_error_payload(
|
|
137
142
|
exc,
|
|
@@ -35,6 +35,7 @@ from ..office.compliance import DEFAULT_POLICY, mask_pii
|
|
|
35
35
|
from ..runtime_services import RUNTIME_SERVICES
|
|
36
36
|
from ..upstream import (
|
|
37
37
|
HP_NS,
|
|
38
|
+
hwp5_conversion_report,
|
|
38
39
|
open_document,
|
|
39
40
|
)
|
|
40
41
|
from ..utils.helpers import default_max_chars, resolve_path, truncate_response
|
|
@@ -777,16 +778,19 @@ def get_document_info(filename: str) -> dict:
|
|
|
777
778
|
path = resolve_path(filename)
|
|
778
779
|
doc = open_doc(path)
|
|
779
780
|
file_size = Path(path).stat().st_size
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
781
|
+
info: dict[str, Any] = {
|
|
782
|
+
"filename": filename,
|
|
783
|
+
"sections": len(doc.sections),
|
|
784
|
+
"paragraphs": _paragraph_count(doc),
|
|
785
|
+
"tables": _table_count(doc),
|
|
786
|
+
"file_size": str(file_size),
|
|
787
|
+
}
|
|
788
|
+
conversion = hwp5_conversion_report(doc)
|
|
789
|
+
if conversion is not None:
|
|
790
|
+
# An .hwp is edited through the document model; this is what it left out.
|
|
791
|
+
info["format"] = "hwp"
|
|
792
|
+
info["hwpConversion"] = conversion
|
|
793
|
+
return _with_document_state(info, path)
|
|
790
794
|
|
|
791
795
|
|
|
792
796
|
def get_document_text(
|
{python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/identity.json
RENAMED
|
@@ -5,27 +5,27 @@
|
|
|
5
5
|
"releaseState": {
|
|
6
6
|
"status": "release-approved",
|
|
7
7
|
"candidate": {
|
|
8
|
-
"pythonHwpx": "6.
|
|
8
|
+
"pythonHwpx": "6.6.0",
|
|
9
9
|
"canonicalDistribution": "python-hwpx-automation",
|
|
10
|
-
"canonicalAutomation": "7.3.
|
|
10
|
+
"canonicalAutomation": "7.3.3",
|
|
11
11
|
"compatibilityDistribution": "hwpx-mcp-server",
|
|
12
|
-
"compatibility": "7.3.
|
|
13
|
-
"plugin": "2.
|
|
12
|
+
"compatibility": "7.3.3",
|
|
13
|
+
"plugin": "2.4.0",
|
|
14
14
|
"contractHash": "5e5c23651f92785a"
|
|
15
15
|
},
|
|
16
16
|
"currentPublic": {
|
|
17
|
-
"pythonHwpx": "6.
|
|
17
|
+
"pythonHwpx": "6.6.0",
|
|
18
18
|
"primaryDistribution": "python-hwpx-automation",
|
|
19
|
-
"primaryApplication": "7.
|
|
20
|
-
"plugin": "2.
|
|
19
|
+
"primaryApplication": "7.3.1",
|
|
20
|
+
"plugin": "2.4.0",
|
|
21
21
|
"contractHash": "5e5c23651f92785a"
|
|
22
22
|
},
|
|
23
23
|
"promotionGate": "Three states are mandatory: unreleased-candidate while auditing; release-approved only after separate owner approval and while currentPublic still names the previously observed coherent stack; released only in a follow-up commit after remote truth is observed for core, canonical automation, the compatibility distribution, the plugin GitHub release, the marketplace entry, and a real marketplace install. The automation tag workflow publishes only release-approved, leaves currentPublic unchanged, and hands an attached receipt to plugin publication.",
|
|
24
24
|
"previousPublic": {
|
|
25
|
-
"pythonHwpx": "6.
|
|
25
|
+
"pythonHwpx": "6.6.0",
|
|
26
26
|
"primaryDistribution": "python-hwpx-automation",
|
|
27
|
-
"primaryApplication": "7.
|
|
28
|
-
"plugin": "2.
|
|
27
|
+
"primaryApplication": "7.3.1",
|
|
28
|
+
"plugin": "2.4.0",
|
|
29
29
|
"contractHash": "5e5c23651f92785a"
|
|
30
30
|
},
|
|
31
31
|
"publicationEvidence": null
|
{python_hwpx_automation-7.3.1 → python_hwpx_automation-7.3.3}/src/hwpx_automation/mixed_form.py
RENAMED
|
@@ -41,7 +41,7 @@ from pydantic import (
|
|
|
41
41
|
from .execution_lock import PUBLIC_MUTATION_LOCK
|
|
42
42
|
from .office.agent._batch_publication import GuardedSavePipeline
|
|
43
43
|
from .office.rendering import resolve_hancom_backend
|
|
44
|
-
from .storage import build_hwpx_open_safety_report
|
|
44
|
+
from .storage import build_hwpx_open_safety_report, require_hwpx_package
|
|
45
45
|
from .utils.helpers import resolve_path
|
|
46
46
|
from .workspace import (
|
|
47
47
|
WorkspaceMissingParentGuard,
|
|
@@ -1374,6 +1374,7 @@ def analyze_mixed_form_plan(
|
|
|
1374
1374
|
|
|
1375
1375
|
request = _authorize_public_plan(_payload(plan, apply=False))
|
|
1376
1376
|
source = Path(request["source"])
|
|
1377
|
+
require_hwpx_package(source, output=request["output"])
|
|
1377
1378
|
source_snapshot = _capture_path_snapshot(source)
|
|
1378
1379
|
if source_snapshot.data is None:
|
|
1379
1380
|
raise FileNotFoundError(source)
|
|
@@ -1494,6 +1495,7 @@ def _apply_canonical_mixed_form_plan_locked(
|
|
|
1494
1495
|
|
|
1495
1496
|
compiled = validate_mixed_form_plan(compiled).to_dict()
|
|
1496
1497
|
source, output = _authorize_compiled_plan(compiled)
|
|
1498
|
+
require_hwpx_package(source, output=output)
|
|
1497
1499
|
source_snapshot = _capture_path_snapshot(source)
|
|
1498
1500
|
if source_snapshot.data is None: # pragma: no cover - compiled plan invariant
|
|
1499
1501
|
raise FileNotFoundError(source)
|
|
@@ -85,14 +85,9 @@ def parse_government_report_text(text: str, *, title: str = "") -> dict[str, Any
|
|
|
85
85
|
flush_bullets()
|
|
86
86
|
flush_table()
|
|
87
87
|
|
|
88
|
-
if not blocks:
|
|
89
|
-
fallback = normalize_cell_text(title) or "본문"
|
|
90
|
-
blocks.append({"type": "paragraph", "text": fallback})
|
|
91
|
-
|
|
92
|
-
metadata: dict[str, str] = {}
|
|
93
88
|
normalized_title = normalize_cell_text(title)
|
|
94
|
-
if normalized_title
|
|
95
|
-
|
|
89
|
+
metadata = {"title": normalized_title} if normalized_title else {}
|
|
90
|
+
blocks = _with_title_block(blocks, normalized_title) or [{"type": "paragraph", "text": "본문"}]
|
|
96
91
|
|
|
97
92
|
return {
|
|
98
93
|
"schemaVersion": DOCUMENT_PLAN_V2_SCHEMA_VERSION,
|
|
@@ -102,6 +97,23 @@ def parse_government_report_text(text: str, *, title: str = "") -> dict[str, Any
|
|
|
102
97
|
}
|
|
103
98
|
|
|
104
99
|
|
|
100
|
+
def _with_title_block(blocks: list[dict[str, Any]], title: str) -> list[dict[str, Any]]:
|
|
101
|
+
"""Put *title* at the top of the body as a centred bold paragraph.
|
|
102
|
+
|
|
103
|
+
The plan title and metadata go to the document properties, not the body, so
|
|
104
|
+
a report shows its title only through a body block. A first line that
|
|
105
|
+
already is the title becomes that block instead of a copy.
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
if not title:
|
|
109
|
+
return blocks
|
|
110
|
+
rest = blocks
|
|
111
|
+
if rest and rest[0].get("type") in {"paragraph", "heading"} and rest[0].get("text") == title:
|
|
112
|
+
rest = rest[1:]
|
|
113
|
+
title_block = {"type": "paragraph", "align": "center", "runs": [{"text": title, "bold": True}]}
|
|
114
|
+
return [title_block, *rest]
|
|
115
|
+
|
|
116
|
+
|
|
105
117
|
def _parse_heading(line: str) -> tuple[int, str] | None:
|
|
106
118
|
markdown_match = _MARKDOWN_HEADING_RE.match(line)
|
|
107
119
|
if markdown_match:
|
|
@@ -124,13 +124,35 @@ function Copy-ToTrustedTemp {
|
|
|
124
124
|
return @{ Directory = $dir; Path = $target }
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
function
|
|
128
|
-
|
|
127
|
+
function Register-FilePathCheck {
|
|
128
|
+
# True when Hancom accepted a file-path check module. The module name is a
|
|
129
|
+
# value name under HKCU\SOFTWARE\HNC\HwpAutomation\Modules:
|
|
130
|
+
# HWPX_HANCOM_SECURITY_MODULE first, then Hancom's example name, then every
|
|
131
|
+
# other value registered there. The module type is always "FilePathCheckDLL".
|
|
132
|
+
param($Hwp)
|
|
133
|
+
$names = New-Object System.Collections.Generic.List[string]
|
|
134
|
+
if ($env:HWPX_HANCOM_SECURITY_MODULE) { $names.Add([string]$env:HWPX_HANCOM_SECURITY_MODULE) }
|
|
135
|
+
if (-not $names.Contains("FilePathCheckerModuleExample")) { $names.Add("FilePathCheckerModuleExample") }
|
|
129
136
|
try {
|
|
130
|
-
$
|
|
131
|
-
|
|
132
|
-
|
|
137
|
+
$key = Get-Item -LiteralPath "HKCU:\SOFTWARE\HNC\HwpAutomation\Modules" -ErrorAction Stop
|
|
138
|
+
foreach ($name in $key.GetValueNames()) {
|
|
139
|
+
if ($name -and -not $names.Contains($name)) { $names.Add($name) }
|
|
140
|
+
}
|
|
141
|
+
} catch {}
|
|
142
|
+
foreach ($name in $names) {
|
|
143
|
+
try {
|
|
144
|
+
if ([bool]$Hwp.RegisterModule("FilePathCheckDLL", $name)) { return $true }
|
|
145
|
+
} catch {}
|
|
133
146
|
}
|
|
147
|
+
return $false
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function New-HwpObject {
|
|
151
|
+
$hwp = New-Object -ComObject "HWPFrame.HwpObject"
|
|
152
|
+
# Inputs are opened from a copy in %TEMP% (Copy-ToTrustedTemp), which Hancom
|
|
153
|
+
# opens without its access-approval prompt. A registered file-path check
|
|
154
|
+
# module is used as well when there is one.
|
|
155
|
+
$null = Register-FilePathCheck $hwp
|
|
134
156
|
# FR-002a: suppress modal dialogs. The negative controls (FR-005) prove the
|
|
135
157
|
# suppressed default action is NOT silent auto-repair.
|
|
136
158
|
try { $null = $hwp.SetMessageBoxMode($MESSAGE_BOX_MODE) } catch {
|
|
@@ -98,7 +98,10 @@ end windowNames
|
|
|
98
98
|
|
|
99
99
|
on listContains(theList, theValue)
|
|
100
100
|
repeat with x in theList
|
|
101
|
-
|
|
101
|
+
-- a window without a title (missing value) cannot become a string
|
|
102
|
+
try
|
|
103
|
+
if (x as string) is theValue then return true
|
|
104
|
+
end try
|
|
102
105
|
end repeat
|
|
103
106
|
return false
|
|
104
107
|
end listContains
|