@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,485 @@
1
+ <!--
2
+ AI-RULEZ :: GENERATED FILE — DO NOT EDIT
3
+ Content-Hash: blake3:5dd1dce4a7814ed37c2ea273dda3dd60d7caa18b08b0aff933ce3a8f7717d1a6
4
+ Source-Hash: blake3:662aa704cf97ad20f02258c9dcd1c73822213a426e27ec7ebc292d3f599fb7c2
5
+ Schema-Version: v1
6
+ -->
7
+
8
+ # Node.js/TypeScript API Reference
9
+
10
+ ## Overview
11
+
12
+ **Package**: `@xberg-io/xberg` — a high-performance TypeScript SDK built on a Rust core for document intelligence and content extraction.
13
+
14
+ Install with `npm install @xberg-io/xberg`. Supports both **ESM** (`import`) and **CommonJS** (`require`):
15
+
16
+ ```typescript
17
+ // ESM
18
+ import { extract, extractBatch } from "@xberg-io/xberg";
19
+
20
+ // CommonJS
21
+ const { extract, extractBatch } = require("@xberg-io/xberg");
22
+ ```
23
+
24
+ There are exactly two extraction entry points — `extract` and `extractBatch` — and both are `async` (return `Promise`). There are no `extractFile` / `extractBytes` / `extractFileSync` / `batchExtractFiles` / worker-pool functions.
25
+
26
+ ---
27
+
28
+ ## Core Extraction Functions
29
+
30
+ ### `extract(input?, config?): Promise<ExtractionResult>`
31
+
32
+ Extract content from a single input. Returns an `ExtractionResult` **envelope** — the extracted document(s) live in `output.results`.
33
+
34
+ ```typescript
35
+ import { extract } from "@xberg-io/xberg";
36
+
37
+ const output = await extract({ kind: "uri", uri: "document.pdf" });
38
+
39
+ console.log(output.results[0].content);
40
+ console.log(`MIME type: ${output.results[0].mimeType}`);
41
+ console.log(`Results: ${output.summary.results}`);
42
+ ```
43
+
44
+ **Parameters**:
45
+
46
+ - `input?: ExtractInput` — the input to extract (see [ExtractInput](#extractinput)).
47
+ - `config?: ExtractionConfig` — optional extraction configuration.
48
+
49
+ **Returns**: `Promise<ExtractionResult>`.
50
+
51
+ ### `extractBatch(inputs, config?): Promise<ExtractionResult>`
52
+
53
+ Extract content from multiple inputs in parallel. Returns a single envelope whose `results` array holds one document per input (in input order), plus any per-input `errors`.
54
+
55
+ ```typescript
56
+ import { extractBatch } from "@xberg-io/xberg";
57
+
58
+ const output = await extractBatch([
59
+ { kind: "uri", uri: "document.pdf" },
60
+ {
61
+ kind: "bytes",
62
+ bytes: Buffer.from("Hello from memory"),
63
+ mimeType: "text/plain",
64
+ filename: "note.txt",
65
+ },
66
+ ]);
67
+
68
+ for (const doc of output.results) {
69
+ console.log(doc.content.slice(0, 200));
70
+ }
71
+ ```
72
+
73
+ **Parameters**:
74
+
75
+ - `inputs: ExtractInput[]` — array of inputs.
76
+ - `config?: ExtractionConfig` — configuration applied to all inputs.
77
+
78
+ **Returns**: `Promise<ExtractionResult>`.
79
+
80
+ ---
81
+
82
+ ## ExtractInput
83
+
84
+ The input to `extract` / `extractBatch` is a plain object discriminated by `kind`:
85
+
86
+ ```typescript
87
+ // From a path, file:// URI, or HTTP(S) URL
88
+ { kind: "uri", uri: "document.pdf" }
89
+
90
+ // From raw bytes (Buffer or Uint8Array)
91
+ {
92
+ kind: "bytes",
93
+ bytes: Buffer.from(/* ... */),
94
+ mimeType: "application/pdf", // optional hint
95
+ filename: "document.pdf", // optional hint
96
+ }
97
+ ```
98
+
99
+ `ExtractInputKind` is exported as an enum (`ExtractInputKind.Uri === "uri"`, `ExtractInputKind.Bytes === "bytes"`), but the string literals shown above work directly.
100
+
101
+ ---
102
+
103
+ ## Configuration Interface
104
+
105
+ ### `ExtractionConfig`
106
+
107
+ Configuration object controlling extraction behavior. All fields optional; field names are **camelCase**.
108
+
109
+ ```typescript
110
+ interface ExtractionConfig {
111
+ // Caching and processing
112
+ useCache?: boolean; // default: true
113
+ enableQualityProcessing?: boolean; // default: true
114
+
115
+ // OCR
116
+ ocr?: OcrConfig;
117
+ forceOcr?: boolean; // default: false
118
+
119
+ // Document processing
120
+ chunking?: ChunkingConfig;
121
+ images?: ImageExtractionConfig;
122
+ pdfOptions?: PdfConfig;
123
+ tokenReduction?: TokenReductionOptions;
124
+ languageDetection?: LanguageDetectionConfig;
125
+ postprocessor?: PostProcessorConfig;
126
+ htmlOutput?: HtmlOutputConfig;
127
+ keywords?: KeywordConfig;
128
+ pages?: PageConfig;
129
+
130
+ // Output control
131
+ maxConcurrentExtractions?: number;
132
+ outputFormat?: "plain" | "markdown" | "djot" | "html" | "json" | "doctags" | string; // default: 'plain'
133
+ resultFormat?: "unified" | "element_based"; // default: 'unified'
134
+ securityLimits?: SecurityLimits;
135
+ }
136
+ ```
137
+
138
+ ```typescript
139
+ import { extract, type ExtractionConfig } from "@xberg-io/xberg";
140
+
141
+ const config: ExtractionConfig = {
142
+ useCache: true,
143
+ enableQualityProcessing: true,
144
+ outputFormat: "markdown",
145
+ ocr: { backend: "tesseract", language: ["eng", "deu"], tesseractConfig: { psm: 6 } },
146
+ chunking: { maxCharacters: 1000, overlap: 200 },
147
+ };
148
+
149
+ const output = await extract({ kind: "uri", uri: "document.pdf" }, config);
150
+ console.log(output.results[0].content);
151
+ ```
152
+
153
+ ### `ChunkingConfig`
154
+
155
+ ```typescript
156
+ interface ChunkingConfig {
157
+ maxCharacters?: number; // max characters per chunk
158
+ overlap?: number; // overlap between chunks
159
+ chunkerType?: "text" | "markdown" | "semantic";
160
+ embedding?: { model?: { type: "preset"; name: string } } | Record<string, unknown>; // embedding config
161
+ preset?: string; // named preset
162
+ }
163
+ ```
164
+
165
+ **Key Point**: Use `maxCharacters` and `overlap` (there are no `maxChars`/`maxOverlap` fields).
166
+
167
+ ```typescript
168
+ const config = {
169
+ chunking: {
170
+ maxCharacters: 1000,
171
+ overlap: 200,
172
+ embedding: { model: { type: "preset", name: "balanced" } },
173
+ },
174
+ };
175
+ const output = await extract({ kind: "uri", uri: "document.pdf" }, config);
176
+ console.log(`Total chunks: ${output.results[0].chunks?.length ?? 0}`);
177
+ ```
178
+
179
+ ### `OcrConfig`
180
+
181
+ ```typescript
182
+ interface OcrConfig {
183
+ backend: string; // 'tesseract', 'paddleocr', 'paddle-ocr', 'vlm'
184
+ language?: string[]; // ['eng'], ['eng', 'deu']; joined with '+' for Tesseract
185
+ tesseractConfig?: TesseractConfig;
186
+ }
187
+
188
+ interface TesseractConfig {
189
+ psm?: number; // Page Segmentation Mode (0-13)
190
+ oem?: number; // OCR Engine Mode (0-3)
191
+ enableTableDetection?: boolean;
192
+ minConfidence?: number;
193
+ tesseditCharWhitelist?: string;
194
+ }
195
+ ```
196
+
197
+ ### `PdfConfig`
198
+
199
+ ```typescript
200
+ interface PdfConfig {
201
+ extractImages?: boolean; // default: false
202
+ extractTables?: boolean; // default: true
203
+ passwords?: string[]; // passwords for encrypted PDFs
204
+ extractMetadata?: boolean; // default: true
205
+ hierarchy?: HierarchyConfig;
206
+ }
207
+ ```
208
+
209
+ ### `LanguageDetectionConfig`
210
+
211
+ ```typescript
212
+ interface LanguageDetectionConfig {
213
+ enabled?: boolean; // default: true
214
+ minConfidence?: number; // 0.0-1.0 (default: 0.8)
215
+ detectMultiple?: boolean; // default: false
216
+ }
217
+ ```
218
+
219
+ ### `TokenReductionOptions`
220
+
221
+ ```typescript
222
+ interface TokenReductionOptions {
223
+ mode?: "off" | "light" | "moderate" | "aggressive" | "maximum";
224
+ preserveImportantWords?: boolean; // default: true
225
+ }
226
+ ```
227
+
228
+ ### `KeywordConfig`
229
+
230
+ ```typescript
231
+ interface KeywordConfig {
232
+ algorithm?: "yake" | "rake"; // default: 'yake'
233
+ maxKeywords?: number;
234
+ minScore?: number;
235
+ language?: string;
236
+ yakeParams?: { windowSize?: number };
237
+ rakeParams?: { minWordLength?: number; maxWordsPerPhrase?: number };
238
+ }
239
+ ```
240
+
241
+ ### `PageConfig`
242
+
243
+ ```typescript
244
+ interface PageConfig {
245
+ extractPages?: boolean;
246
+ insertPageMarkers?: boolean;
247
+ markerFormat?: string; // contains {page_num}
248
+ }
249
+ ```
250
+
251
+ ---
252
+
253
+ ## Result Types
254
+
255
+ ### `ExtractionResult` (envelope)
256
+
257
+ `extract` and `extractBatch` both resolve to this envelope. Per-document data is in `results`.
258
+
259
+ ```typescript
260
+ interface ExtractionResult {
261
+ results: ExtractedDocument[]; // one per input, in input order
262
+ errors: ExtractionErrorItem[]; // non-fatal per-input errors
263
+ summary: ExtractionSummary; // { inputs, results, errors, ... }
264
+ }
265
+ ```
266
+
267
+ ### `ExtractedDocument`
268
+
269
+ ```typescript
270
+ interface ExtractedDocument {
271
+ content: string; // main extracted text
272
+ mimeType: string;
273
+ metadata: Metadata; // common fields at top level; format-specific under metadata.format, custom under metadata.additional
274
+ tables: Table[];
275
+ detectedLanguages?: string[] | null;
276
+ chunks?: Chunk[] | null;
277
+ images?: ExtractedImage[] | null;
278
+ pages?: PageContent[] | null;
279
+ elements?: Element[] | null; // when resultFormat: 'element_based'
280
+ extractedKeywords?: Keyword[] | null;
281
+ qualityScore?: number | null;
282
+ processingWarnings?: ProcessingWarning[];
283
+ }
284
+ ```
285
+
286
+ ### `Table`
287
+
288
+ ```typescript
289
+ interface Table {
290
+ cells: string[][]; // 2D array (rows × columns)
291
+ markdown: string;
292
+ pageNumber: number; // 1-indexed
293
+ }
294
+ ```
295
+
296
+ ```typescript
297
+ const output = await extract({ kind: "uri", uri: "document.pdf" });
298
+ output.results[0].tables?.forEach((table) => {
299
+ console.log(`Table with ${table.cells?.length ?? 0} rows`);
300
+ console.log(table.markdown);
301
+ });
302
+ ```
303
+
304
+ ### `Chunk`
305
+
306
+ ```typescript
307
+ interface Chunk {
308
+ content: string;
309
+ embedding?: number[] | null; // when chunking embedding is configured
310
+ metadata: ChunkMetadata;
311
+ }
312
+ ```
313
+
314
+ ### `Keyword`
315
+
316
+ ```typescript
317
+ interface Keyword {
318
+ text: string;
319
+ score: number;
320
+ algorithm: KeywordAlgorithm; // 'yake' | 'rake'
321
+ positions?: number[] | null;
322
+ }
323
+ ```
324
+
325
+ ### `Metadata`
326
+
327
+ Metadata is **not** flat. Common fields (`title`, `subject`, `authors`, `keywords`, `language`, `createdAt`/`modifiedAt`, `pages`, etc.) sit at the top level, but format-specific fields nest under `metadata.format` (a `FormatMetadata` discriminated union keyed by `format_type`), and custom post-processor fields nest under `metadata.additional`. There is no `page_count`/`pageCount` member on `Metadata`, and use `authors` (an array), not `author`. Read page count from format-specific metadata or from `metadata.pages` (PageStructure):
328
+
329
+ The variant payload sits directly on `format`: `format_type` narrows the union and the payload
330
+ fields are read at the same level, matching the JSON the core library serializes.
331
+
332
+ ```typescript
333
+ const doc = output.results[0];
334
+ if (doc.metadata?.format?.format_type === "pdf") {
335
+ console.log(`Pages: ${doc.metadata.format.page_count}`);
336
+ } else if (doc.metadata?.pages) {
337
+ console.log(`Pages: ${doc.metadata.pages.totalCount}`);
338
+ }
339
+ ```
340
+
341
+ > **Changed in 1.1.6:** the payload used to nest one level down under a property named for the
342
+ > variant (`format.pdf.pageCount`). It is now flat (`format.page_count`), which aligns the Node
343
+ > binding with the WebAssembly binding and with the wire format every other binding emits.
344
+ > `format_type` remains the discriminant. The payload fields are **snake_case** here, unlike the
345
+ > camelCase Node uses elsewhere -- the variants carry mutually incompatible field types, so the
346
+ > value is passed through exactly as the core serializes it rather than being remapped.
347
+
348
+ ---
349
+
350
+ ## Error Handling
351
+
352
+ The Node binding throws standard `Error` objects (it does **not** export typed error classes such as `ParsingError` / `OcrError`). Catch with `instanceof Error`, and inspect the per-input `errors` array on the envelope for non-fatal failures.
353
+
354
+ ```typescript
355
+ import { extract } from "@xberg-io/xberg";
356
+
357
+ try {
358
+ const output = await extract({ kind: "uri", uri: "missing.pdf" });
359
+ if (output.errors.length > 0) {
360
+ console.error("Per-input errors:", output.errors);
361
+ }
362
+ console.log(output.results[0]?.content);
363
+ } catch (error: unknown) {
364
+ if (error instanceof Error) {
365
+ console.error(`Extraction failed: ${error.message}`);
366
+ }
367
+ throw error;
368
+ }
369
+ ```
370
+
371
+ ---
372
+
373
+ ## Plugin System
374
+
375
+ Custom plugins extend the Rust pipeline. Plugin callbacks receive a single `ExtractedDocument`.
376
+
377
+ ### Post-Processors
378
+
379
+ ```typescript
380
+ import { registerPostProcessor } from "@xberg-io/xberg";
381
+
382
+ const processor = {
383
+ name() {
384
+ return "my_processor";
385
+ },
386
+ async process(result) {
387
+ result.metadata["custom_field"] = "value";
388
+ return result;
389
+ },
390
+ processingStage() {
391
+ return "Late"; // "Early" | "Middle" | "Late"
392
+ },
393
+ };
394
+
395
+ registerPostProcessor(processor);
396
+ ```
397
+
398
+ `unregisterPostProcessor(name)`, `listPostProcessors()`, and `clearPostProcessors()` manage the registry.
399
+
400
+ ### Validators
401
+
402
+ ```typescript
403
+ import { registerValidator } from "@xberg-io/xberg";
404
+
405
+ const validator = {
406
+ name() {
407
+ return "content_length_validator";
408
+ },
409
+ validate(result) {
410
+ if (result.content.length < 10) {
411
+ throw new Error("Content too short");
412
+ }
413
+ },
414
+ priority() {
415
+ return 100; // higher = runs first
416
+ },
417
+ };
418
+
419
+ registerValidator(validator);
420
+ ```
421
+
422
+ `unregisterValidator(name)`, `listValidators()`, and `clearValidators()` manage the registry.
423
+
424
+ ### OCR Backends
425
+
426
+ ```typescript
427
+ import { registerOcrBackend } from "@xberg-io/xberg";
428
+
429
+ const backend = {
430
+ name() {
431
+ return "my-ocr";
432
+ },
433
+ supportedLanguages() {
434
+ return ["eng", "deu", "fra"];
435
+ },
436
+ async processImage(imageBytes, config) {
437
+ return {
438
+ content: "extracted text",
439
+ mimeType: "text/plain",
440
+ metadata: { confidence: 0.95, language: config.language },
441
+ tables: [],
442
+ };
443
+ },
444
+ };
445
+
446
+ registerOcrBackend(backend);
447
+ ```
448
+
449
+ `unregisterOcrBackend(name)`, `listOcrBackends()`, and `clearOcrBackends()` manage the registry.
450
+
451
+ ---
452
+
453
+ ## Embeddings
454
+
455
+ Embedding models are selected inside `chunking.embedding` via a `model` tagged union (`{ type: "preset", name }` for a named preset, or a custom model object). Presets: `fast`, `balanced`, `quality`, `multilingual`.
456
+
457
+ ```typescript
458
+ const config = {
459
+ chunking: {
460
+ maxCharacters: 512,
461
+ embedding: { model: { type: "preset", name: "balanced" } },
462
+ },
463
+ };
464
+
465
+ const output = await extract({ kind: "uri", uri: "document.pdf" }, config);
466
+ for (const chunk of output.results[0].chunks ?? []) {
467
+ console.log(`Embedding dims: ${chunk.embedding?.length ?? 0}`);
468
+ }
469
+ ```
470
+
471
+ ---
472
+
473
+ ## Other Functions
474
+
475
+ ```typescript
476
+ import { listSupportedFormats } from "@xberg-io/xberg";
477
+
478
+ console.log(listSupportedFormats());
479
+ ```
480
+
481
+ ---
482
+
483
+ ## Supported Document Formats
484
+
485
+ Xberg supports 107 formats across 141 file extensions: PDF, Office, eBooks, images, HTML/XML/SVG, email, archives, structured data, academic formats, and source code. See [supported-formats.md](supported-formats.md) for the complete list.