@xberg-io/opencode-xberg 1.3.8 → 1.3.11

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 (150) hide show
  1. package/.opencode/ai-rulez-bundle.json +17 -16
  2. package/.opencode/ai-rulez-content.js +3 -3
  3. package/.opencode/commands/xberg-extract.md +3 -3
  4. package/.opencode/commands/xberg-ocr.md +3 -3
  5. package/.opencode/plugins/xberg.js +1 -1
  6. package/.opencode/skills/xberg/SKILL.md +16 -21
  7. package/.opencode/skills/xberg/index.md +10 -0
  8. package/.opencode/skills/xberg/references/advanced-features.md +1 -1
  9. package/.opencode/skills/xberg/references/cli-reference.md +3 -3
  10. package/.opencode/skills/xberg/references/configuration.md +4 -4
  11. package/.opencode/skills/xberg/references/nodejs-api.md +1 -1
  12. package/.opencode/skills/xberg/references/other-bindings.md +1 -1
  13. package/.opencode/skills/xberg/references/python-api.md +3 -3
  14. package/.opencode/skills/xberg/references/rust-api.md +5 -5
  15. package/.opencode/skills/xberg/references/supported-formats.md +1 -1
  16. package/.opencode/skills/{batch-extraction → xberg-batch-extraction}/SKILL.md +11 -9
  17. package/.opencode/skills/xberg-batch-extraction/index.md +10 -0
  18. package/.opencode/skills/xberg-batch-extraction/references/advanced-features.md +628 -0
  19. package/.opencode/skills/xberg-batch-extraction/references/cli-reference.md +462 -0
  20. package/.opencode/skills/xberg-batch-extraction/references/configuration.md +587 -0
  21. package/.opencode/skills/xberg-batch-extraction/references/nodejs-api.md +485 -0
  22. package/.opencode/skills/xberg-batch-extraction/references/other-bindings.md +345 -0
  23. package/.opencode/skills/xberg-batch-extraction/references/python-api.md +657 -0
  24. package/.opencode/skills/xberg-batch-extraction/references/rust-api.md +412 -0
  25. package/.opencode/skills/xberg-batch-extraction/references/supported-formats.md +252 -0
  26. package/{.pi/skills/chunking → .opencode/skills/xberg-chunking}/SKILL.md +5 -5
  27. package/.opencode/skills/xberg-chunking/index.md +10 -0
  28. package/.opencode/skills/xberg-chunking/references/advanced-features.md +628 -0
  29. package/.opencode/skills/xberg-chunking/references/cli-reference.md +462 -0
  30. package/.opencode/skills/xberg-chunking/references/configuration.md +587 -0
  31. package/.opencode/skills/xberg-chunking/references/nodejs-api.md +485 -0
  32. package/.opencode/skills/xberg-chunking/references/other-bindings.md +345 -0
  33. package/.opencode/skills/xberg-chunking/references/python-api.md +657 -0
  34. package/.opencode/skills/xberg-chunking/references/rust-api.md +412 -0
  35. package/.opencode/skills/xberg-chunking/references/supported-formats.md +252 -0
  36. package/.opencode/skills/{extracting-keywords → xberg-extracting-keywords}/SKILL.md +7 -8
  37. package/.opencode/skills/xberg-extracting-keywords/index.md +10 -0
  38. package/.opencode/skills/xberg-extracting-keywords/references/advanced-features.md +628 -0
  39. package/.opencode/skills/xberg-extracting-keywords/references/cli-reference.md +462 -0
  40. package/.opencode/skills/xberg-extracting-keywords/references/configuration.md +587 -0
  41. package/.opencode/skills/xberg-extracting-keywords/references/nodejs-api.md +485 -0
  42. package/.opencode/skills/xberg-extracting-keywords/references/other-bindings.md +345 -0
  43. package/.opencode/skills/xberg-extracting-keywords/references/python-api.md +657 -0
  44. package/.opencode/skills/xberg-extracting-keywords/references/rust-api.md +412 -0
  45. package/.opencode/skills/xberg-extracting-keywords/references/supported-formats.md +252 -0
  46. package/{.pi/skills/extracting-tables → .opencode/skills/xberg-extracting-tables}/SKILL.md +4 -5
  47. package/.opencode/skills/xberg-extracting-tables/index.md +10 -0
  48. package/.opencode/skills/xberg-extracting-tables/references/advanced-features.md +628 -0
  49. package/.opencode/skills/xberg-extracting-tables/references/cli-reference.md +462 -0
  50. package/.opencode/skills/xberg-extracting-tables/references/configuration.md +587 -0
  51. package/.opencode/skills/xberg-extracting-tables/references/nodejs-api.md +485 -0
  52. package/.opencode/skills/xberg-extracting-tables/references/other-bindings.md +345 -0
  53. package/.opencode/skills/xberg-extracting-tables/references/python-api.md +657 -0
  54. package/.opencode/skills/xberg-extracting-tables/references/rust-api.md +412 -0
  55. package/.opencode/skills/xberg-extracting-tables/references/supported-formats.md +252 -0
  56. package/{.pi/skills/extracting-with-ocr → .opencode/skills/xberg-extracting-with-ocr}/SKILL.md +5 -6
  57. package/.opencode/skills/xberg-extracting-with-ocr/index.md +10 -0
  58. package/.opencode/skills/xberg-extracting-with-ocr/references/advanced-features.md +628 -0
  59. package/.opencode/skills/xberg-extracting-with-ocr/references/cli-reference.md +462 -0
  60. package/.opencode/skills/xberg-extracting-with-ocr/references/configuration.md +587 -0
  61. package/.opencode/skills/xberg-extracting-with-ocr/references/nodejs-api.md +485 -0
  62. package/.opencode/skills/xberg-extracting-with-ocr/references/other-bindings.md +345 -0
  63. package/.opencode/skills/xberg-extracting-with-ocr/references/python-api.md +657 -0
  64. package/.opencode/skills/xberg-extracting-with-ocr/references/rust-api.md +412 -0
  65. package/.opencode/skills/xberg-extracting-with-ocr/references/supported-formats.md +252 -0
  66. package/.opencode/skills/{picking-a-format → xberg-picking-a-format}/SKILL.md +4 -4
  67. package/.opencode/skills/xberg-picking-a-format/index.md +10 -0
  68. package/.opencode/skills/xberg-picking-a-format/references/advanced-features.md +628 -0
  69. package/.opencode/skills/xberg-picking-a-format/references/cli-reference.md +462 -0
  70. package/.opencode/skills/xberg-picking-a-format/references/configuration.md +587 -0
  71. package/.opencode/skills/xberg-picking-a-format/references/nodejs-api.md +485 -0
  72. package/.opencode/skills/xberg-picking-a-format/references/other-bindings.md +345 -0
  73. package/.opencode/skills/xberg-picking-a-format/references/python-api.md +657 -0
  74. package/.opencode/skills/xberg-picking-a-format/references/rust-api.md +412 -0
  75. package/.opencode/skills/xberg-picking-a-format/references/supported-formats.md +252 -0
  76. package/.pi/prompts/xberg-extract.md +1 -1
  77. package/.pi/prompts/xberg-ocr.md +1 -1
  78. package/.pi/skills/xberg/SKILL.md +16 -21
  79. package/.pi/skills/xberg/index.md +10 -0
  80. package/.pi/skills/xberg/references/advanced-features.md +1 -1
  81. package/.pi/skills/xberg/references/cli-reference.md +3 -3
  82. package/.pi/skills/xberg/references/configuration.md +4 -4
  83. package/.pi/skills/xberg/references/nodejs-api.md +1 -1
  84. package/.pi/skills/xberg/references/other-bindings.md +1 -1
  85. package/.pi/skills/xberg/references/python-api.md +3 -3
  86. package/.pi/skills/xberg/references/rust-api.md +5 -5
  87. package/.pi/skills/xberg/references/supported-formats.md +1 -1
  88. package/.pi/skills/{batch-extraction → xberg-batch-extraction}/SKILL.md +11 -9
  89. package/.pi/skills/xberg-batch-extraction/index.md +10 -0
  90. package/.pi/skills/xberg-batch-extraction/references/advanced-features.md +628 -0
  91. package/.pi/skills/xberg-batch-extraction/references/cli-reference.md +462 -0
  92. package/.pi/skills/xberg-batch-extraction/references/configuration.md +587 -0
  93. package/.pi/skills/xberg-batch-extraction/references/nodejs-api.md +485 -0
  94. package/.pi/skills/xberg-batch-extraction/references/other-bindings.md +345 -0
  95. package/.pi/skills/xberg-batch-extraction/references/python-api.md +657 -0
  96. package/.pi/skills/xberg-batch-extraction/references/rust-api.md +412 -0
  97. package/.pi/skills/xberg-batch-extraction/references/supported-formats.md +252 -0
  98. package/{.opencode/skills/chunking → .pi/skills/xberg-chunking}/SKILL.md +5 -5
  99. package/.pi/skills/xberg-chunking/index.md +10 -0
  100. package/.pi/skills/xberg-chunking/references/advanced-features.md +628 -0
  101. package/.pi/skills/xberg-chunking/references/cli-reference.md +462 -0
  102. package/.pi/skills/xberg-chunking/references/configuration.md +587 -0
  103. package/.pi/skills/xberg-chunking/references/nodejs-api.md +485 -0
  104. package/.pi/skills/xberg-chunking/references/other-bindings.md +345 -0
  105. package/.pi/skills/xberg-chunking/references/python-api.md +657 -0
  106. package/.pi/skills/xberg-chunking/references/rust-api.md +412 -0
  107. package/.pi/skills/xberg-chunking/references/supported-formats.md +252 -0
  108. package/.pi/skills/{extracting-keywords → xberg-extracting-keywords}/SKILL.md +7 -8
  109. package/.pi/skills/xberg-extracting-keywords/index.md +10 -0
  110. package/.pi/skills/xberg-extracting-keywords/references/advanced-features.md +628 -0
  111. package/.pi/skills/xberg-extracting-keywords/references/cli-reference.md +462 -0
  112. package/.pi/skills/xberg-extracting-keywords/references/configuration.md +587 -0
  113. package/.pi/skills/xberg-extracting-keywords/references/nodejs-api.md +485 -0
  114. package/.pi/skills/xberg-extracting-keywords/references/other-bindings.md +345 -0
  115. package/.pi/skills/xberg-extracting-keywords/references/python-api.md +657 -0
  116. package/.pi/skills/xberg-extracting-keywords/references/rust-api.md +412 -0
  117. package/.pi/skills/xberg-extracting-keywords/references/supported-formats.md +252 -0
  118. package/{.opencode/skills/extracting-tables → .pi/skills/xberg-extracting-tables}/SKILL.md +4 -5
  119. package/.pi/skills/xberg-extracting-tables/index.md +10 -0
  120. package/.pi/skills/xberg-extracting-tables/references/advanced-features.md +628 -0
  121. package/.pi/skills/xberg-extracting-tables/references/cli-reference.md +462 -0
  122. package/.pi/skills/xberg-extracting-tables/references/configuration.md +587 -0
  123. package/.pi/skills/xberg-extracting-tables/references/nodejs-api.md +485 -0
  124. package/.pi/skills/xberg-extracting-tables/references/other-bindings.md +345 -0
  125. package/.pi/skills/xberg-extracting-tables/references/python-api.md +657 -0
  126. package/.pi/skills/xberg-extracting-tables/references/rust-api.md +412 -0
  127. package/.pi/skills/xberg-extracting-tables/references/supported-formats.md +252 -0
  128. package/{.opencode/skills/extracting-with-ocr → .pi/skills/xberg-extracting-with-ocr}/SKILL.md +5 -6
  129. package/.pi/skills/xberg-extracting-with-ocr/index.md +10 -0
  130. package/.pi/skills/xberg-extracting-with-ocr/references/advanced-features.md +628 -0
  131. package/.pi/skills/xberg-extracting-with-ocr/references/cli-reference.md +462 -0
  132. package/.pi/skills/xberg-extracting-with-ocr/references/configuration.md +587 -0
  133. package/.pi/skills/xberg-extracting-with-ocr/references/nodejs-api.md +485 -0
  134. package/.pi/skills/xberg-extracting-with-ocr/references/other-bindings.md +345 -0
  135. package/.pi/skills/xberg-extracting-with-ocr/references/python-api.md +657 -0
  136. package/.pi/skills/xberg-extracting-with-ocr/references/rust-api.md +412 -0
  137. package/.pi/skills/xberg-extracting-with-ocr/references/supported-formats.md +252 -0
  138. package/.pi/skills/{picking-a-format → xberg-picking-a-format}/SKILL.md +4 -4
  139. package/.pi/skills/xberg-picking-a-format/index.md +10 -0
  140. package/.pi/skills/xberg-picking-a-format/references/advanced-features.md +628 -0
  141. package/.pi/skills/xberg-picking-a-format/references/cli-reference.md +462 -0
  142. package/.pi/skills/xberg-picking-a-format/references/configuration.md +587 -0
  143. package/.pi/skills/xberg-picking-a-format/references/nodejs-api.md +485 -0
  144. package/.pi/skills/xberg-picking-a-format/references/other-bindings.md +345 -0
  145. package/.pi/skills/xberg-picking-a-format/references/python-api.md +657 -0
  146. package/.pi/skills/xberg-picking-a-format/references/rust-api.md +412 -0
  147. package/.pi/skills/xberg-picking-a-format/references/supported-formats.md +252 -0
  148. package/README.md +72 -6
  149. package/package.json +135 -20
  150. package/scripts/mcp-launch.sh +6 -5
@@ -0,0 +1,587 @@
1
+ <!--
2
+ AI-RULEZ :: GENERATED FILE — DO NOT EDIT
3
+ Content-Hash: blake3:025df7e4b6c9e1dd2a98b81236a46d427816da719521512e3b03bc2ae15ae065
4
+ Source-Hash: blake3:662aa704cf97ad20f02258c9dcd1c73822213a426e27ec7ebc292d3f599fb7c2
5
+ Schema-Version: v1
6
+ -->
7
+
8
+ # Configuration Reference
9
+
10
+ Xberg uses a hierarchical configuration system supporting multiple formats and auto-discovery mechanisms. This reference covers the Xberg 1.1.0 `ExtractionConfig` schema, config-file keys, defaults, and loading strategies.
11
+
12
+ Every key and default below is backed by the Rust config structs in `crates/xberg/src/core/config/` (the serde field name, after any `#[serde(rename)]`, is the authoritative config-file key) and mirrored by the generated binding option dataclasses in `packages/python/xberg/options.py`.
13
+
14
+ ## Supported Formats
15
+
16
+ Xberg configurations can be defined in three formats:
17
+
18
+ - **TOML** (recommended): `xberg.toml`
19
+ - **YAML**: `xberg.yaml` / `xberg.yml`
20
+ - **JSON**: `xberg.json`
21
+
22
+ All formats deserialize into the same `ExtractionConfig` schema. The schema uses `#[serde(deny_unknown_fields)]`, so an unrecognized key is a hard error — verify spelling against this reference.
23
+
24
+ ## Auto-Discovery
25
+
26
+ `ExtractionConfig::discover()` searches the current working directory and then each parent directory, probing `xberg.toml`, `xberg.yaml`, `xberg.yml`, and `xberg.json` in that order at every level. Explicit loads via `ExtractionConfig::from_file(path)` accept the same extensions.
27
+
28
+ ## Loading Configuration
29
+
30
+ Config-file loading and auto-discovery live in the Rust core and the CLI. The language bindings (Python, Node, etc.) accept a config object/dict directly — they do not expose file-loading class methods.
31
+
32
+ ### Rust
33
+
34
+ ```rust
35
+ use xberg::core::config::ExtractionConfig;
36
+
37
+ // Explicit path (.toml / .yaml / .yml / .json by extension)
38
+ let config = ExtractionConfig::from_file("xberg.toml")?;
39
+
40
+ // Auto-discover xberg.toml/yaml/yml/json up the directory tree
41
+ let config = ExtractionConfig::discover()?; // -> Option<ExtractionConfig>
42
+ ```
43
+
44
+ ### CLI
45
+
46
+ ```bash
47
+ # Explicit configuration file
48
+ xberg extract --config xberg.toml document.pdf
49
+
50
+ # Auto-discovery (searches cwd and parents for xberg.toml/yaml/yml/json)
51
+ xberg extract document.pdf
52
+
53
+ # Inline JSON (field-level merge over the discovered/loaded config)
54
+ xberg extract --config-json '{"force_ocr": true}' document.pdf
55
+ xberg extract --config-json-base64 "$B64" document.pdf
56
+ ```
57
+
58
+ ### Python
59
+
60
+ In Python, `ExtractionConfig` is a `TypedDict`; pass a plain dict to `extract`. There is no `ExtractionConfig.from_file` / `.discover` in the binding — read the file yourself (or use the CLI) and pass the resulting dict.
61
+
62
+ ```python
63
+ from xberg import extract, ExtractInput
64
+
65
+ result = await extract(
66
+ ExtractInput(uri="document.pdf"),
67
+ config={"force_ocr": True, "chunking": {"max_characters": 1000}},
68
+ )
69
+ ```
70
+
71
+ ### Node.js / TypeScript
72
+
73
+ The Node binding likewise takes a config object passed to `extract` — file loading/discovery is a CLI/Rust-core concern, not a binding class method.
74
+
75
+ ## Configuration Schema
76
+
77
+ ### Top-Level Options
78
+
79
+ ```toml
80
+ use_cache = true
81
+ enable_quality_processing = true
82
+ force_ocr = false
83
+ disable_ocr = false
84
+ output_format = "plain"
85
+ result_format = "unified"
86
+ extraction_timeout_secs = 600
87
+ max_archive_depth = 3
88
+ ```
89
+
90
+ | Option | Type | Default | Description |
91
+ | ---------------------------- | ---------------- | ------------- | -------------------------------------------------------------------------------------------- |
92
+ | `use_cache` | boolean | `true` | Enable caching of extraction results |
93
+ | `enable_quality_processing` | boolean | `true` | Enable quality post-processing |
94
+ | `force_ocr` | boolean | `false` | Force OCR even for searchable PDFs |
95
+ | `force_ocr_pages` | array of int | unset | Force OCR only on these 1-indexed pages (PDF only). Ignored when `force_ocr = true` |
96
+ | `disable_ocr` | boolean | `false` | Disable OCR entirely, even for images (cannot be `true` together with `force_ocr`) |
97
+ | `output_format` | string | `"plain"` | Content render format: `plain`, `markdown`, `djot`, `html`, `json`, `doctags`, or a registered custom renderer |
98
+ | `result_format` | string | `"unified"` | Result shape: `unified` or `element_based` |
99
+ | `extraction_timeout_secs` | int \| null | `600` | Per-file timeout in seconds for batch extraction (10 minutes). `null` disables the timeout |
100
+ | `max_concurrent_extractions` | int \| null | `null` | Optional batch ceiling. When unset, the scheduler derives document concurrency from `concurrency.max_threads`. |
101
+ | `max_embedded_file_bytes` | int \| null | `52428800` | Max uncompressed size (bytes) of a single embedded file before recursive extraction (50 MiB) |
102
+ | `max_archive_depth` | int | `3` | Max recursion depth for archive extraction. `0` disables recursive extraction |
103
+ | `use_layout_for_markdown` | boolean | `false` | Use layout detection on the non-OCR PDF markdown path (requires `layout` set) |
104
+ | `include_document_structure` | boolean | `false` | Populate the structured `document` tree on the result |
105
+ | `cache_namespace` | string \| null | `null` | Cache namespace for tenant isolation (alphanumeric, `-`, `_`; max 64 chars) |
106
+ | `cache_ttl_secs` | int \| null | `null` | Per-request cache TTL in seconds. `0` skips the cache entirely |
107
+ | `qr_codes` | boolean \| null | `null` | Enable QR-code detection in extracted images |
108
+
109
+ Nested sections (each `None`/unset by default unless noted): `ocr`, `xberg-chunking`, `content_filter`, `images`, `pdf_options`, `token_reduction`, `language_detection`, `pages`, `keywords`, `postprocessor`, `html_output`, `security_limits`, `layout`, `transcription`, `acceleration`, `email`, `tree_sitter`, `structured_extraction`, `ner`, `redaction`, `summarization`, `translation`, `page_classification`, `captioning`, and `url`. The `url` section always has a default (it is not optional). The sections documented below are the ones most commonly set in config files.
110
+
111
+ ### OCR Configuration
112
+
113
+ ```toml
114
+ [ocr]
115
+ enabled = true
116
+ backend = "tesseract"
117
+ language = ["eng"]
118
+ auto_rotate = false
119
+ ```
120
+
121
+ | Option | Type | Default | Description |
122
+ | -------------- | ---------------- | ----------- | --------------------------------------------------------------------- |
123
+ | `enabled` | boolean | `true` | Whether OCR is enabled. Setting `false` is equivalent to `disable_ocr` |
124
+ | `backend` | string | `"tesseract"` | OCR backend: `tesseract`, `paddleocr`/`paddle-ocr`, or `vlm` |
125
+ | `language` | string or array | `["eng"]` | Language code(s). Accepts `"eng"` or `["eng", "deu"]`. Tesseract joins with `+` |
126
+ | `auto_rotate` | boolean | `false` | Enable automatic page rotation based on orientation detection |
127
+ | `vlm_fallback` | string | `"disabled"` | VLM fallback policy |
128
+ | `output_format`| string \| null | `null` | Optional OCR output format override |
129
+
130
+ Additional `[ocr]` fields exist for advanced use: `tesseract_config`, `paddle_ocr_config`, `backend_options`, `element_config`, `quality_thresholds`, `pipeline`, `vlm_config`, `vlm_prompt`, `acceleration`, `tessdata_bytes`, `tessdata_path`.
131
+
132
+ #### Tesseract Configuration
133
+
134
+ ```toml
135
+ [ocr.tesseract_config]
136
+ language = ["eng"]
137
+ psm = 3
138
+ oem = 3
139
+ output_format = "markdown"
140
+ min_confidence = 0.0
141
+ enable_table_detection = true
142
+ table_min_confidence = 0.0
143
+ table_column_threshold = 50
144
+ table_row_threshold_ratio = 0.5
145
+ use_cache = true
146
+ ```
147
+
148
+ | Option | Type | Default | Description |
149
+ | --------------------------- | --------------- | ------------ | ------------------------------------------------------------ |
150
+ | `language` | array | `["eng"]` | Language code(s); joined with `+` for Tesseract |
151
+ | `psm` | integer | `3` | Page Segmentation Mode (0–13). WASM target defaults to `6` |
152
+ | `oem` | integer | `3` | OCR Engine Mode (0–3) |
153
+ | `output_format` | string | `"markdown"` | OCR output format (`text` or `markdown`) |
154
+ | `min_confidence` | float | `0.0` | Minimum OCR confidence threshold (0.0–100.0) |
155
+ | `enable_table_detection` | boolean | `true` | Enable table detection during OCR |
156
+ | `table_min_confidence` | float | `0.0` | Minimum confidence for table cells (0.0–1.0) |
157
+ | `table_column_threshold` | integer | `50` | Pixel threshold for column detection |
158
+ | `table_row_threshold_ratio` | float | `0.5` | Row height ratio threshold (0.0–1.0) |
159
+ | `use_cache` | boolean | `true` | Cache OCR results |
160
+ | `preprocessing` | table \| null | `null` | Image preprocessing (see below) |
161
+
162
+ Advanced Tesseract engine knobs (all with the listed defaults): `classify_use_pre_adapted_templates` (`true`), `language_model_ngram_on` (`false`), `tessedit_dont_blkrej_good_wds` (`true`), `tessedit_dont_rowrej_good_wds` (`true`), `tessedit_enable_dict_correction` (`true`), `tessedit_char_whitelist` (`""`), `tessedit_char_blacklist` (`""`), `tessedit_use_primary_params_model` (`true`), `textord_space_size_is_variable` (`true`), `thresholding_method` (`false`).
163
+
164
+ #### Tesseract Preprocessing
165
+
166
+ ```toml
167
+ [ocr.tesseract_config.preprocessing]
168
+ target_dpi = 300
169
+ auto_rotate = false
170
+ deskew = true
171
+ denoise = false
172
+ contrast_enhance = false
173
+ binarization_method = "otsu"
174
+ invert_colors = false
175
+ ```
176
+
177
+ | Option | Type | Default | Description |
178
+ | --------------------- | ------- | -------- | ---------------------------------------------- |
179
+ | `target_dpi` | integer | `300` | Target DPI (300 standard, 600 for small text) |
180
+ | `auto_rotate` | boolean | `false` | Auto-detect and correct image rotation |
181
+ | `deskew` | boolean | `true` | Correct skewed (tilted) images |
182
+ | `denoise` | boolean | `false` | Remove noise from images |
183
+ | `contrast_enhance` | boolean | `false` | Enhance image contrast |
184
+ | `binarization_method` | string | `"otsu"` | Binarization method: `otsu`, `sauvola`, `adaptive` |
185
+ | `invert_colors` | boolean | `false` | Invert image colors |
186
+
187
+ ### PDF Options
188
+
189
+ ```toml
190
+ [pdf_options]
191
+ extract_images = false
192
+ extract_tables = true
193
+ extract_metadata = true
194
+ extract_form_fields = true
195
+
196
+ [pdf_options.hierarchy]
197
+ enabled = true
198
+ k_clusters = 3
199
+ include_bbox = true
200
+ ```
201
+
202
+ | Option | Type | Default | Description |
203
+ | ---------------------------------- | --------------- | ------- | ----------------------------------------------------------------------- |
204
+ | `extract_images` | boolean | `false` | Extract images from PDF documents |
205
+ | `extract_tables` | boolean | `true` | Extract tables from PDF |
206
+ | `extract_metadata` | boolean | `true` | Extract PDF metadata |
207
+ | `extract_form_fields` | boolean | `true` | Extract AcroForm / XFA form fields |
208
+ | `extract_annotations` | boolean | `false` | Extract annotations (notes, highlights, links, stamps) |
209
+ | `passwords` | array \| null | `null` | Passwords to try when opening encrypted PDFs |
210
+ | `top_margin_fraction` | float \| null | `null` | Top margin fraction (0.0–1.0) to exclude headers. Effective default 0.06 |
211
+ | `bottom_margin_fraction` | float \| null | `null` | Bottom margin fraction (0.0–1.0) to exclude footers. Effective default 0.05 |
212
+ | `allow_single_column_tables` | boolean | `false` | Allow single-column pseudo-tables |
213
+ | `ocr_inline_images` | boolean | `false` | OCR inline images extracted from PDF pages |
214
+ | `reading_order` | boolean | `false` | Reorder text by layout-detected reading order |
215
+ | `hierarchy` | table \| null | `null` | Hierarchy extraction config (see below) |
216
+
217
+ #### PDF Hierarchy
218
+
219
+ | Option | Type | Default | Description |
220
+ | ------------------------ | ------------- | ------- | ---------------------------------------------------- |
221
+ | `enabled` | boolean | `true` | Enable hierarchy extraction |
222
+ | `k_clusters` | integer | `3` | Number of font-size clusters for hierarchy (1–7) |
223
+ | `include_bbox` | boolean | `true` | Include bounding boxes in hierarchy blocks |
224
+
225
+ ### Image Processing
226
+
227
+ The `[images]` section configures `ImageExtractionConfig` (None = no image extraction).
228
+
229
+ ```toml
230
+ [images]
231
+ extract_images = true
232
+ target_dpi = 300
233
+ max_image_dimension = 4096
234
+ auto_adjust_dpi = true
235
+ min_dpi = 72
236
+ max_dpi = 600
237
+ run_ocr_on_images = true
238
+ inject_placeholders = true
239
+ ```
240
+
241
+ | Option | Type | Default | Description |
242
+ | --------------------- | -------------- | ---------- | ------------------------------------------------------- |
243
+ | `extract_images` | boolean | `true` | Extract images from documents |
244
+ | `target_dpi` | integer | `300` | Target DPI for image normalization |
245
+ | `max_image_dimension` | integer | `4096` | Maximum image dimension (width or height) in pixels |
246
+ | `inject_placeholders` | boolean | `true` | Inject `![Image](embedded:...)` placeholders into markdown |
247
+ | `auto_adjust_dpi` | boolean | `true` | Automatically adjust DPI based on image content |
248
+ | `min_dpi` | integer | `72` | Minimum DPI threshold |
249
+ | `max_dpi` | integer | `600` | Maximum DPI threshold |
250
+ | `max_images_per_page` | int \| null | `null` | Cap on image objects per PDF page (`null` = no limit) |
251
+ | `classify` | boolean | `false` | Classify and cluster extracted images by figure |
252
+ | `include_page_rasters`| boolean | `false` | Capture full-page renders as `PageRaster` images (PDF + OCR) |
253
+ | `run_ocr_on_images` | boolean | `true` | OCR extracted images and include the text in content |
254
+ | `ocr_text_only` | boolean | `false` | Render image OCR as plain text without the markdown placeholder |
255
+ | `append_ocr_text` | boolean | `false` | Append OCR text after the image placeholder |
256
+ | `output_format` | string/table | `"native"` | Re-encode format: `native`, `png`, `jpeg`, `webp` (tagged by `type`) |
257
+ | `include_data_base64` | boolean | `false` | Populate `ExtractedImage.data_base64` |
258
+
259
+ ### Chunking Configuration
260
+
261
+ ```toml
262
+ [chunking]
263
+ max_characters = 1000
264
+ overlap = 200
265
+ trim = true
266
+ chunker_type = "text"
267
+ table_chunking = "split"
268
+
269
+ [chunking.embedding]
270
+ batch_size = 32
271
+ normalize = true
272
+ show_download_progress = false
273
+
274
+ [chunking.embedding.model]
275
+ type = "preset"
276
+ name = "balanced"
277
+ ```
278
+
279
+ | Option | Type | Default | Description |
280
+ | ---------------------------------- | --------------- | ----------- | ----------------------------------------------------------------------- |
281
+ | `max_characters` | integer | `1000` | Maximum size per chunk (units determined by `sizing`) |
282
+ | `overlap` | integer | `200` | Overlap between consecutive chunks (units determined by `sizing`) |
283
+ | `trim` | boolean | `true` | Trim whitespace from chunk boundaries |
284
+ | `chunker_type` | string | `"text"` | Chunker: `text`, `markdown`, `yaml`, `semantic` |
285
+ | `preset` | string \| null | `null` | Use a preset config (overrides individual settings when set) |
286
+ | `sizing` | table \| null | `null` | How to measure chunk size; default `characters`. `tokenizer` requires the `chunking-tokenizers` feature |
287
+ | `topic_threshold` | float \| null | `null` | Cosine similarity threshold for `semantic` chunker (effective default 0.75) |
288
+ | `table_chunking` | string | `"split"` | Oversized markdown tables: `split` or `repeat_header` |
289
+ | `embedding` | table \| null | `null` | Embedding configuration (see below) |
290
+
291
+ #### Embedding
292
+
293
+ ```toml
294
+ [chunking.embedding]
295
+ normalize = true
296
+ batch_size = 32
297
+ show_download_progress = false
298
+ ```
299
+
300
+ | Option | Type | Default | Description |
301
+ | ------------------------ | -------------- | ------- | ----------------------------------------------------------------- |
302
+ | `model` | table | preset `gte-modernbert-base` | Embedding model (tagged enum, see below). Defaults to the `gte-modernbert-base` preset (`balanced` is still a selectable preset) |
303
+ | `normalize` | boolean | `true` | Normalize embedding vectors (recommended for cosine similarity) |
304
+ | `batch_size` | integer | `32` | Batch size for embedding generation |
305
+ | `show_download_progress` | boolean | `false` | Show model download progress |
306
+ | `cache_dir` | string \| null | `null` | Custom cache directory (defaults to `~/.cache/xberg/embeddings/`) |
307
+ | `acceleration` | table \| null | `null` | Hardware acceleration for the embedding ONNX model |
308
+ | `max_embed_duration_secs`| int \| null | `60` | Per-`embed()` timeout for the `plugin` model variant |
309
+
310
+ The `[chunking.embedding.model]` table is a tagged enum keyed on `type`:
311
+
312
+ | `type` | Fields | Description |
313
+ | ---------- | ------------------------------- | ----------------------------------------------------- |
314
+ | `preset` | `name` (e.g. `"balanced"`) | Built-in preset model (recommended) |
315
+ | `custom` | `model_id`, `dimensions` | Custom ONNX model from HuggingFace |
316
+ | `llm` | `llm` (LlmConfig) | Provider-hosted embedding model via liter-llm |
317
+ | `plugin` | `name` | In-process backend registered via the plugin system |
318
+
319
+ ### Keywords Configuration
320
+
321
+ ```toml
322
+ [keywords]
323
+ algorithm = "yake"
324
+ max_keywords = 10
325
+ min_score = 0.0
326
+ language = "en"
327
+ ```
328
+
329
+ | Option | Type | Default | Description |
330
+ | -------------- | --------------- | -------- | ------------------------------------------------------- |
331
+ | `algorithm` | string | `"yake"` | Keyword extraction algorithm: `yake` or `rake` |
332
+ | `max_keywords` | integer | `10` | Maximum keywords to extract |
333
+ | `min_score` | float | `0.0` | Minimum relevance score (range is algorithm-specific) |
334
+ | `ngram_range` | array `[min,max]` | `[1, 3]` | N-gram range. Config-file/Rust-only — `alef(skip)` so it is absent from the generated language-binding dataclasses |
335
+ | `language` | string \| null | `"en"` | Language code for stopword filtering (`null` = no filtering) |
336
+ | `yake_params` | table \| null | `null` | YAKE tuning: `window_size` (default `2`) |
337
+ | `rake_params` | table \| null | `null` | RAKE tuning: `min_word_length` (`1`), `max_words_per_phrase` (`3`) |
338
+
339
+ ### Token Reduction
340
+
341
+ ```toml
342
+ [token_reduction]
343
+ mode = "off"
344
+ preserve_important_words = true
345
+ ```
346
+
347
+ | Option | Type | Default | Description |
348
+ | -------------------------- | ------- | ------- | ------------------------------------------------------- |
349
+ | `mode` | string | `"off"` | Mode: `off`, `light`, `moderate`, `aggressive`, `maximum` |
350
+ | `preserve_important_words` | boolean | `true` | Preserve important words (capitalized, technical terms) |
351
+
352
+ ### Language Detection
353
+
354
+ ```toml
355
+ [language_detection]
356
+ enabled = true
357
+ min_confidence = 0.8
358
+ detect_multiple = false
359
+ ```
360
+
361
+ | Option | Type | Default | Description |
362
+ | ----------------- | ------- | ------- | ------------------------------------------ |
363
+ | `enabled` | boolean | `true` | Enable automatic language detection |
364
+ | `min_confidence` | float | `0.8` | Minimum confidence threshold for detection |
365
+ | `detect_multiple` | boolean | `false` | Detect multiple languages in the document |
366
+
367
+ ### Content Filter
368
+
369
+ ```toml
370
+ [content_filter]
371
+ include_headers = false
372
+ include_footers = false
373
+ strip_repeating_text = true
374
+ include_watermarks = false
375
+ ```
376
+
377
+ | Option | Type | Default | Description |
378
+ | ---------------------- | ------- | ------- | -------------------------------------------------- |
379
+ | `include_headers` | boolean | `false` | Include running headers in output |
380
+ | `include_footers` | boolean | `false` | Include running footers in output |
381
+ | `strip_repeating_text` | boolean | `true` | Enable the cross-page repeating-text detector |
382
+ | `include_watermarks` | boolean | `false` | Include watermark text in output |
383
+
384
+ ### Post-Processor
385
+
386
+ ```toml
387
+ [postprocessor]
388
+ enabled = true
389
+ ```
390
+
391
+ | Option | Type | Default | Description |
392
+ | --------------------- | -------------- | ------- | ----------------------------------------------- |
393
+ | `enabled` | boolean | `true` | Enable post-processors |
394
+ | `enabled_processors` | array \| null | `null` | Whitelist of processor names (`null` = all) |
395
+ | `disabled_processors` | array \| null | `null` | Blacklist of processor names (`null` = none) |
396
+
397
+ ### Security Limits
398
+
399
+ ```toml
400
+ [security_limits]
401
+ max_archive_size = 524288000
402
+ max_compression_ratio = 100
403
+ max_files_in_archive = 10000
404
+ ```
405
+
406
+ | Option | Type | Default | Description |
407
+ | ----------------------- | ------- | ------------ | --------------------------------------------------- |
408
+ | `max_archive_size` | integer | `524288000` | Max uncompressed archive size (500 MB) |
409
+ | `max_compression_ratio` | integer | `100` | Max compression ratio before flagging a bomb (100:1) |
410
+ | `max_files_in_archive` | integer | `10000` | Max files in an archive |
411
+ | `max_nesting_depth` | integer | `1024` | Max nesting depth for structures |
412
+ | `max_entity_length` | integer | `1048576` | Max length of a single XML entity/token (1 MiB) |
413
+ | `max_content_size` | integer | `104857600` | Max string growth per document (100 MB) |
414
+ | `max_iterations` | integer | `10000000` | Max iterations per operation |
415
+ | `max_xml_depth` | integer | `1024` | Max XML depth |
416
+ | `max_table_cells` | integer | `100000` | Max cells per table |
417
+
418
+ ### URL Ingestion
419
+
420
+ ```toml
421
+ [url]
422
+ mode = "auto"
423
+ allow_local_file_inputs = true
424
+ allow_file_uris = true
425
+ ```
426
+
427
+ | Option | Type | Default | Description |
428
+ | ------------------------------ | -------------- | -------- | --------------------------------------------------- |
429
+ | `mode` | string | `"auto"` | URL extraction mode: `auto`, `document`, `crawl` |
430
+ | `document_url_pattern` | string \| null | `null` | Regex filter for document-discovered URLs |
431
+ | `max_document_urls_per_result` | int \| null | `100` | Max URLs followed per extraction result |
432
+ | `max_total_urls` | int \| null | `1000` | Max URLs followed across the whole call |
433
+ | `allow_local_file_inputs` | boolean | `true` | Allow bare local filesystem path inputs |
434
+ | `allow_file_uris` | boolean | `true` | Allow local `file://` URI inputs |
435
+
436
+ ## Per-Input Configuration (`ExtractInput.config`)
437
+
438
+ Per-input overrides are no longer a separate batch function. Each `ExtractInput` carries an optional `config` field of type `FileExtractionConfig` — every field is `Option<T>` (`None` = use the batch-level default). Overrides are merged onto the batch `ExtractionConfig` per input: `Some(value)` replaces the batch default; `None` falls through.
439
+
440
+ ```python
441
+ from xberg import extract_batch, ExtractInput, FileExtractionConfig
442
+
443
+ result = await extract_batch(
444
+ [
445
+ ExtractInput(uri="scan.pdf", config=FileExtractionConfig(force_ocr=True)),
446
+ ExtractInput(uri="report.docx"), # uses batch defaults
447
+ ],
448
+ config={"chunking": {"max_characters": 1000}}, # batch-level default
449
+ )
450
+ ```
451
+
452
+ **Overridable fields:** `enable_quality_processing`, `ocr`, `force_ocr`, `force_ocr_pages`, `disable_ocr`, `xberg-chunking`, `content_filter`, `images`, `pdf_options`, `token_reduction`, `language_detection`, `pages`, `keywords`, `postprocessor`, `html_output` (and `html_options`), `result_format`, `output_format`, `include_document_structure`, `layout`, `transcription`, `timeout_secs`, `tree_sitter`, `structured_extraction`, `url`, `ner`, `redaction`, `summarization`, `translation`, `page_classification`, `captioning`, `qr_codes`.
453
+
454
+ **Batch-level only (not overridable per input):** `max_concurrent_extractions`, `use_cache`, `acceleration`, `security_limits`.
455
+
456
+ `FileExtractionConfig` is a programmatic, per-input API. It cannot be expressed in a standalone config file — config files describe the batch-level `ExtractionConfig`.
457
+
458
+ ## Naming Conventions
459
+
460
+ | Context | Convention | Example |
461
+ | -------------------- | ---------- | ----------------------------------------------------- |
462
+ | Python | snake_case | `max_characters`, `pdf_options`, `use_cache` |
463
+ | Node.js / TypeScript | camelCase | `maxCharacters`, `pdfOptions`, `useCache` |
464
+ | Rust | snake_case | `max_characters`, `pdf_options`, `use_cache` |
465
+ | TOML / YAML / JSON | snake_case | `max_characters`, `pdf_options`, `use_cache` |
466
+ | CLI flags | kebab-case | `--output-format`, `--config` |
467
+
468
+ When switching between languages:
469
+
470
+ - Python → Node.js: `snake_case` to `camelCase`
471
+ - TOML → Python: no conversion needed (both `snake_case`)
472
+
473
+ ## Environment Variables
474
+
475
+ `ExtractionConfig::apply_env_overrides()` applies these at runtime (highest precedence). Unset variables are ignored; invalid values raise a validation error.
476
+
477
+ | Variable | Maps to | Notes |
478
+ | ------------------------------ | ----------------------------------------- | -------------------------------------------------- |
479
+ | `XBERG_OCR_LANGUAGE` | `ocr.language` | ISO 639 code, e.g. `eng`, `fra`, `deu` |
480
+ | `XBERG_OCR_BACKEND` | `ocr.backend` | `tesseract`, `paddleocr`/`paddle-ocr`, `vlm` |
481
+ | `XBERG_CHUNKING_MAX_CHARS` | `chunking.max_characters` | Positive integer (env var name keeps `MAX_CHARS`) |
482
+ | `XBERG_CHUNKING_MAX_OVERLAP` | `chunking.overlap` | Non-negative integer |
483
+ | `XBERG_CHUNKING_TOKENIZER` | `chunking.sizing` (tokenizer) | Requires the `chunking-tokenizers` feature |
484
+ | `XBERG_CACHE_ENABLED` | `use_cache` | `true` / `false` |
485
+ | `XBERG_DISABLE_OCR` | `disable_ocr` | `true`/`1` or `false`/`0` |
486
+ | `XBERG_TOKEN_REDUCTION_MODE` | `token_reduction.mode` | `off`, `light`, `moderate`, `aggressive`, `maximum` |
487
+ | `XBERG_OUTPUT_FORMAT` | `output_format` | `plain`, `markdown`, `djot`, `html`, ... |
488
+ | `XBERG_LLM_MODEL` | `structured_extraction.llm.model` | e.g. `openai/gpt-4o` |
489
+ | `XBERG_LLM_API_KEY` | `structured_extraction.llm.api_key` | |
490
+ | `XBERG_LLM_BASE_URL` | `structured_extraction.llm.base_url` | |
491
+ | `XBERG_VLM_OCR_MODEL` | `ocr.vlm_config.model` | Vision-model OCR |
492
+ | `XBERG_VLM_EMBEDDING_MODEL` | `chunking.embedding.model` (llm variant) | Mutually exclusive with `XBERG_EMBEDDING_PLUGIN_NAME` |
493
+ | `XBERG_EMBEDDING_PLUGIN_NAME` | `chunking.embedding.model` (plugin variant) | Mutually exclusive with `XBERG_VLM_EMBEDDING_MODEL` |
494
+ | `XBERG_HOST` | server bind address (serve command) | e.g. `127.0.0.1` |
495
+ | `XBERG_PORT` | server port (serve command) | e.g. `8080` |
496
+
497
+ ## Configuration Merging
498
+
499
+ For the CLI, sources are merged in priority order (highest to lowest):
500
+
501
+ 1. **Individual CLI flags** (e.g. `--ocr`, `--output-format`)
502
+ 2. **Inline JSON config** (`--config-json` / `--config-json-base64`) — field-level merge
503
+ 3. **Configuration file** (`--config path`)
504
+ 4. **Auto-discovered config** (`xberg.{toml,yaml,yml,json}` in cwd/parents)
505
+ 5. **Defaults**
506
+
507
+ Environment variable overrides (`apply_env_overrides`) are applied on top of the loaded config.
508
+
509
+ ## Example Configurations
510
+
511
+ ### Minimal Configuration
512
+
513
+ ```toml
514
+ use_cache = true
515
+ enable_quality_processing = true
516
+
517
+ [ocr]
518
+ backend = "tesseract"
519
+ language = ["eng"]
520
+ ```
521
+
522
+ ### High-Quality PDF Extraction
523
+
524
+ ```toml
525
+ use_cache = true
526
+ force_ocr = false
527
+
528
+ [ocr]
529
+ backend = "tesseract"
530
+ language = ["eng"]
531
+
532
+ [ocr.tesseract_config]
533
+ psm = 3
534
+ oem = 3
535
+ enable_table_detection = true
536
+ table_min_confidence = 0.7
537
+
538
+ [pdf_options]
539
+ extract_images = true
540
+ extract_tables = true
541
+ extract_metadata = true
542
+
543
+ [pdf_options.hierarchy]
544
+ enabled = true
545
+ k_clusters = 3
546
+
547
+ [images]
548
+ extract_images = true
549
+ target_dpi = 300
550
+ ```
551
+
552
+ ### Semantic Search Configuration
553
+
554
+ ```toml
555
+ [chunking]
556
+ max_characters = 800
557
+ overlap = 150
558
+ chunker_type = "markdown"
559
+
560
+ [chunking.embedding]
561
+ batch_size = 32
562
+ normalize = true
563
+
564
+ [chunking.embedding.model]
565
+ type = "preset"
566
+ name = "quality"
567
+
568
+ [keywords]
569
+ algorithm = "yake"
570
+ max_keywords = 15
571
+ ```
572
+
573
+ ## Field Name Reference
574
+
575
+ Critical config-file keys (verify against the source structs when adding options):
576
+
577
+ - `max_characters` (chunk size; default `1000`)
578
+ - `overlap` (chunk overlap; default `200`)
579
+ - `chunker_type`, `table_chunking`, `sizing`
580
+ - `enable_table_detection`, `table_min_confidence`, `table_column_threshold`, `table_row_threshold_ratio`
581
+ - `k_clusters`, `include_bbox`
582
+ - `auto_rotate`, `auto_adjust_dpi`, `inject_placeholders`
583
+ - `show_download_progress`, `normalize`, `batch_size`
584
+ - `min_confidence`, `detect_multiple`
585
+ - `extract_tables`, `extract_form_fields`, `extract_annotations`
586
+
587
+ Always verify field names and defaults against the Rust config structs in `crates/xberg/src/core/config/` and the generated `packages/python/xberg/options.py`.