python-hwpx-automation 6.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. hwpx_automation/__init__.py +61 -0
  2. hwpx_automation/__init__.pyi +27 -0
  3. hwpx_automation/__main__.py +8 -0
  4. hwpx_automation/agent_document.py +392 -0
  5. hwpx_automation/api.py +136 -0
  6. hwpx_automation/blind_eval.py +407 -0
  7. hwpx_automation/capabilities.py +110 -0
  8. hwpx_automation/compat.py +48 -0
  9. hwpx_automation/configuration.py +60 -0
  10. hwpx_automation/core/__init__.py +2 -0
  11. hwpx_automation/core/content.py +762 -0
  12. hwpx_automation/core/context.py +111 -0
  13. hwpx_automation/core/diff.py +53 -0
  14. hwpx_automation/core/document.py +37 -0
  15. hwpx_automation/core/formatting.py +513 -0
  16. hwpx_automation/core/handles.py +24 -0
  17. hwpx_automation/core/locations.py +205 -0
  18. hwpx_automation/core/locator.py +162 -0
  19. hwpx_automation/core/plan.py +680 -0
  20. hwpx_automation/core/resources.py +42 -0
  21. hwpx_automation/core/search.py +296 -0
  22. hwpx_automation/core/transactions.py +434 -0
  23. hwpx_automation/core/txn.py +48 -0
  24. hwpx_automation/document_state.py +95 -0
  25. hwpx_automation/errors.py +174 -0
  26. hwpx_automation/execution_lock.py +15 -0
  27. hwpx_automation/fastmcp_adapter.py +672 -0
  28. hwpx_automation/form_fill.py +1177 -0
  29. hwpx_automation/form_output_models.py +223 -0
  30. hwpx_automation/handlers/__init__.py +2 -0
  31. hwpx_automation/handlers/_shared.py +377 -0
  32. hwpx_automation/handlers/agent_document.py +257 -0
  33. hwpx_automation/handlers/authoring.py +750 -0
  34. hwpx_automation/handlers/content_edit.py +1078 -0
  35. hwpx_automation/handlers/form_fill.py +607 -0
  36. hwpx_automation/handlers/layout_style.py +660 -0
  37. hwpx_automation/handlers/quality_render.py +566 -0
  38. hwpx_automation/handlers/read_export.py +1295 -0
  39. hwpx_automation/handlers/specialized.py +624 -0
  40. hwpx_automation/handlers/tracked_changes.py +589 -0
  41. hwpx_automation/handlers/workflow.py +105 -0
  42. hwpx_automation/hwp_converter.py +227 -0
  43. hwpx_automation/hwp_support.py +94 -0
  44. hwpx_automation/hwpx_ops.py +1439 -0
  45. hwpx_automation/identity.json +263 -0
  46. hwpx_automation/identity.py +18 -0
  47. hwpx_automation/ingest_adapters.py +85 -0
  48. hwpx_automation/markdown_plan.py +216 -0
  49. hwpx_automation/mcp_cli.py +29 -0
  50. hwpx_automation/metadata/tools_meta.py +40 -0
  51. hwpx_automation/mixed_form.py +3007 -0
  52. hwpx_automation/mutation_models.py +401 -0
  53. hwpx_automation/network_policy.py +232 -0
  54. hwpx_automation/office/__init__.py +14 -0
  55. hwpx_automation/office/agent/__init__.py +125 -0
  56. hwpx_automation/office/agent/_batch_verification.py +383 -0
  57. hwpx_automation/office/agent/blueprint/__init__.py +58 -0
  58. hwpx_automation/office/agent/blueprint/bundle.py +282 -0
  59. hwpx_automation/office/agent/blueprint/catalog.py +136 -0
  60. hwpx_automation/office/agent/blueprint/dump.py +520 -0
  61. hwpx_automation/office/agent/blueprint/mapping.py +312 -0
  62. hwpx_automation/office/agent/blueprint/model.py +722 -0
  63. hwpx_automation/office/agent/blueprint/native.py +621 -0
  64. hwpx_automation/office/agent/blueprint/replay.py +622 -0
  65. hwpx_automation/office/agent/catalog.py +252 -0
  66. hwpx_automation/office/agent/cli.py +647 -0
  67. hwpx_automation/office/agent/commands.py +1383 -0
  68. hwpx_automation/office/agent/document.py +801 -0
  69. hwpx_automation/office/agent/form_plan.py +1760 -0
  70. hwpx_automation/office/agent/model.py +808 -0
  71. hwpx_automation/office/agent/path.py +155 -0
  72. hwpx_automation/office/agent/query.py +230 -0
  73. hwpx_automation/office/agent/story.py +207 -0
  74. hwpx_automation/office/authoring/__init__.py +3542 -0
  75. hwpx_automation/office/authoring/advanced_generators.py +154 -0
  76. hwpx_automation/office/authoring/builder/__init__.py +52 -0
  77. hwpx_automation/office/authoring/builder/core.py +996 -0
  78. hwpx_automation/office/authoring/builder/report.py +195 -0
  79. hwpx_automation/office/authoring/design/__init__.py +30 -0
  80. hwpx_automation/office/authoring/design/_support.py +144 -0
  81. hwpx_automation/office/authoring/design/composer.py +282 -0
  82. hwpx_automation/office/authoring/design/harvest.py +305 -0
  83. hwpx_automation/office/authoring/design/plan.py +69 -0
  84. hwpx_automation/office/authoring/design/profile.py +88 -0
  85. hwpx_automation/office/authoring/design/profiles/application_form/fragments/body.xml +1 -0
  86. hwpx_automation/office/authoring/design/profiles/application_form/fragments/heading.xml +1 -0
  87. hwpx_automation/office/authoring/design/profiles/application_form/fragments/info_table.xml +1 -0
  88. hwpx_automation/office/authoring/design/profiles/application_form/fragments/title.xml +1 -0
  89. hwpx_automation/office/authoring/design/profiles/application_form/profile.json +25 -0
  90. hwpx_automation/office/authoring/design/profiles/application_form/template.hwpx +0 -0
  91. hwpx_automation/office/authoring/design/profiles/home_notice/fragments/body.xml +1 -0
  92. hwpx_automation/office/authoring/design/profiles/home_notice/fragments/heading.xml +1 -0
  93. hwpx_automation/office/authoring/design/profiles/home_notice/fragments/title.xml +1 -0
  94. hwpx_automation/office/authoring/design/profiles/home_notice/profile.json +24 -0
  95. hwpx_automation/office/authoring/design/profiles/home_notice/template.hwpx +0 -0
  96. hwpx_automation/office/authoring/design/profiles/official_notice/fragments/body.xml +1 -0
  97. hwpx_automation/office/authoring/design/profiles/official_notice/fragments/heading.xml +1 -0
  98. hwpx_automation/office/authoring/design/profiles/official_notice/fragments/info_table.xml +1 -0
  99. hwpx_automation/office/authoring/design/profiles/official_notice/fragments/title.xml +1 -0
  100. hwpx_automation/office/authoring/design/profiles/official_notice/profile.json +25 -0
  101. hwpx_automation/office/authoring/design/profiles/official_notice/template.hwpx +0 -0
  102. hwpx_automation/office/authoring/design/profiles/report/fragments/body.xml +1 -0
  103. hwpx_automation/office/authoring/design/profiles/report/fragments/heading.xml +1 -0
  104. hwpx_automation/office/authoring/design/profiles/report/fragments/info_table.xml +1 -0
  105. hwpx_automation/office/authoring/design/profiles/report/fragments/title.xml +1 -0
  106. hwpx_automation/office/authoring/design/profiles/report/profile.json +25 -0
  107. hwpx_automation/office/authoring/design/profiles/report/template.hwpx +0 -0
  108. hwpx_automation/office/authoring/design/validator.py +107 -0
  109. hwpx_automation/office/authoring/presets/__init__.py +22 -0
  110. hwpx_automation/office/authoring/presets/proposal.py +538 -0
  111. hwpx_automation/office/authoring/report_parser.py +141 -0
  112. hwpx_automation/office/authoring/style_profile.py +437 -0
  113. hwpx_automation/office/authoring/template_analyzer.py +657 -0
  114. hwpx_automation/office/compliance/__init__.py +38 -0
  115. hwpx_automation/office/compliance/official_lint.py +478 -0
  116. hwpx_automation/office/compliance/pii.py +388 -0
  117. hwpx_automation/office/document_ops/__init__.py +13 -0
  118. hwpx_automation/office/document_ops/comparison.py +62 -0
  119. hwpx_automation/office/document_ops/mail_merge.py +73 -0
  120. hwpx_automation/office/document_ops/redline.py +35 -0
  121. hwpx_automation/office/evalplan/__init__.py +36 -0
  122. hwpx_automation/office/evalplan/runtime.py +2762 -0
  123. hwpx_automation/office/exam/__init__.py +44 -0
  124. hwpx_automation/office/exam/compose.py +282 -0
  125. hwpx_automation/office/exam/ir.py +44 -0
  126. hwpx_automation/office/exam/measure.py +163 -0
  127. hwpx_automation/office/exam/parser.py +150 -0
  128. hwpx_automation/office/exam/profile.py +123 -0
  129. hwpx_automation/office/form_fill/__init__.py +66 -0
  130. hwpx_automation/office/form_fill/classification.py +108 -0
  131. hwpx_automation/office/form_fill/fill_residue.py +242 -0
  132. hwpx_automation/office/form_fill/fit/__init__.py +36 -0
  133. hwpx_automation/office/form_fill/fit/apply.py +24 -0
  134. hwpx_automation/office/form_fill/fit/engine.py +24 -0
  135. hwpx_automation/office/form_fill/fit/measure.py +50 -0
  136. hwpx_automation/office/form_fill/fit/policy.py +28 -0
  137. hwpx_automation/office/form_fill/fit/report.py +28 -0
  138. hwpx_automation/office/form_fill/fit/seal.py +457 -0
  139. hwpx_automation/office/form_fill/fit/wordbox.py +1343 -0
  140. hwpx_automation/office/form_fill/guidance.py +704 -0
  141. hwpx_automation/office/form_fill/quality.py +961 -0
  142. hwpx_automation/office/form_fill/split_run.py +333 -0
  143. hwpx_automation/office/form_fill/template_formfit.py +656 -0
  144. hwpx_automation/office/house_style/__init__.py +196 -0
  145. hwpx_automation/office/house_style/composition.py +68 -0
  146. hwpx_automation/office/house_style/data/bank.json +625 -0
  147. hwpx_automation/office/house_style/data/genres.json +43 -0
  148. hwpx_automation/office/quality/__init__.py +14 -0
  149. hwpx_automation/office/quality/page_guard.py +277 -0
  150. hwpx_automation/office/rendering/__init__.py +145 -0
  151. hwpx_automation/office/rendering/_hancom_open_rate.ps1 +374 -0
  152. hwpx_automation/office/rendering/_refresh_hwpx_mac.applescript +162 -0
  153. hwpx_automation/office/rendering/_render_hwpx.ps1 +72 -0
  154. hwpx_automation/office/rendering/_render_hwpx_mac.applescript +249 -0
  155. hwpx_automation/office/rendering/block_splits.py +76 -0
  156. hwpx_automation/office/rendering/detectors.py +151 -0
  157. hwpx_automation/office/rendering/diff.py +153 -0
  158. hwpx_automation/office/rendering/fixture_corpus.py +215 -0
  159. hwpx_automation/office/rendering/oracle.py +909 -0
  160. hwpx_automation/office/rendering/page_qa.py +245 -0
  161. hwpx_automation/office/rendering/qa_contracts.py +293 -0
  162. hwpx_automation/office/rendering/qa_metrics.py +241 -0
  163. hwpx_automation/office/rendering/worker.py +290 -0
  164. hwpx_automation/office/utilities/__init__.py +12 -0
  165. hwpx_automation/office/utilities/table_compute.py +477 -0
  166. hwpx_automation/ops_services/__init__.py +1 -0
  167. hwpx_automation/ops_services/_border_fill.py +283 -0
  168. hwpx_automation/ops_services/composition.py +55 -0
  169. hwpx_automation/ops_services/content_layout.py +322 -0
  170. hwpx_automation/ops_services/context.py +213 -0
  171. hwpx_automation/ops_services/form_fields.py +557 -0
  172. hwpx_automation/ops_services/media.py +178 -0
  173. hwpx_automation/ops_services/memo_style.py +477 -0
  174. hwpx_automation/ops_services/package_validation.py +166 -0
  175. hwpx_automation/ops_services/planning.py +201 -0
  176. hwpx_automation/ops_services/preview_export.py +585 -0
  177. hwpx_automation/ops_services/read_query.py +601 -0
  178. hwpx_automation/ops_services/save_policy.py +604 -0
  179. hwpx_automation/ops_services/tables.py +539 -0
  180. hwpx_automation/ops_services/transactions.py +616 -0
  181. hwpx_automation/preview_output_models.py +69 -0
  182. hwpx_automation/public-modules.json +206 -0
  183. hwpx_automation/py.typed +1 -0
  184. hwpx_automation/quality.py +351 -0
  185. hwpx_automation/quality_generation.py +725 -0
  186. hwpx_automation/runtime.py +321 -0
  187. hwpx_automation/runtime_services.py +100 -0
  188. hwpx_automation/server.py +259 -0
  189. hwpx_automation/storage.py +747 -0
  190. hwpx_automation/tool_bindings.py +170 -0
  191. hwpx_automation/tool_contract.py +982 -0
  192. hwpx_automation/upstream.py +755 -0
  193. hwpx_automation/utils/__init__.py +2 -0
  194. hwpx_automation/utils/helpers.py +29 -0
  195. hwpx_automation/visual_qa.py +667 -0
  196. hwpx_automation/workflow/__init__.py +55 -0
  197. hwpx_automation/workflow/adapters.py +482 -0
  198. hwpx_automation/workflow/dispatcher.py +213 -0
  199. hwpx_automation/workflow/models.py +243 -0
  200. hwpx_automation/workflow/policy.py +198 -0
  201. hwpx_automation/workflow/render_contracts.py +173 -0
  202. hwpx_automation/workflow/render_metrics.py +196 -0
  203. hwpx_automation/workflow/render_queue.py +482 -0
  204. hwpx_automation/workflow/render_security.py +172 -0
  205. hwpx_automation/workflow/render_transport.py +369 -0
  206. hwpx_automation/workflow/rendering.py +206 -0
  207. hwpx_automation/workflow/service.py +758 -0
  208. hwpx_automation/workflow/state_machine.py +65 -0
  209. hwpx_automation/workflow/store.py +747 -0
  210. hwpx_automation/workspace.py +1694 -0
  211. python_hwpx_automation-6.0.3.dist-info/METADATA +279 -0
  212. python_hwpx_automation-6.0.3.dist-info/RECORD +217 -0
  213. python_hwpx_automation-6.0.3.dist-info/WHEEL +5 -0
  214. python_hwpx_automation-6.0.3.dist-info/entry_points.txt +3 -0
  215. python_hwpx_automation-6.0.3.dist-info/licenses/LICENSE +178 -0
  216. python_hwpx_automation-6.0.3.dist-info/licenses/NOTICE +14 -0
  217. python_hwpx_automation-6.0.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,252 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Single-source catalog and help generation for the agent document facade."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import hashlib
7
+ import json
8
+ from copy import deepcopy
9
+ from typing import Any
10
+
11
+ from .model import (
12
+ AGENT_BATCH_SCHEMA,
13
+ AGENT_CATALOG_SCHEMA,
14
+ MAX_COMMANDS,
15
+ AgentContractError,
16
+ NODE_KINDS,
17
+ NODE_PROPERTY_CATALOG_V1,
18
+ QUALITY_KEYS,
19
+ QUALITY_MODES,
20
+ REVISION_PATTERN,
21
+ VERIFICATION_REQUIREMENTS,
22
+ agent_contract_manifest,
23
+ )
24
+
25
+
26
+ def agent_catalog() -> dict[str, Any]:
27
+ """Return a detached deterministic catalog shared by nodes, CLI, and MCP."""
28
+
29
+ manifest = agent_contract_manifest()
30
+ manifest["commands"] = {
31
+ "set": {"required": ["commandId", "op", "path", "properties"]},
32
+ "add": {
33
+ "required": ["commandId", "op", "parent", "kind", "properties"],
34
+ "optional": ["position"],
35
+ },
36
+ "remove": {"required": ["commandId", "op", "path"]},
37
+ "move": {
38
+ "required": ["commandId", "op", "path", "parent"],
39
+ "optional": ["position"],
40
+ },
41
+ "copy": {
42
+ "required": ["commandId", "op", "path", "parent"],
43
+ "optional": ["position"],
44
+ },
45
+ }
46
+ manifest["query"] = {
47
+ "examples": [
48
+ 'paragraph[style="개요 1"]:contains("평가")',
49
+ 'section > paragraph[type="normal"]',
50
+ 'table[id="123"] > row > cell',
51
+ ],
52
+ "limitRequired": True,
53
+ "normalization": "Unicode NFKC + whitespace collapse + casefold",
54
+ }
55
+ return deepcopy(manifest)
56
+
57
+
58
+ def catalog_hash() -> str:
59
+ payload = json.dumps(agent_catalog(), ensure_ascii=False, sort_keys=True, separators=(",", ":"))
60
+ return "sha256:" + hashlib.sha256(payload.encode("utf-8")).hexdigest()
61
+
62
+
63
+ def agent_json_schemas() -> dict[str, Any]:
64
+ """Generate public JSON Schema fragments from the frozen catalog."""
65
+
66
+ catalog = agent_catalog()
67
+ command_variants: list[dict[str, Any]] = []
68
+ for operation, shape in catalog["commands"].items():
69
+ properties: dict[str, Any] = {
70
+ "commandId": {"type": "string", "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,31}$"},
71
+ "op": {"const": operation},
72
+ "path": {"type": "string"},
73
+ "parent": {"type": "string"},
74
+ "kind": {"enum": [kind for kind in NODE_KINDS if kind not in {"document", "unsupported"}]},
75
+ "properties": {"type": "object", "minProperties": 1, "maxProperties": 32},
76
+ "position": {"type": "object"},
77
+ }
78
+ allowed = set(shape["required"]) | set(shape.get("optional", []))
79
+ command_variants.append(
80
+ {
81
+ "type": "object",
82
+ "required": list(shape["required"]),
83
+ "additionalProperties": False,
84
+ "properties": {key: value for key, value in properties.items() if key in allowed},
85
+ }
86
+ )
87
+ quality_object: dict[str, Any] = {
88
+ "type": "object",
89
+ "additionalProperties": False,
90
+ "properties": {
91
+ "mode": {"enum": list(QUALITY_MODES)},
92
+ "renderCheck": {"enum": ["off", "auto", "required"]},
93
+ "xsdMode": {"enum": ["off", "lint"]},
94
+ "overflowPolicy": {"enum": ["fail", "warn", "truncate"]},
95
+ "layoutLint": {"enum": ["off", "warn", "strict"]},
96
+ "preserveUnmodifiedParts": {"type": "boolean"},
97
+ "requireReferenceIntegrity": {"type": "boolean"},
98
+ },
99
+ }
100
+ if set(quality_object["properties"]) != set(QUALITY_KEYS): # pragma: no cover
101
+ raise AssertionError("quality JSON Schema drifted from QUALITY_KEYS")
102
+
103
+ return {
104
+ "node": {
105
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
106
+ "title": "HwpxAgentNode v1",
107
+ "type": "object",
108
+ "required": [
109
+ "schemaVersion",
110
+ "kind",
111
+ "path",
112
+ "stableId",
113
+ "stability",
114
+ "summary",
115
+ "childCount",
116
+ "children",
117
+ "coverage",
118
+ "revision",
119
+ ],
120
+ "properties": {
121
+ "schemaVersion": {"const": catalog["schemas"]["node"]},
122
+ "kind": {"enum": list(NODE_KINDS)},
123
+ "path": {"type": "string"},
124
+ "stableId": {"type": ["string", "null"]},
125
+ "stability": {"enum": catalog["path"]["stabilityLevels"]},
126
+ "summary": {"type": "object"},
127
+ "childCount": {"type": "integer", "minimum": 0},
128
+ "children": {"type": "array"},
129
+ "coverage": {"type": "object"},
130
+ "revision": {"type": "string", "pattern": "^sha256:[a-f0-9]{64}$"},
131
+ },
132
+ },
133
+ "command": {
134
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
135
+ "title": "HwpxAgentCommand v1",
136
+ "oneOf": command_variants,
137
+ },
138
+ "batch": {
139
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
140
+ "title": "HwpxAgentBatch v1",
141
+ "type": "object",
142
+ "required": [
143
+ "schemaVersion",
144
+ "input",
145
+ "output",
146
+ "commands",
147
+ "expectedRevision",
148
+ "idempotencyKey",
149
+ "dryRun",
150
+ "quality",
151
+ "verificationRequirements",
152
+ ],
153
+ "additionalProperties": False,
154
+ "properties": {
155
+ "schemaVersion": {"const": AGENT_BATCH_SCHEMA},
156
+ "input": {
157
+ "type": "object",
158
+ "required": ["filename"],
159
+ "additionalProperties": False,
160
+ "properties": {"filename": {"type": "string", "minLength": 1}},
161
+ },
162
+ "output": {
163
+ "type": "object",
164
+ "required": ["filename", "overwrite"],
165
+ "additionalProperties": False,
166
+ "properties": {
167
+ "filename": {"type": "string", "minLength": 1},
168
+ "overwrite": {"type": "boolean"},
169
+ },
170
+ },
171
+ "commands": {
172
+ "type": "array",
173
+ "minItems": 1,
174
+ "maxItems": MAX_COMMANDS,
175
+ "items": {"oneOf": deepcopy(command_variants)},
176
+ },
177
+ "expectedRevision": {
178
+ "type": ["string", "null"],
179
+ "pattern": REVISION_PATTERN.pattern,
180
+ },
181
+ "idempotencyKey": {
182
+ "type": ["string", "null"],
183
+ "minLength": 1,
184
+ "maxLength": 128,
185
+ },
186
+ "dryRun": {"type": "boolean"},
187
+ "quality": {
188
+ "oneOf": [
189
+ {"enum": list(QUALITY_MODES)},
190
+ deepcopy(quality_object),
191
+ {"type": "null"},
192
+ ]
193
+ },
194
+ "verificationRequirements": {
195
+ "type": "array",
196
+ "items": {"enum": list(VERIFICATION_REQUIREMENTS)},
197
+ "uniqueItems": True,
198
+ },
199
+ },
200
+ },
201
+ "queryInput": {
202
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
203
+ "type": "object",
204
+ "required": ["selector", "limit"],
205
+ "additionalProperties": False,
206
+ "properties": {
207
+ "selector": {
208
+ "type": "string",
209
+ "minLength": 1,
210
+ "maxLength": catalog["limits"]["maxSelectorChars"],
211
+ },
212
+ "limit": {"type": "integer", "minimum": 1, "maximum": catalog["limits"]["maxQueryResults"]},
213
+ },
214
+ },
215
+ }
216
+
217
+
218
+ def node_help(kind: str) -> dict[str, Any]:
219
+ if kind not in NODE_KINDS:
220
+ raise AgentContractError("unknown_kind", f"unknown node kind: {kind}", target="kind")
221
+ entry = NODE_PROPERTY_CATALOG_V1[kind]
222
+ return {
223
+ "schemaVersion": AGENT_CATALOG_SCHEMA,
224
+ "kind": kind,
225
+ "readableProperties": list(entry["readable"]),
226
+ "editableProperties": list(entry["editable"]),
227
+ "operations": list(entry["operations"]),
228
+ }
229
+
230
+
231
+ def human_help(kind: str | None = None) -> str:
232
+ """Render compact human help from the same catalog used for JSON schemas."""
233
+
234
+ kinds = [kind] if kind is not None else list(NODE_KINDS)
235
+ lines = ["HWPX agent document interface v1", ""]
236
+ for candidate in kinds:
237
+ info = node_help(candidate)
238
+ readable = ", ".join(info["readableProperties"]) or "-"
239
+ editable = ", ".join(info["editableProperties"]) or "-"
240
+ operations = ", ".join(info["operations"]) or "-"
241
+ lines.extend(
242
+ [
243
+ candidate,
244
+ f" readable: {readable}",
245
+ f" editable: {editable}",
246
+ f" operations: {operations}",
247
+ ]
248
+ )
249
+ return "\n".join(lines).rstrip() + "\n"
250
+
251
+
252
+ __all__ = ["agent_catalog", "agent_json_schemas", "catalog_hash", "human_help", "node_help"]