docling-serve-client 0.4.0 → 0.5.0
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.
- package/README.md +270 -29
- package/dist/capabilities.d.ts +10 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/core/input.d.ts +1 -1
- package/dist/core/pdf.d.ts +2 -2
- package/dist/core/validate.d.ts +2 -2
- package/dist/core/validate.d.ts.map +1 -1
- package/dist/images.d.ts +6 -3
- package/dist/images.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +146 -52
- package/dist/index.js.map +11 -10
- package/dist/options.d.ts +15 -5
- package/dist/options.d.ts.map +1 -1
- package/dist/types.d.ts +123 -9
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/capabilities.ts +109 -0
- package/src/client.ts +132 -65
- package/src/core/input.ts +3 -3
- package/src/core/pdf.ts +2 -2
- package/src/core/validate.ts +2 -2
- package/src/images.ts +4 -4
- package/src/index.ts +8 -0
- package/src/options.ts +23 -7
- package/src/response.ts +1 -1
- package/src/types.ts +136 -10
package/README.md
CHANGED
|
@@ -15,20 +15,29 @@ bytes in, docling's Markdown or DoclingDocument JSON out**.
|
|
|
15
15
|
docling's raw output, e.g. with `&` entities, soft hyphens and dot leaders left in.
|
|
16
16
|
- In-memory only: no file I/O, no streaming.
|
|
17
17
|
- **Calls never throw on runtime failures.** Every call resolves to `{ ok: true, data } | { ok: false, error }`.
|
|
18
|
-
Two exceptions are programming errors: the factory throws a `TypeError` on
|
|
19
|
-
invalid option
|
|
18
|
+
Two exceptions are programming errors: the factory throws a `TypeError` on invalid config, and any call with an
|
|
19
|
+
invalid option rejects with a `TypeError` before sending a request.
|
|
20
20
|
- Sync (`convert*`) and async (`submit*` + `check`). No built-in polling, queueing or rate limiting.
|
|
21
21
|
- Zero dependencies. ESM, works in Node ≥ 22.12 (also via `require()`) and Bun.
|
|
22
22
|
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bun add docling-serve-client
|
|
27
|
+
# or
|
|
28
|
+
npm install docling-serve-client
|
|
29
|
+
```
|
|
30
|
+
|
|
23
31
|
## Usage
|
|
24
32
|
|
|
25
33
|
```ts
|
|
34
|
+
import { readFile } from 'node:fs/promises';
|
|
26
35
|
import { createDoclingClient } from 'docling-serve-client';
|
|
27
36
|
|
|
28
37
|
const docling = createDoclingClient({ baseUrl: 'http://127.0.0.1:5001' });
|
|
29
38
|
|
|
30
39
|
// Input is always a Uint8Array (Node Buffer is one): a PDF, or a PNG, JPEG, TIFF or WebP image
|
|
31
|
-
const pdf = await readFile('paper.pdf');
|
|
40
|
+
const pdf = await readFile('paper.pdf');
|
|
32
41
|
// const pdf = await Bun.file('paper.pdf').bytes(); // Bun
|
|
33
42
|
// const pdf = new Uint8Array(await (await fetch(pdfUrl)).arrayBuffer()); // any download
|
|
34
43
|
|
|
@@ -49,24 +58,49 @@ if (doc.ok) {
|
|
|
49
58
|
|
|
50
59
|
`submitMarkdown()` and `submitDocument()` return a plain JSON job object. Store all of it and pass it back to
|
|
51
60
|
`check()`. A Markdown job carries its image handling, so `check()` works the same from another process or after a
|
|
52
|
-
restart. `check()` returns the result type that matches the job's `kind`.
|
|
61
|
+
restart. `check()` returns the result type that matches the job's `kind`. The job also carries the
|
|
62
|
+
[conversion settings](#conversion-settings) of its submission; `check()` does not need them, so a stored job may omit
|
|
63
|
+
`settings`, and the `done` state does not repeat them.
|
|
53
64
|
|
|
54
65
|
```ts
|
|
66
|
+
import type { DocumentJob } from 'docling-serve-client';
|
|
67
|
+
|
|
55
68
|
const job = await docling.submitDocument(pdf);
|
|
56
69
|
if (!job.ok) return handle(job.error);
|
|
57
|
-
await save(JSON.stringify(job.data)); // { kind: 'document', id }
|
|
70
|
+
await save(JSON.stringify(job.data)); // { kind: 'document', id, settings }
|
|
58
71
|
|
|
59
|
-
// later, as often as you like:
|
|
60
|
-
const
|
|
72
|
+
// later, as often as you like (e.g. in a polling loop or another worker):
|
|
73
|
+
const storedJob: DocumentJob = JSON.parse(await load());
|
|
74
|
+
const state = await docling.check(storedJob);
|
|
61
75
|
if (state.ok) {
|
|
62
76
|
switch (state.data.status) {
|
|
63
|
-
case 'queued':
|
|
64
|
-
case 'running': break;
|
|
77
|
+
case 'queued': console.log('Queue position:', state.data.position); break;
|
|
78
|
+
case 'running': console.log('Processing...'); break;
|
|
65
79
|
case 'done': use(state.data.document); break;
|
|
66
80
|
}
|
|
81
|
+
} else {
|
|
82
|
+
// state.error.code: 'not_found' (e.g. expired or unknown id), 'http', 'conversion_failed', etc.
|
|
83
|
+
console.error(state.error.code, state.error.message);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// In-process polling loop until done:
|
|
87
|
+
while (true) {
|
|
88
|
+
const poll = await docling.check(storedJob);
|
|
89
|
+
if (!poll.ok) {
|
|
90
|
+
console.error('Job error:', poll.error.code, poll.error.message);
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
if (poll.data.status === 'done') {
|
|
94
|
+
use(poll.data.document);
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
67
98
|
}
|
|
68
99
|
```
|
|
69
100
|
|
|
101
|
+
For Markdown jobs (`submitMarkdown`), `check()` returns `JobState<ConvertedMarkdown>` whose `done` state provides
|
|
102
|
+
`markdown`, `images`, `warnings`, and `versions`.
|
|
103
|
+
|
|
70
104
|
docling-serve deletes a result `DOCLING_SERVE_RESULT_REMOVAL_DELAY` seconds (default 300) after its first fetch
|
|
71
105
|
(`DOCLING_SERVE_SINGLE_USE_RESULTS=true`, the default). A `check()` whose result download failed (network error,
|
|
72
106
|
`timeoutMs`, abort) can be repeated within that time; later `check()` returns `not_found` (`Result already fetched or
|
|
@@ -104,8 +138,9 @@ docling options (factory and per call):
|
|
|
104
138
|
| `pdfBackend` | `'docling_parse'` | text extractor; `'pypdfium2'` reads ligatures and word spaces better but misses page headers and footers |
|
|
105
139
|
| `ocr` | `true` | OCR bitmap content of PDFs (scans, pictures); image input is always OCRed |
|
|
106
140
|
| `forceOcr` | `false` | OCR whole PDF pages and drop their text layer, for PDFs with broken text; ignored for image input |
|
|
141
|
+
| `ocrEngine` | `'auto'` | OCR engine preset (`ocr_preset`): `'auto'`, `'rapidocr'`, `'easyocr'`, `'tesseract'`, `'tesserocr'`, `'ocrmac'` or any other non-empty preset id; the server rejects an id it does not allow with `http` 422, see [server capabilities](#server-capabilities) |
|
|
107
142
|
|
|
108
|
-
Factory only (`options` of `createDoclingClient`; per call they
|
|
143
|
+
Factory only (`options` of `createDoclingClient`; per call they reject with `Option "x" is not supported`). Use a second
|
|
109
144
|
client for other values:
|
|
110
145
|
|
|
111
146
|
| option | default | effect |
|
|
@@ -114,13 +149,25 @@ client for other values:
|
|
|
114
149
|
| `pageRange` | all pages | `[from, to]`, 1-based, inclusive |
|
|
115
150
|
| `documentTimeout` | server default | server-side limit in seconds |
|
|
116
151
|
|
|
117
|
-
Per call only
|
|
152
|
+
Per call only (not allowed in factory `options`, rejected with `Option "x" is not supported`):
|
|
153
|
+
|
|
154
|
+
| option | calls | default | effect |
|
|
155
|
+
|---|---|---|---|
|
|
156
|
+
| `images` | `convertMarkdown`, `submitMarkdown` | `'placeholder'` | `'placeholder'`, `'none'`, or `'extract'` |
|
|
157
|
+
| `imageOptions` | `convertMarkdown`, `submitMarkdown` | none | `{ prefix: string, omitSmall?: boolean }`; required with `images: 'extract'`, not allowed otherwise |
|
|
158
|
+
| `images` | `convertDocument`, `submitDocument` | `'embedded'` | `'embedded'` or `'placeholder'` |
|
|
159
|
+
| `pageImages` | `convertDocument`, `submitDocument` | `false` | renders pages as images, decoded in `pageImages` |
|
|
160
|
+
| `signal` | all calls (`convert*`, `submit*`, `check`, `capabilities`) | none | `AbortSignal` to cancel the request |
|
|
161
|
+
|
|
118
162
|
`timeoutMs` is a factory setting: it limits every request except `GET /version` and is combined with `signal`.
|
|
119
163
|
|
|
120
164
|
Always on, not configurable: table structure with the accurate TableFormer model (`do_table_structure`,
|
|
121
|
-
`table_mode: 'accurate'`), pictures and
|
|
122
|
-
|
|
123
|
-
|
|
165
|
+
`table_mode: 'accurate'`, `table_structure_preset: 'tableformer_v1_accurate'`, `table_cell_matching`), pictures and
|
|
166
|
+
page images at 144 dpi (`images_scale=2`, exported as `PAGE_IMAGE_SCALE`) and, for Markdown, compact tables
|
|
167
|
+
(`md_compact_tables`) without page break placeholders (`md_page_break_placeholder`). The image scale does not affect
|
|
168
|
+
OCR: docling OCRs at its own fixed 216 dpi. Model presets are pinned: `granite_docling` for `pipeline: 'vlm'`,
|
|
169
|
+
`granite_vision_v4` for `chartExtraction`, `codeformulav2` for formula and code enrichment. Picture classification
|
|
170
|
+
and description stay off.
|
|
124
171
|
|
|
125
172
|
### Input formats
|
|
126
173
|
|
|
@@ -154,6 +201,8 @@ client moves them out of the document: `document.pages[n].image` is always `null
|
|
|
154
201
|
images come back decoded in `data.pageImages`, in page order:
|
|
155
202
|
|
|
156
203
|
```ts
|
|
204
|
+
import { writeFile } from 'node:fs/promises';
|
|
205
|
+
|
|
157
206
|
const res = await docling.convertDocument(pdf, { pageImages: true, images: 'placeholder' });
|
|
158
207
|
if (res.ok) {
|
|
159
208
|
await writeFile(`out/${docId}.json`, JSON.stringify(res.data.document)); // no page image data inside
|
|
@@ -176,17 +225,73 @@ onto its page image as `{ page, x, y, width, height }` in pixels with a top-left
|
|
|
176
225
|
next to the page image file or to crop with:
|
|
177
226
|
|
|
178
227
|
```ts
|
|
228
|
+
import { toPageImageBox } from 'docling-serve-client';
|
|
229
|
+
|
|
179
230
|
for (const item of res.data.document.texts) {
|
|
180
231
|
for (const prov of item.prov) {
|
|
181
|
-
const box = toPageImageBox(res.data.document, prov); // undefined if
|
|
232
|
+
const box = toPageImageBox(res.data.document, prov); // undefined if coordinates or page missing
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// table cells carry their own bbox (top-left origin) and belong to the page of their table:
|
|
237
|
+
for (const table of res.data.document.tables) {
|
|
238
|
+
const pageNo = table.prov[0]?.page_no ?? 1;
|
|
239
|
+
for (const row of table.data.grid) {
|
|
240
|
+
for (const cell of row) {
|
|
241
|
+
if (cell.bbox) {
|
|
242
|
+
const box = toPageImageBox(res.data.document, { page_no: pageNo, bbox: cell.bbox });
|
|
243
|
+
}
|
|
244
|
+
}
|
|
182
245
|
}
|
|
183
246
|
}
|
|
184
|
-
// table cells carry their own bbox (top-left origin) and the page of their table:
|
|
185
|
-
const box = toPageImageBox(document, { page_no: table.prov[0].page_no, bbox: cell.bbox });
|
|
186
247
|
```
|
|
187
248
|
|
|
188
249
|
The boxes fit page images of any conversion by this client, also when `pageImages` was off.
|
|
189
250
|
|
|
251
|
+
### DoclingDocument structure
|
|
252
|
+
|
|
253
|
+
`convertDocument()` returns the full JSON AST (`doc.data.document`) typed as `DoclingDocument`:
|
|
254
|
+
|
|
255
|
+
- `texts`: array of text blocks (`label`, `text`, `orig`, `prov: [{ page_no, bbox, charspan }]`). Common labels include `'paragraph'`, `'section_header'`, `'title'`, `'list_item'`, `'code'`, `'formula'`, `'footnote'`, `'page_header'`, `'page_footer'`, `'caption'`. Section headers include heading `level`. List items include `enumerated` and `marker`. Code listings include `code_language`. Formulas contain LaTeX in `text` with `formulaEnrichment`. Note on `prov.charspan`: `[start, end)` span is in Python Unicode code points; slice in JS using `Array.from(item.text).slice(start, end).join('')`, not `item.text.slice(start, end)`.
|
|
256
|
+
- `tables`: array of tables (`prov`, `data: { grid: TableCell[][], num_rows, num_cols }`). Cells contain `text`, `row_span`, `col_span`, `bbox`, `column_header`, and `row_header`.
|
|
257
|
+
- `pictures`: array of figures with `captions`, `prov`, `image` (`ImageRef` with base64 data URI when `images: 'embedded'`, or `null` when `images: 'placeholder'`), and `annotations` (e.g. chart data when `chartExtraction` was enabled, classifications, descriptions).
|
|
258
|
+
- `groups`: structural groupings (`(ListGroup | InlineGroup | GroupItem)[]`) such as lists, inline formatting runs, chapters, or form sections.
|
|
259
|
+
- `key_value_items`: key-value regions extracted from forms or documents (`graph: { cells: GraphCell[], links: GraphLink[] }`).
|
|
260
|
+
- `form_items`: form regions and form fields (`graph: { cells: GraphCell[], links: GraphLink[] }`).
|
|
261
|
+
- `pages`: record of page metadata keyed by 1-based page number string (`"1"`, `"2"`, ...) with `size: { width, height }` in PDF points.
|
|
262
|
+
- `body`: root group of content in reading order. Walk `body.children` (`{ $ref: string }` JSON pointers, e.g. `'#/texts/0'`) depth-first to follow the logical document flow.
|
|
263
|
+
- `furniture`: root group of header, footer and page number items outside the body flow.
|
|
264
|
+
|
|
265
|
+
#### Navigating the AST in reading order
|
|
266
|
+
|
|
267
|
+
The root content in reading order is stored in `body.children`. Each child is a JSON pointer reference (e.g. `#/texts/0`, `#/tables/1`, `#/groups/2`). You can resolve references and walk the reading order like this:
|
|
268
|
+
|
|
269
|
+
```ts
|
|
270
|
+
import type { DoclingDocument } from 'docling-serve-client';
|
|
271
|
+
|
|
272
|
+
// Resolving a JSON pointer reference (e.g. '#/texts/0'):
|
|
273
|
+
function resolveRef(doc: DoclingDocument, ref: string) {
|
|
274
|
+
const [, collection, idx] = ref.split('/');
|
|
275
|
+
return (doc as Record<string, any>)[collection]?.[Number(idx)];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Walking body items in logical reading order:
|
|
279
|
+
function* walkReadingOrder(
|
|
280
|
+
doc: DoclingDocument,
|
|
281
|
+
node: { children: { $ref: string }[] } = doc.body,
|
|
282
|
+
): Generator<any> {
|
|
283
|
+
for (const child of node.children) {
|
|
284
|
+
const item = resolveRef(doc, child.$ref);
|
|
285
|
+
if (!item) continue;
|
|
286
|
+
if ('children' in item && Array.isArray(item.children) && item.children.length > 0) {
|
|
287
|
+
yield* walkReadingOrder(doc, item);
|
|
288
|
+
} else {
|
|
289
|
+
yield item;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
190
295
|
### Images in the Markdown
|
|
191
296
|
|
|
192
297
|
| `images` | effect |
|
|
@@ -198,6 +303,8 @@ The boxes fit page images of any conversion by this client, also when `pageImage
|
|
|
198
303
|
With `'extract'`, `imageOptions` is required on each call, because the prefix names one document's images:
|
|
199
304
|
|
|
200
305
|
```ts
|
|
306
|
+
import { writeFile } from 'node:fs/promises';
|
|
307
|
+
|
|
201
308
|
const res = await docling.convertMarkdown(pdf, {
|
|
202
309
|
images: 'extract',
|
|
203
310
|
imageOptions: { prefix: `images/${docId}-` }, // omitSmall: drop bullets, icons and small logos, default true
|
|
@@ -243,6 +350,51 @@ Store it with each converted document: the same PDF can convert differently unde
|
|
|
243
350
|
versions once and keeps them; the request has its own 2 s limit, and when it fails `versions` is `null` and the next
|
|
244
351
|
result asks again. Create a new client after a server update.
|
|
245
352
|
|
|
353
|
+
### Conversion settings
|
|
354
|
+
|
|
355
|
+
`convert*()` results (`data.settings`) and `submit*()` jobs (`job.settings`) carry the form fields the request sent,
|
|
356
|
+
as a typed `DoclingSettings` object. The client sends an explicit value for every field it controls, also where it
|
|
357
|
+
equals docling-serve's default, so the settings do not depend on the server's defaults. Store them with the versions
|
|
358
|
+
to know how a document was converted.
|
|
359
|
+
|
|
360
|
+
```ts
|
|
361
|
+
const res = await docling.convertMarkdown(pdf, { ocrEngine: 'rapidocr' });
|
|
362
|
+
if (res.ok) {
|
|
363
|
+
res.data.settings.ocrPreset; // 'rapidocr'
|
|
364
|
+
res.data.settings.tableStructurePreset; // 'tableformer_v1_accurate'
|
|
365
|
+
res.data.settings.vlmPipelinePreset; // null: pipeline is 'standard'
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
- Each key is the camelCase name of a docling-serve form field (`ocrPreset` = `ocr_preset`).
|
|
370
|
+
- `null` means the field was not sent: Markdown-only fields for document output, the preset of a disabled stage,
|
|
371
|
+
unset `pageRange` and `documentTimeout`. An empty `ocrLang` was not sent either (engine default).
|
|
372
|
+
- Image input records what was sent: `doOcr: true` and `forceOcr: false`, whatever `ocr` and `forceOcr` say.
|
|
373
|
+
- Server configuration that has no request field (e.g. the layout model) is not included; see
|
|
374
|
+
`stages.layout` of the [server capabilities](#server-capabilities).
|
|
375
|
+
|
|
376
|
+
### Server capabilities
|
|
377
|
+
|
|
378
|
+
`docling.capabilities()` asks `GET /v1/capabilities` for the presets, limits and features of the server. It is for
|
|
379
|
+
diagnostics, e.g. to list the allowed `ocrEngine` ids; conversions never call it. It takes only `{ signal }`.
|
|
380
|
+
|
|
381
|
+
```ts
|
|
382
|
+
const caps = await docling.capabilities();
|
|
383
|
+
if (caps.ok) {
|
|
384
|
+
caps.data.stages.ocr?.presets.map((preset) => preset.id); // ['auto', 'easyocr', 'rapidocr', 'tesseract', …]
|
|
385
|
+
caps.data.stages.table_structure?.default; // 'tableformer_v1_accurate'
|
|
386
|
+
caps.data.limits.maxImagesScale; // 2, or null when unlimited
|
|
387
|
+
caps.data.features.apiKeyRequired; // false
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
- The server's snake_case keys come back in camelCase; `stages` keys stay as the server sends them (`ocr`, `layout`,
|
|
392
|
+
`table_structure`, `vlm_pipeline`, `chart_extraction`, …). Each stage has `option` (its form field), `default` and
|
|
393
|
+
`presets` (`{ id, name, description, source }`).
|
|
394
|
+
- Missing or mistyped fields become `[]`, `''`, `null` or `false`, so a newer or older payload does not fail the call.
|
|
395
|
+
- An allowed preset is not always usable: e.g. `ocrmac` only runs on macOS.
|
|
396
|
+
- An older server without the endpoint answers `http` with `status: 404`.
|
|
397
|
+
|
|
246
398
|
### Broken umlauts / special characters
|
|
247
399
|
|
|
248
400
|
If the output shows `fŸhrt`, `Nu§baum`, `…sterreich`, the PDF's text layer uses an encoding docling-parse misreads
|
|
@@ -251,7 +403,18 @@ It is slower, so use it per document, not by default.
|
|
|
251
403
|
|
|
252
404
|
### Errors
|
|
253
405
|
|
|
254
|
-
|
|
406
|
+
All client calls resolve to a `Result<T>` union:
|
|
407
|
+
- `{ ok: true, data: T }` on success
|
|
408
|
+
- `{ ok: false, error: ConvertError }` on runtime failure
|
|
409
|
+
|
|
410
|
+
#### Error fields
|
|
411
|
+
|
|
412
|
+
Every `ConvertError` contains:
|
|
413
|
+
- `code`: one of the `ErrorCode` values below
|
|
414
|
+
- `message`: human-readable explanation of the failure
|
|
415
|
+
- `status`: optional HTTP status code (present when the server answered, e.g. `400`, `404`, `422`, `500`)
|
|
416
|
+
- `versions`: server versions captured from `GET /version` if the server answered, or `null`
|
|
417
|
+
- `details`: `{ errors: ServerError[]; failure: TaskFailure | null }` (present only when `code === 'conversion_failed'`)
|
|
255
418
|
|
|
256
419
|
| code | meaning |
|
|
257
420
|
|---|---|
|
|
@@ -267,21 +430,99 @@ It is slower, so use it per document, not by default.
|
|
|
267
430
|
`{ message, details }` (component, module, category, page); `failure` is docling's task classification
|
|
268
431
|
`{ category, phase, retryable }` for async jobs, or `null`.
|
|
269
432
|
|
|
270
|
-
|
|
433
|
+
TypeScript narrows `error` on `error.code`:
|
|
271
434
|
|
|
272
|
-
|
|
435
|
+
```ts
|
|
436
|
+
if (!res.ok) {
|
|
437
|
+
switch (res.error.code) {
|
|
438
|
+
case 'conversion_failed':
|
|
439
|
+
console.error('Conversion failed:', res.error.message);
|
|
440
|
+
console.error('Server error items:', res.error.details.errors);
|
|
441
|
+
console.error('Task failure:', res.error.details.failure);
|
|
442
|
+
break;
|
|
443
|
+
case 'http':
|
|
444
|
+
console.error(`HTTP error ${res.error.status}:`, res.error.message);
|
|
445
|
+
break;
|
|
446
|
+
case 'invalid_input':
|
|
447
|
+
console.error('Input rejected before request:', res.error.message);
|
|
448
|
+
break;
|
|
449
|
+
default:
|
|
450
|
+
console.error(res.error.code, res.error.message);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
```
|
|
273
454
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
455
|
+
#### Programming errors vs runtime errors
|
|
456
|
+
|
|
457
|
+
| Error Category | Trigger | Handling |
|
|
458
|
+
|---|---|---|
|
|
459
|
+
| **Runtime failure** | Server unreachable, invalid input file bytes, server HTTP 4xx/5xx, model/conversion failure, abort signal or request timeout | Resolves to `{ ok: false, error: ConvertError }` (never throws) |
|
|
460
|
+
| **Programming error** | Invalid client config (malformed URL, invalid types), unsupported or mistyped call options, incompatible options (such as `imageOptions` without `images: 'extract'`) | Throws `TypeError` synchronously on factory; rejects with `TypeError` on async client calls before sending request |
|
|
461
|
+
|
|
462
|
+
### Exported types, utilities & constants
|
|
463
|
+
|
|
464
|
+
In addition to `createDoclingClient`, the package exports helper functions, constants, and TypeScript types:
|
|
277
465
|
|
|
278
|
-
|
|
279
|
-
|
|
466
|
+
```ts
|
|
467
|
+
import {
|
|
468
|
+
createDoclingClient,
|
|
469
|
+
toPageImageBox,
|
|
470
|
+
isSmallImage,
|
|
471
|
+
readPngSize,
|
|
472
|
+
PAGE_IMAGE_SCALE,
|
|
473
|
+
type DoclingClient,
|
|
474
|
+
type DoclingConfig,
|
|
475
|
+
type ClientOptions,
|
|
476
|
+
type DoclingOptions,
|
|
477
|
+
type MarkdownOptions,
|
|
478
|
+
type DocumentOptions,
|
|
479
|
+
type CallOptions,
|
|
480
|
+
type Result,
|
|
481
|
+
type ConvertError,
|
|
482
|
+
type ErrorCode,
|
|
483
|
+
type ConvertedMarkdown,
|
|
484
|
+
type ConvertedDocument,
|
|
485
|
+
type DoclingDocument,
|
|
486
|
+
type DocumentJob,
|
|
487
|
+
type MarkdownJob,
|
|
488
|
+
type Job,
|
|
489
|
+
type JobRef,
|
|
490
|
+
type JobState,
|
|
491
|
+
type DoclingSettings,
|
|
492
|
+
type ServerCapabilities,
|
|
493
|
+
type ExtractedImage,
|
|
494
|
+
type PageImage,
|
|
495
|
+
type PageImageBox,
|
|
496
|
+
type ImageSize,
|
|
497
|
+
type MarkdownWarning,
|
|
498
|
+
type DocumentWarning,
|
|
499
|
+
type ServerError,
|
|
500
|
+
type TaskFailure,
|
|
501
|
+
} from 'docling-serve-client';
|
|
280
502
|
```
|
|
281
503
|
|
|
504
|
+
- `toPageImageBox(document, prov)`: maps a provenance item `{ page_no, bbox }` to `{ page, x, y, width, height }` in pixels with a top-left origin; returns `undefined` if the page is missing or coordinates are invalid.
|
|
505
|
+
- `isSmallImage(size)`: returns `true` if pixel dimensions match the `omitSmall` filter (area < 15,000 px, long side < 200 px, or short side < 24 px).
|
|
506
|
+
- `readPngSize(bytes)`: parses `{ width, height }` directly from a PNG's IHDR header; returns `undefined` if not a valid PNG.
|
|
507
|
+
- `PAGE_IMAGE_SCALE`: constant `2` (144 dpi resolution used by docling page images and bounding box coordinates).
|
|
508
|
+
|
|
509
|
+
## Running docling-serve
|
|
510
|
+
|
|
511
|
+
The client connects to a running [docling-serve](https://github.com/docling-project/docling-serve) server:
|
|
512
|
+
|
|
282
513
|
```bash
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
514
|
+
# Install docling-serve (default / CPU)
|
|
515
|
+
uv tool install docling-serve
|
|
516
|
+
|
|
517
|
+
# Or with CUDA (check your driver with nvidia-smi; use matching PyTorch tag, e.g. cu124, cu126)
|
|
518
|
+
uv tool install --torch-backend <cuda-tag> docling-serve
|
|
519
|
+
|
|
520
|
+
# Or via Docker (CPU)
|
|
521
|
+
docker run -p 5001:5001 quay.io/ds4sd/docling-serve
|
|
522
|
+
|
|
523
|
+
# Or via Docker (NVIDIA GPU / CUDA)
|
|
524
|
+
docker run --gpus all -p 5001:5001 quay.io/ds4sd/docling-serve
|
|
525
|
+
|
|
526
|
+
# Start the local server (listens on http://127.0.0.1:5001 by default)
|
|
527
|
+
docling-serve run
|
|
287
528
|
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Result, ServerCapabilities } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* **Maps the `GET /v1/capabilities` payload to camelCase `ServerCapabilities`**.
|
|
4
|
+
*
|
|
5
|
+
* - lenient per field: missing or mistyped values become `[]`, `''`, `null` or `false`, so new server fields or
|
|
6
|
+
* removed ones never fail the call
|
|
7
|
+
* - non-object body: `invalid_response`
|
|
8
|
+
*/
|
|
9
|
+
export declare function readCapabilities(body: unknown): Result<ServerCapabilities>;
|
|
10
|
+
//# sourceMappingURL=capabilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAuD,MAAM,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAalH;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,kBAAkB,CAAC,CA0B1E"}
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAKR,aAAa,EACb,aAAa,EAUhB,MAAM,YAAY,CAAC;AAwEpB;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CAgQxE"}
|
package/dist/core/input.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export type InputFormat = {
|
|
|
12
12
|
*
|
|
13
13
|
* - image signatures must start at byte 0; PDF: `%PDF-` within the first 1024 bytes
|
|
14
14
|
* - images are checked first, so an image whose data happens to contain `%PDF-` is still an image
|
|
15
|
-
*
|
|
15
|
+
* - returns `undefined` for empty, non-`Uint8Array` or unrecognized input
|
|
16
16
|
*/
|
|
17
17
|
export declare function detectInputFormat(bytes: unknown): InputFormat | undefined;
|
|
18
18
|
//# sourceMappingURL=input.d.ts.map
|
package/dist/core/pdf.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/** Matches a `%PDF-` header starting within the first 1024 bytes. */
|
|
2
2
|
export declare function isPdf(bytes: unknown): bytes is Uint8Array;
|
|
3
3
|
/**
|
|
4
|
-
* **Returns cross-reference offset if PDF is truncated**: last
|
|
4
|
+
* **Returns cross-reference offset if PDF is truncated**: last `startxref` points at or past EOF.
|
|
5
5
|
*
|
|
6
6
|
* - typical for aborted downloads; docling then fails with a vague load error
|
|
7
7
|
* - only the last 2 KB are read, as latin1
|
|
8
|
-
* - returns
|
|
8
|
+
* - returns `undefined` when offset lies inside file or no `startxref` found
|
|
9
9
|
*/
|
|
10
10
|
export declare function findTruncatedXref(bytes: Uint8Array): number | undefined;
|
|
11
11
|
//# sourceMappingURL=pdf.d.ts.map
|
package/dist/core/validate.d.ts
CHANGED
|
@@ -22,8 +22,8 @@ export declare function invalidValue(name: string): string;
|
|
|
22
22
|
* - rejects arrays, `Map`, `Date`, class instances and objects from another realm
|
|
23
23
|
*/
|
|
24
24
|
export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
|
|
25
|
-
/**
|
|
25
|
+
/** Returns true for boolean primitives (`true` or `false`). */
|
|
26
26
|
export declare function isBoolean(value: unknown): value is boolean;
|
|
27
|
-
/**
|
|
27
|
+
/** Returns true when string belongs to allowed set. */
|
|
28
28
|
export declare function isOneOf<T extends string>(value: unknown, allowed: readonly T[]): value is T;
|
|
29
29
|
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/core/validate.ts"],"names":[],"mappings":"AAOA,2CAA2C;AAC3C,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;AAMrD,iFAAiF;AACjF,eAAO,MAAM,uBAAuB,wCAAwC,CAAC;AAM7E;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EACzC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,EAClC,UAAU,SAAK,GAChB,OAAO,CAAC,CAAC,CAAC,CAiBZ;AAED,uDAAuD;AACvD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAM9E;AAED
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/core/validate.ts"],"names":[],"mappings":"AAOA,2CAA2C;AAC3C,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;AAMrD,iFAAiF;AACjF,eAAO,MAAM,uBAAuB,wCAAwC,CAAC;AAM7E;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EACzC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,EAClC,UAAU,SAAK,GAChB,OAAO,CAAC,CAAC,CAAC,CAiBZ;AAED,uDAAuD;AACvD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAM9E;AAED,+DAA+D;AAC/D,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAE1D;AAED,uDAAuD;AACvD,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC,CAE3F"}
|
package/dist/images.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BoundingBox, DoclingDocument } from './document.js';
|
|
2
2
|
import type { ExtractedImage, ImageOptions, ImageSize, ImageWarning, PageImage, PageImageBox, PageImageWarning } from './types.js';
|
|
3
3
|
/** Rewritten md, extracted image files, and `image_not_decoded` warnings. */
|
|
4
4
|
export type ExtractedMarkdown = {
|
|
@@ -54,9 +54,12 @@ export declare function extractPageImages(document: DoclingDocument): ExtractedP
|
|
|
54
54
|
* - `prov`: any `prov[]` entry; for a table cell pass `{ page_no: table.prov[0].page_no, bbox: cell.bbox }`
|
|
55
55
|
* - flips `BOTTOMLEFT` boxes using the page height from `document.pages`, then scales points by `PAGE_IMAGE_SCALE`
|
|
56
56
|
* - works without `pageImages: true`; the boxes fit the page images of any conversion by this client
|
|
57
|
-
* - returns `undefined` when page_no or
|
|
57
|
+
* - returns `undefined` when `page_no` or coordinate is not a finite number, or page is missing from `document.pages`
|
|
58
58
|
*/
|
|
59
|
-
export declare function toPageImageBox(document: DoclingDocument, prov:
|
|
59
|
+
export declare function toPageImageBox(document: DoclingDocument, prov: {
|
|
60
|
+
page_no: number;
|
|
61
|
+
bbox?: BoundingBox | null;
|
|
62
|
+
}): PageImageBox | undefined;
|
|
60
63
|
/**
|
|
61
64
|
* **Removes `<!-- image -->` placeholders**.
|
|
62
65
|
*
|
package/dist/images.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"images.d.ts","sourceRoot":"","sources":["../src/images.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAY,
|
|
1
|
+
{"version":3,"file":"images.d.ts","sourceRoot":"","sources":["../src/images.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAY,MAAM,eAAe,CAAC;AAC5E,OAAO,KAAK,EACR,cAAc,EACd,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,gBAAgB,EACnB,MAAM,YAAY,CAAC;AAMpB,6EAA6E;AAC7E,MAAM,MAAM,iBAAiB,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC5B,CAAC;AAEF,0HAA0H;AAC1H,MAAM,MAAM,mBAAmB,GAAG;IAC9B,QAAQ,EAAE,eAAe,CAAC;IAC1B,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAAC;AAMF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAmDlC;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAOrD;AAED,+FAA+F;AAC/F,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAYpE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,iBAAiB,CAoClG;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,mBAAmB,CAgChF;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC1B,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,GACrD,YAAY,GAAG,SAAS,CA2B1B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhE"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type * from './document.js';
|
|
2
|
-
export type { CallOptions, ClientOptions, ConversionFailure, ConvertError, ConvertedDocument, ConvertedMarkdown, ConvertInput, DoclingClient, DoclingConfig, DoclingOptions, DocumentImageMode, DocumentJob, DocumentOptions, DocumentWarning, ErrorCode, ExtractedImage, ImageOptions, ImageSize, ImageWarning, Job, JobState, MarkdownImageMode, MarkdownJob, MarkdownJobOutput, MarkdownOptions, MarkdownWarning, PageImage, PageImageBox, PageImageWarning, PdfBackend, PdfInput, Pipeline, Result, ServerDetails, ServerError, ServerVersions, ServerWarning, TaskFailure, } from './types.js';
|
|
2
|
+
export type { CallOptions, CapabilityLimits, CapabilityPreset, CapabilityStage, ClientOptions, ConversionFailure, ConvertError, ConvertedDocument, ConvertedMarkdown, ConvertInput, DoclingClient, DoclingConfig, DoclingOptions, DoclingSettings, DocumentImageMode, DocumentJob, DocumentOptions, DocumentWarning, ErrorCode, ExtractedImage, ImageOptions, ImageSize, ImageWarning, Job, JobRef, JobState, MarkdownImageMode, MarkdownJob, MarkdownJobOutput, MarkdownOptions, MarkdownWarning, OcrEngine, PageImage, PageImageBox, PageImageWarning, PdfBackend, PdfInput, Pipeline, Result, ServerCapabilities, ServerDetails, ServerError, ServerVersions, ServerWarning, TaskFailure, WithSettings, } from './types.js';
|
|
3
3
|
export { PAGE_IMAGE_SCALE } from './images.js';
|
|
4
4
|
export { createDoclingClient } from './client.js';
|
|
5
5
|
export { isSmallImage, readPngSize, toPageImageBox } from './images.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,mBAAmB,eAAe,CAAC;AACnC,YAAY,EACR,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,eAAe,EACf,SAAS,EACT,cAAc,EACd,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,GAAG,EACH,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,aAAa,EACb,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,mBAAmB,eAAe,CAAC;AACnC,YAAY,EACR,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,eAAe,EACf,SAAS,EACT,cAAc,EACd,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,GAAG,EACH,MAAM,EACN,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,SAAS,EACT,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,GACf,MAAM,YAAY,CAAC;AAMpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAM/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|