docling-serve-client 0.4.0 → 0.6.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 +466 -164
- package/dist/capabilities.d.ts +10 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/client.d.ts +3 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/core/input.d.ts +1 -1
- package/dist/core/input.d.ts.map +1 -1
- package/dist/core/pdf.d.ts +2 -2
- package/dist/core/pdf.d.ts.map +1 -1
- package/dist/core/validate.d.ts +2 -2
- package/dist/core/validate.d.ts.map +1 -1
- package/dist/document.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 +272 -78
- package/dist/index.js.map +12 -11
- package/dist/options.d.ts +37 -5
- package/dist/options.d.ts.map +1 -1
- package/dist/types.d.ts +169 -17
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/capabilities.ts +109 -0
- package/src/client.ts +254 -81
- package/src/core/http.ts +2 -4
- package/src/core/input.ts +1 -3
- package/src/core/pdf.ts +2 -3
- package/src/core/validate.ts +2 -3
- package/src/document.ts +7 -19
- package/src/images.ts +4 -6
- package/src/index.ts +9 -0
- package/src/options.ts +142 -27
- package/src/response.ts +2 -2
- package/src/types.ts +191 -30
package/README.md
CHANGED
|
@@ -6,282 +6,584 @@
|
|
|
6
6
|
|
|
7
7
|
# docling-serve-client
|
|
8
8
|
|
|
9
|
-
Typed HTTP client for a running [docling-serve](https://github.com/docling-project/docling-serve): **PDF or image
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
Typed HTTP client for a running [docling-serve](https://github.com/docling-project/docling-serve): **PDF or image bytes in, docling's Markdown or DoclingDocument JSON out**.
|
|
10
|
+
|
|
11
|
+
- **Two outputs**: `convertMarkdown` returns docling's Markdown unchanged (with configurable image handling); `convertDocument` returns the full DoclingDocument JSON AST (labels, reading order, page metadata, bounding boxes).
|
|
12
|
+
- **No text heuristics**: raw docling output is preserved exactly as returned by the server (e.g. HTML entities, soft hyphens, dot leaders).
|
|
13
|
+
- **In-memory only**: no file I/O or streaming dependencies.
|
|
14
|
+
- **Never throws on runtime failures**: all client calls resolve to `{ ok: true, data } | { ok: false, error }`. Programming errors throw a `TypeError` (synchronously on the factory for invalid configuration; rejected on methods before sending requests for invalid options).
|
|
15
|
+
- **Three execution modes**: single requests (`convert*`), background jobs (`submit*` + `check`), and automated polling helpers (`run*`, `waitForJob`). See [Single request or job?](#single-request-or-job).
|
|
16
|
+
- **Zero dependencies**: pure ESM, runs on Node ≥ 22.12 (including `require()`) and Bun.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
bun add docling-serve-client
|
|
22
|
+
# or
|
|
23
|
+
npm install docling-serve-client
|
|
24
|
+
```
|
|
22
25
|
|
|
23
26
|
## Usage
|
|
24
27
|
|
|
25
28
|
```ts
|
|
29
|
+
import { readFile } from 'node:fs/promises';
|
|
26
30
|
import { createDoclingClient } from 'docling-serve-client';
|
|
27
31
|
|
|
28
32
|
const docling = createDoclingClient({ baseUrl: 'http://127.0.0.1:5001' });
|
|
29
33
|
|
|
30
|
-
// Input is
|
|
31
|
-
const pdf = await readFile('paper.pdf');
|
|
32
|
-
// const pdf = await Bun.file('paper.pdf').bytes();
|
|
33
|
-
// const pdf = new Uint8Array(await (await fetch(pdfUrl)).arrayBuffer()); // any download
|
|
34
|
+
// Input is a Uint8Array (Node Buffer is an instance): PDF, PNG, JPEG, TIFF, or WebP
|
|
35
|
+
const pdf = await readFile('paper.pdf');
|
|
36
|
+
// const pdf = await Bun.file('paper.pdf').bytes(); // Bun
|
|
34
37
|
|
|
38
|
+
// 1. Convert to Markdown
|
|
35
39
|
const md = await docling.convertMarkdown(pdf);
|
|
36
|
-
if (md.ok)
|
|
40
|
+
if (md.ok) {
|
|
41
|
+
console.log(md.data.markdown, md.data.warnings);
|
|
42
|
+
}
|
|
37
43
|
|
|
44
|
+
// 2. Convert to DoclingDocument JSON AST
|
|
38
45
|
const doc = await docling.convertDocument(pdf);
|
|
39
46
|
if (doc.ok) {
|
|
40
47
|
for (const item of doc.data.document.texts) {
|
|
41
|
-
if (item.label === 'section_header')
|
|
48
|
+
if (item.label === 'section_header') {
|
|
49
|
+
console.log(item.level, item.text, item.prov[0]?.page_no);
|
|
50
|
+
}
|
|
42
51
|
}
|
|
43
52
|
} else {
|
|
44
53
|
console.error(doc.error.code, doc.error.message);
|
|
45
54
|
}
|
|
55
|
+
|
|
56
|
+
// 3. Automated job helper (identical data, typically faster for small inputs)
|
|
57
|
+
const fast = await docling.runDocument(pdf);
|
|
58
|
+
if (fast.ok) {
|
|
59
|
+
console.log(fast.data.document.texts.length, fast.data.settings);
|
|
60
|
+
}
|
|
46
61
|
```
|
|
47
62
|
|
|
48
|
-
###
|
|
63
|
+
### Single request or job?
|
|
64
|
+
|
|
65
|
+
docling-serve exposes two endpoint families, covered by three client patterns:
|
|
66
|
+
|
|
67
|
+
| Client Calls | docling-serve Endpoints | Execution Model |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| Single request: `convertMarkdown`, `convertDocument` | Sync: `POST /v1/convert/file` | Holds a single HTTP connection open until conversion completes |
|
|
70
|
+
| Background job: `submitMarkdown`, `submitDocument`, `check` | Async: `POST /v1/convert/file/async`, `GET /v1/status/poll/{id}`, `GET /v1/result/{id}` | Returns a job ID immediately; caller persists job and polls with `check()` |
|
|
71
|
+
| Job helper: `runMarkdown`, `runDocument`, `waitForJob` | Async (as above) | Submits (or takes a stored job) and polls every `pollMs` (default 10 ms) until complete |
|
|
72
|
+
|
|
73
|
+
Under the hood, docling-serve processes single requests as background jobs polled at intervals of `DOCLING_SERVE_SYNC_POLL_INTERVAL` seconds (default 2). A sync request only finishes on a tick: a 0.5 s conversion waits up to 2 s, and a 2.1 s conversion waits 4 s. Measured on a one-page PDF (docling-serve 1.38.2, 5 calls each after warm-up):
|
|
74
|
+
|
|
75
|
+
| Call | Duration per call |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `convertDocument`, `convertMarkdown` | 2006 to 2033 ms |
|
|
78
|
+
| `runDocument`, `runMarkdown` | 221 to 420 ms |
|
|
49
79
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
80
|
+
Which to use:
|
|
81
|
+
|
|
82
|
+
- **Small inputs or latency-sensitive tasks** (single images, OCR crops, one-page PDFs): use `runMarkdown` or `runDocument`. They resolve to the same `data` as `convert*` and act as drop-in replacements.
|
|
83
|
+
- **Long documents**: any call works (latency overhead is at most one tick). Single requests fail with HTTP 504 after `DOCLING_SERVE_MAX_SYNC_WAIT` (120 s), so use a job or job helper for long conversions.
|
|
84
|
+
- **Cross-process workflows, queue progress, or recovery**: use `submit*`, persist the job object, and poll with `check()` or `waitForJob()`.
|
|
85
|
+
- **Single HTTP request without polling**: use `convert*`.
|
|
86
|
+
|
|
87
|
+
Relevant docling-serve environment variables (read from the server environment or `.env` in the server root):
|
|
88
|
+
|
|
89
|
+
| Variable | Default | Description |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| `DOCLING_SERVE_SYNC_POLL_INTERVAL` | `2` | Seconds between status checks on the sync endpoint (integer; `1` halves single-request wait; fractions like `0.5` fail server startup) |
|
|
92
|
+
| `DOCLING_SERVE_MAX_SYNC_WAIT` | `120` | Seconds a single request waits before returning HTTP 504 (the server task continues running) |
|
|
93
|
+
| `DOCLING_SERVE_SINGLE_USE_RESULTS` | `true` | Purges task results `DOCLING_SERVE_RESULT_REMOVAL_DELAY` seconds after first result fetch (see [Jobs](#jobs)) |
|
|
94
|
+
| `DOCLING_SERVE_RESULT_REMOVAL_DELAY` | `300` | Seconds from first result fetch until the task is deleted |
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
DOCLING_SERVE_SYNC_POLL_INTERVAL=1 docling-serve run --host 127.0.0.1 --port 5001
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
In Node, `fetch` aborts if response headers take longer than 300 s (`network` error due to undici's default `headersTimeout`), so single requests fail after 300 s even if `DOCLING_SERVE_MAX_SYNC_WAIT` is set higher. Jobs are not affected.
|
|
101
|
+
|
|
102
|
+
### Jobs
|
|
103
|
+
|
|
104
|
+
`submitMarkdown()` and `submitDocument()` return a plain JSON job object. Persist it and pass it to `check()` or `waitForJob()`. A Markdown job preserves its image handling settings across processes and restarts, returning the result type matching the job's `kind`. Jobs also store the [conversion settings](#conversion-settings) sent at submission; `check()` and `waitForJob()` do not require `settings` and omit them from their result.
|
|
53
105
|
|
|
54
106
|
```ts
|
|
107
|
+
import type { DocumentJob } from 'docling-serve-client';
|
|
108
|
+
|
|
109
|
+
// 1. One awaited helper call: submit, poll every 10 ms, return result (same data as convertDocument)
|
|
110
|
+
const res = await docling.runDocument(pdf, { images: 'placeholder' });
|
|
111
|
+
if (res.ok) {
|
|
112
|
+
console.log(res.data.document, res.data.settings);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 2. Or submit and store the job handle:
|
|
55
116
|
const job = await docling.submitDocument(pdf);
|
|
56
|
-
if (!job.ok)
|
|
57
|
-
|
|
117
|
+
if (!job.ok) {
|
|
118
|
+
throw new Error(`${job.error.code}: ${job.error.message}`);
|
|
119
|
+
}
|
|
120
|
+
await save(JSON.stringify(job.data)); // { kind: 'document', id, settings }
|
|
58
121
|
|
|
59
|
-
//
|
|
60
|
-
const
|
|
122
|
+
// 3. Later (in this or another process): poll until complete
|
|
123
|
+
const storedJob: DocumentJob = JSON.parse(await load());
|
|
124
|
+
const done = await docling.waitForJob(storedJob, { pollMs: 100 }); // Result<ConvertedDocument>
|
|
125
|
+
if (done.ok) {
|
|
126
|
+
console.log(done.data.document);
|
|
127
|
+
} else {
|
|
128
|
+
console.error(done.error.code, done.error.message);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// 4. Or check status on demand (e.g. for progress bars):
|
|
132
|
+
const state = await docling.check(storedJob);
|
|
61
133
|
if (state.ok) {
|
|
62
134
|
switch (state.data.status) {
|
|
63
|
-
case 'queued':
|
|
64
|
-
case 'running': break;
|
|
65
|
-
case 'done':
|
|
135
|
+
case 'queued': console.log('Queue position:', state.data.position); break;
|
|
136
|
+
case 'running': console.log('Processing...'); break;
|
|
137
|
+
case 'done': console.log(state.data.document); break;
|
|
66
138
|
}
|
|
139
|
+
} else {
|
|
140
|
+
// state.error.code: 'not_found' (expired or unknown ID), 'http', 'conversion_failed', etc.
|
|
141
|
+
console.error(state.error.code, state.error.message);
|
|
67
142
|
}
|
|
68
143
|
```
|
|
69
144
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
expired`), so persist the `done` data. Start docling-serve with `DOCLING_SERVE_SINGLE_USE_RESULTS=false` to keep results
|
|
74
|
-
until they expire. These are server settings; `convert*()` is not affected.
|
|
145
|
+
For Markdown jobs (`submitMarkdown`), `check()` returns `JobState<ConvertedMarkdown>` (`done` provides `markdown`, `images`, `warnings`, `versions`) and `waitForJob()` returns `ConvertedMarkdown`.
|
|
146
|
+
|
|
147
|
+
Job helper details:
|
|
75
148
|
|
|
76
|
-
|
|
149
|
+
- `runMarkdown()` / `runDocument()` = `submit*()` + `waitForJob()`. They accept `convert*` options plus `pollMs` and resolve to `WithSettings<...>` (matching `convert*`).
|
|
150
|
+
- `waitForJob()` resolves to `check()`'s `done` data without `status` (`ConvertedMarkdown | ConvertedDocument` when called with an unnarrowed `JobRef`).
|
|
151
|
+
- The first status poll runs immediately; `pollMs` delays only after `queued` or `running` states, keeping at most one request in flight. Finished jobs return in a single check.
|
|
152
|
+
- The first encountered error terminates the call without retries (same error codes as `submit*` and `check()`).
|
|
153
|
+
- `signal` covers submission, status polls, and waits. Factory `timeoutMs` limits individual HTTP requests. Use `signal: AbortSignal.timeout(ms)` to bound total execution time.
|
|
154
|
+
- Aborting a call (or encountering an HTTP 504 on `convert*`) cancels only client-side execution; docling-serve has no task cancellation endpoint, so the server task continues.
|
|
155
|
+
- `run*` does not return the job handle. To retain job IDs across restarts or retry result downloads, use `submit*` with `waitForJob()`.
|
|
77
156
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
157
|
+
When `DOCLING_SERVE_SINGLE_USE_RESULTS=true` (the default), docling-serve purges a task `DOCLING_SERVE_RESULT_REMOVAL_DELAY` seconds (default 300) after its result is first fetched. If a download in `check()` or `waitForJob()` fails (e.g. network interruption or abort), it can be retried within this window. Once purged, calls return `not_found` (`Unknown job id`). To retain completed tasks on the server, configure `DOCLING_SERVE_SINGLE_USE_RESULTS=false`. Single requests (`convert*`) are unaffected.
|
|
158
|
+
|
|
159
|
+
### Client configuration and options
|
|
160
|
+
|
|
161
|
+
Create a client instance with `createDoclingClient(config)`:
|
|
82
162
|
|
|
83
163
|
```ts
|
|
164
|
+
import { createDoclingClient } from 'docling-serve-client';
|
|
165
|
+
|
|
84
166
|
const docling = createDoclingClient({
|
|
85
|
-
baseUrl: 'http://127.0.0.1:5001',
|
|
86
|
-
apiKey: '
|
|
87
|
-
timeoutMs: 120_000, // optional
|
|
88
|
-
|
|
89
|
-
|
|
167
|
+
baseUrl: 'http://127.0.0.1:5001', // base URL (may include a path prefix); trailing slash stripped; no query, fragment, or auth
|
|
168
|
+
apiKey: 'my-secret-key', // optional X-Api-Key header
|
|
169
|
+
timeoutMs: 120_000, // optional per-request timeout in ms (resolves to aborted)
|
|
170
|
+
pollMs: 10, // default polling interval in ms for job helpers (default 10)
|
|
171
|
+
options: { ocrLang: ['de', 'en'] }, // default docling options applied to every call
|
|
172
|
+
fetch: customFetch, // optional custom fetch implementation
|
|
90
173
|
});
|
|
91
|
-
|
|
92
|
-
await docling.convertDocument(pdf, { ocr: false, images: 'placeholder', signal: AbortSignal.timeout(60_000) });
|
|
93
174
|
```
|
|
94
175
|
|
|
95
|
-
|
|
176
|
+
#### Factory configuration (`DoclingConfig`)
|
|
96
177
|
|
|
97
|
-
|
|
|
98
|
-
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `ocr` | `true` | OCR bitmap content of PDFs (scans, pictures); image input is always OCRed |
|
|
106
|
-
| `forceOcr` | `false` | OCR whole PDF pages and drop their text layer, for PDFs with broken text; ignored for image input |
|
|
107
|
-
|
|
108
|
-
Factory only (`options` of `createDoclingClient`; per call they throw `Option "x" is not supported`). Use a second
|
|
109
|
-
client for other values:
|
|
110
|
-
|
|
111
|
-
| option | default | effect |
|
|
112
|
-
|---|---|---|
|
|
113
|
-
| `ocrLang` | engine default | BCP-47 hints in order of preference, e.g. `['de', 'en-US']`; `[]` = engine default |
|
|
114
|
-
| `pageRange` | all pages | `[from, to]`, 1-based, inclusive |
|
|
115
|
-
| `documentTimeout` | server default | server-side limit in seconds |
|
|
178
|
+
| Option | Type | Default | Description |
|
|
179
|
+
|---|---|---|---|
|
|
180
|
+
| `baseUrl` | `string` | *required* | docling-serve base URL (e.g. `'http://127.0.0.1:5001'`). May include a path prefix; trailing slash stripped; no query, fragment, or credentials |
|
|
181
|
+
| `apiKey` | `string` | none | Sent in `X-Api-Key` request header |
|
|
182
|
+
| `timeoutMs` | `number` | none | Per-request timeout in milliseconds (integer `1..2147483647`; resolves to `aborted` on expiry; excludes `/version`) |
|
|
183
|
+
| `pollMs` | `number` | `10` | Default polling interval in ms for job helpers (`run*`, `waitForJob`) (integer `1..2147483647`) |
|
|
184
|
+
| `options` | `ClientOptions` | none | Default conversion options applied to every call |
|
|
185
|
+
| `fetch` | `typeof fetch` | `globalThis.fetch` | Custom fetch implementation for proxies, mocking, or custom dispatchers |
|
|
116
186
|
|
|
117
|
-
|
|
118
|
-
`timeoutMs` is a factory setting: it limits every request except `GET /version` and is combined with `signal`.
|
|
187
|
+
The default `pollMs` of 10 ms sends up to 100 status requests per second per active job. On a local docling-serve instance with the default in-memory engine, status lookups are in-memory checks. For remote servers, queue-backed workers (RQ or Ray), or high-concurrency environments, configure 100 to 500 ms. The client performs no internal request queueing or rate limiting.
|
|
119
188
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
and
|
|
123
|
-
|
|
189
|
+
#### Conversion options (`DoclingOptions`)
|
|
190
|
+
|
|
191
|
+
Configurable on the factory as defaults and overridable per call. Invalid option keys or values throw a `TypeError` synchronously on the factory, or reject with a `TypeError` on client calls before sending a request (`Option "x" is not supported`, `Invalid value for option "x"`; nested keys are named like `imageOptions.prefix`).
|
|
192
|
+
|
|
193
|
+
| Option | Type | Default | Description |
|
|
194
|
+
|---|---|---|---|
|
|
195
|
+
| `headingHierarchy` | `boolean` | `true` | Infers heading levels from bookmarks, numbering, and font styles. When `false`, all headings are level 1 |
|
|
196
|
+
| `formulaEnrichment` | `boolean` | `true` | Extracts math formulas as LaTeX via dedicated model. When `false`, formula text is empty and Markdown shows `<!-- formula-not-decoded -->` |
|
|
197
|
+
| `codeEnrichment` | `boolean` | `false` | Extracts code listings via dedicated model (slower) |
|
|
198
|
+
| `chartExtraction` | `boolean` | `false` | Extracts charts and plots as structured data via vision model (slower) |
|
|
199
|
+
| `pipeline` | `'standard' \| 'vlm'` | `'standard'` | Processing pipeline. `'vlm'` runs a vision-language model per page (slow) |
|
|
200
|
+
| `pdfBackend` | `'docling_parse' \| 'pypdfium2'` | `'docling_parse'` | Text extraction engine. `'pypdfium2'` handles ligatures and word spaces better but omits page headers/footers |
|
|
201
|
+
| `ocr` | `boolean` | `true` | Runs OCR on scanned pages and raster graphics. Image input always runs OCR |
|
|
202
|
+
| `forceOcr` | `boolean` | `false` | Forces full-page OCR across all pages and drops the PDF text layer (for PDFs with corrupt text encodings). Enables OCR even with `ocr: false`. Slower than standard OCR, so prefer using it per document. Ignored for image input |
|
|
203
|
+
| `ocrEngine` | `OcrEngine` | `'auto'` | OCR engine preset (`ocr_preset`), e.g. `'auto'`, `'rapidocr'`, `'easyocr'`, `'tesseract'`, `'tesserocr'`, `'ocrmac'`, or any non-empty preset ID allowed by the server. An unallowed preset is rejected by the server with `http` status 422 (see [Server capabilities](#server-capabilities)) |
|
|
204
|
+
|
|
205
|
+
#### Factory-only options
|
|
206
|
+
|
|
207
|
+
Configured in `options` of `createDoclingClient`. Passing these per-call rejects with a `TypeError: Option "x" is not supported`. Use a separate client instance if different values are required.
|
|
208
|
+
|
|
209
|
+
| Option | Type | Default | Description |
|
|
210
|
+
|---|---|---|---|
|
|
211
|
+
| `ocrLang` | `string[]` | engine default | BCP-47 language priority codes, e.g. `['de', 'en-US']`. `[]` uses the engine default |
|
|
212
|
+
| `pageRange` | `[number, number]` | all pages | Inclusive 1-based page range `[from, to]` |
|
|
213
|
+
| `documentTimeout` | `number` | server default | Server-side conversion timeout in seconds |
|
|
214
|
+
|
|
215
|
+
#### Per-call options
|
|
216
|
+
|
|
217
|
+
Options passed to individual conversion calls. These cannot be set in factory `options` (the factory throws a synchronous `TypeError: Option "x" is not supported`).
|
|
218
|
+
|
|
219
|
+
| Option | Applicable Calls | Type | Default | Description |
|
|
220
|
+
|---|---|---|---|---|
|
|
221
|
+
| `images` | Markdown calls | `'placeholder' \| 'none' \| 'extract'` | `'placeholder'` | Markdown image handling mode (see [Images in Markdown](#images-in-markdown)) |
|
|
222
|
+
| `imageOptions` | Markdown calls | `{ prefix: string, omitSmall?: boolean }` | none | Link prefix and size filtering. Required with `images: 'extract'`; rejected otherwise |
|
|
223
|
+
| `images` | Document calls | `'embedded' \| 'placeholder'` | `'embedded'` | AST picture image mode (see [Images in the DoclingDocument](#images-in-the-doclingdocument)) |
|
|
224
|
+
| `pageImages` | Document calls | `boolean` | `false` | Renders pages as images, decoded into `data.pageImages` (see [Page images](#page-images)) |
|
|
225
|
+
| `signal` | All calls | `AbortSignal` | none | Cancels the request or overall operation on abort |
|
|
226
|
+
| `pollMs` | `runMarkdown`, `runDocument`, `waitForJob` | `number` | factory `pollMs` (`10`) | Polling interval in milliseconds (integer `1..2147483647`). Rejected by `convert*`, `submit*`, and `check` |
|
|
227
|
+
|
|
228
|
+
#### Pinned server settings
|
|
229
|
+
|
|
230
|
+
The client enforces explicit server settings for consistent output:
|
|
231
|
+
- **Table structure**: Accurate TableFormer model is always enabled (`do_table_structure: true`, `table_mode: 'accurate'`, `table_structure_preset: 'tableformer_v1_accurate'`, `table_cell_matching: true`).
|
|
232
|
+
- **Resolution**: Pictures and page images render at 144 DPI (`images_scale: 2`, exported as `PAGE_IMAGE_SCALE`). Note: OCR runs independently at docling's internal 216 DPI.
|
|
233
|
+
- **Markdown format**: Compact tables are enabled (`md_compact_tables: true`) without page break placeholders (`md_page_break_placeholder: ''`). For document output, both parameters are omitted (`null`).
|
|
234
|
+
- **Model presets**: Pinned to `granite_docling` for `pipeline: 'vlm'`, `granite_vision_v4` for `chartExtraction`, and `codeformulav2` for code and formula enrichment. Picture classification and description remain disabled.
|
|
124
235
|
|
|
125
236
|
### Input formats
|
|
126
237
|
|
|
127
|
-
|
|
238
|
+
Input is supplied as a `Uint8Array` (Node `Buffer` instances are compatible). File formats are detected directly from header magic bytes; unsupported formats immediately resolve to `invalid_input` without sending an HTTP request:
|
|
128
239
|
|
|
129
|
-
|
|
|
240
|
+
| Format | Detection Signature | Sent As |
|
|
130
241
|
|---|---|---|
|
|
131
242
|
| PDF | `%PDF-` within the first 1024 bytes | `from_formats=pdf`, `document.pdf` |
|
|
132
|
-
| PNG
|
|
243
|
+
| PNG | `89 50 4E 47 0D 0A 1A 0A` at byte 0 | `from_formats=image`, `document.png` |
|
|
244
|
+
| JPEG | `FF D8 FF` at byte 0 | `from_formats=image`, `document.jpg` |
|
|
245
|
+
| TIFF | Little-endian `49 49 2A 00` or big-endian `4D 4D 00 2A` at byte 0 | `from_formats=image`, `document.tiff` |
|
|
246
|
+
| WebP | `RIFF` at byte 0 and `WEBP` at byte 8 | `from_formats=image`, `document.webp` |
|
|
133
247
|
|
|
134
|
-
|
|
135
|
-
on for images and never full-page: `ocr: false` would return no text, and `forceOcr: true` merges words (`stepsand`),
|
|
136
|
-
so both are ignored for image input. Use it e.g. to re-read a crop of a page whose text layer is broken. Text only
|
|
137
|
-
comes back if the server has a working OCR engine. PDF-only options (`pdfBackend`, `pageRange`) have no effect on
|
|
138
|
-
images.
|
|
248
|
+
Image inputs are converted as single-page documents. Docling runs layout detection and OCR on the image (`ocrLang` applies). Because images contain no embedded text layer, text extraction requires a working OCR engine on the server. OCR is always active for images: `ocr: false` and `forceOcr: true` are ignored (forcing full-page OCR on images merges words like `stepsand`). PDF-specific options (`pdfBackend`, `pageRange`) do not affect images.
|
|
139
249
|
|
|
140
250
|
### Images in the DoclingDocument
|
|
141
251
|
|
|
142
|
-
| `images` |
|
|
252
|
+
| `images` | Effect |
|
|
143
253
|
|---|---|
|
|
144
|
-
| `'embedded'` (default) | `pictures[].image.uri`
|
|
145
|
-
| `'placeholder'` | `pictures[].image` is `null
|
|
254
|
+
| `'embedded'` (default) | `pictures[].image.uri` contains a `data:image/png;base64,…` URI. Pictures retain bounding boxes, captions, and dimensions |
|
|
255
|
+
| `'placeholder'` | `pictures[].image` is `null`. Picture entries, bounding boxes, and captions remain intact; document payload is significantly smaller |
|
|
146
256
|
|
|
147
|
-
|
|
148
|
-
document. `isSmallImage(picture.image.size)` applies the same size filter as `omitSmall` (see below).
|
|
257
|
+
Base64 image data remains inside the document JSON. `isSmallImage(picture.image.size)` can be used to filter icons and decorative elements using the same heuristic as `omitSmall`.
|
|
149
258
|
|
|
150
259
|
### Page images
|
|
151
260
|
|
|
152
|
-
`pageImages: true` (
|
|
153
|
-
client moves them out of the document: `document.pages[n].image` is always `null`, so the JSON stays small, and the
|
|
154
|
-
images come back decoded in `data.pageImages`, in page order:
|
|
261
|
+
Setting `pageImages: true` (document conversions only; default `false`) requests page renderings from docling (`include_page_images`). The client strips embedded base64 data from `document.pages[n].image` (setting it to `null`) and returns decoded raw PNG images in `data.pageImages`:
|
|
155
262
|
|
|
156
263
|
```ts
|
|
264
|
+
import { writeFile } from 'node:fs/promises';
|
|
265
|
+
|
|
157
266
|
const res = await docling.convertDocument(pdf, { pageImages: true, images: 'placeholder' });
|
|
158
267
|
if (res.ok) {
|
|
159
|
-
await writeFile(`out/${docId}.json`, JSON.stringify(res.data.document)); //
|
|
268
|
+
await writeFile(`out/${docId}.json`, JSON.stringify(res.data.document)); // Small JSON without embedded page images
|
|
160
269
|
for (const image of res.data.pageImages) {
|
|
161
|
-
await writeFile(`out/${docId}-p${image.page}.png`, image.bytes);
|
|
270
|
+
await writeFile(`out/${docId}-p${image.page}.png`, image.bytes); // { page, mimeType, width, height, dpi, bytes }
|
|
162
271
|
}
|
|
163
272
|
}
|
|
164
273
|
```
|
|
165
274
|
|
|
166
|
-
- `page
|
|
167
|
-
- `width` and `height
|
|
168
|
-
|
|
169
|
-
-
|
|
170
|
-
-
|
|
171
|
-
|
|
172
|
-
|
|
275
|
+
- `page`: 1-based page number (absolute, preserved across `pageRange`); `dpi` is the resolution reported by docling (typically 144), or `0` if not reported.
|
|
276
|
+
- `width` and `height`: Pixel dimensions parsed from the PNG header (or docling's `image.size`). Scaled at 2 px per PDF point (an A4 page is ~1190 × 1684 px, ~0.4–0.6 MB PNG).
|
|
277
|
+
- Independent of `images`: `{ images: 'placeholder', pageImages: true }` drops figure raster data while returning page images.
|
|
278
|
+
- Job persistence: `submitDocument(pdf, { pageImages: true })` requires no extra storage; `check()` and `waitForJob()` return decoded page images.
|
|
279
|
+
- Any page image whose URI is not a base64 data URI, or contains invalid or empty data, is omitted from `pageImages`, retained in `document.pages[].image` as docling sent it, and reported in `data.warnings` with code `page_image_not_decoded` (`details.page`).
|
|
280
|
+
|
|
281
|
+
#### Mapping bounding boxes to page images (`toPageImageBox`)
|
|
173
282
|
|
|
174
|
-
|
|
175
|
-
onto its page image as `{ page, x, y, width, height }` in pixels with a top-left origin (unrounded), ready to store
|
|
176
|
-
next to the page image file or to crop with:
|
|
283
|
+
Docling documents store coordinates in PDF points, typically with a `BOTTOMLEFT` origin. The helper `toPageImageBox` maps any provenance bounding box to top-left pixel coordinates matching rendered page images:
|
|
177
284
|
|
|
178
285
|
```ts
|
|
286
|
+
import { toPageImageBox } from 'docling-serve-client';
|
|
287
|
+
|
|
179
288
|
for (const item of res.data.document.texts) {
|
|
180
289
|
for (const prov of item.prov) {
|
|
181
|
-
const box = toPageImageBox(res.data.document, prov); //
|
|
290
|
+
const box = toPageImageBox(res.data.document, prov); // { page, x, y, width, height }
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Table cells provide their own bbox (with TOPLEFT origin) and belong to their table's page:
|
|
295
|
+
for (const table of res.data.document.tables) {
|
|
296
|
+
const pageNo = table.prov[0]?.page_no ?? 1;
|
|
297
|
+
for (const row of table.data.grid) {
|
|
298
|
+
for (const cell of row) {
|
|
299
|
+
if (cell.bbox) {
|
|
300
|
+
const box = toPageImageBox(res.data.document, { page_no: pageNo, bbox: cell.bbox });
|
|
301
|
+
}
|
|
302
|
+
}
|
|
182
303
|
}
|
|
183
304
|
}
|
|
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
305
|
```
|
|
187
306
|
|
|
188
|
-
|
|
307
|
+
`toPageImageBox` calculates pixel coordinates using `PAGE_IMAGE_SCALE` (`2`). It works on any conversion result, even when `pageImages: false` was used. Returns `undefined` if page dimensions or coordinates are missing or invalid.
|
|
308
|
+
|
|
309
|
+
### DoclingDocument structure
|
|
310
|
+
|
|
311
|
+
`convertDocument()` returns the full JSON AST (`doc.data.document`) typed as `DoclingDocument`:
|
|
312
|
+
|
|
313
|
+
- `texts`: Array of text blocks (`label`, `text`, `orig`, `prov: [{ page_no, bbox, charspan }]`). Common labels: `'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` when `formulaEnrichment` is enabled. Note on `prov.charspan`: `[start, end)` is in Python Unicode code points; slice in JavaScript using `Array.from(item.text).slice(start, end).join('')` instead of `item.text.slice(start, end)` to handle surrogate pairs.
|
|
314
|
+
- `tables`: Array of tables (`prov`, `data: { grid: TableCell[][], num_rows, num_cols }`). Cells provide `text`, `row_span`, `col_span`, `bbox`, `column_header`, and `row_header`.
|
|
315
|
+
- `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).
|
|
316
|
+
- `groups`: Structural groupings (`(ListGroup | InlineGroup | GroupItem)[]`) such as lists, inline formatting runs, chapters, or form sections.
|
|
317
|
+
- `key_value_items`: Key-value regions extracted from forms or documents (`graph: { cells: GraphCell[], links: GraphLink[] }`).
|
|
318
|
+
- `form_items`: Form regions and fields (`graph: { cells: GraphCell[], links: GraphLink[] }`).
|
|
319
|
+
- `pages`: Record of page metadata keyed by 1-based page number string (`"1"`, `"2"`, ...) with `size: { width, height }` in PDF points.
|
|
320
|
+
- `body`: Root container of content in logical reading order. Walk `body.children` (`{ $ref: string }` JSON pointers, e.g. `'#/texts/0'`) depth-first to traverse the document flow.
|
|
321
|
+
- `furniture`: Root container of headers, footers, and page numbers outside the body flow.
|
|
322
|
+
|
|
323
|
+
#### Navigating the AST in reading order
|
|
189
324
|
|
|
190
|
-
|
|
325
|
+
Root document flow is organized under `body.children`. Each child contains a JSON pointer reference (e.g. `#/texts/0`, `#/tables/1`, `#/groups/2`). References can be resolved and traversed like this:
|
|
191
326
|
|
|
192
|
-
|
|
327
|
+
```ts
|
|
328
|
+
import type { DoclingDocument } from 'docling-serve-client';
|
|
329
|
+
|
|
330
|
+
// Resolves a JSON pointer reference (e.g. '#/texts/0' or '#/body'):
|
|
331
|
+
function resolveRef(doc: DoclingDocument, ref: string) {
|
|
332
|
+
const parts = ref.replace(/^#\//, '').split('/');
|
|
333
|
+
if (parts.length === 1) return (doc as Record<string, any>)[parts[0]!];
|
|
334
|
+
return (doc as Record<string, any>)[parts[0]!]?.[Number(parts[1])];
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Walks body items in logical reading order:
|
|
338
|
+
function* walkReadingOrder(
|
|
339
|
+
doc: DoclingDocument,
|
|
340
|
+
node: { children: { $ref: string }[] } = doc.body,
|
|
341
|
+
): Generator<any> {
|
|
342
|
+
for (const child of node.children) {
|
|
343
|
+
const item = resolveRef(doc, child.$ref);
|
|
344
|
+
if (!item) continue;
|
|
345
|
+
if ('children' in item && Array.isArray(item.children) && item.children.length > 0) {
|
|
346
|
+
yield* walkReadingOrder(doc, item);
|
|
347
|
+
} else {
|
|
348
|
+
yield item;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Images in Markdown
|
|
355
|
+
|
|
356
|
+
| `images` | Effect |
|
|
193
357
|
|---|---|
|
|
194
|
-
| `'placeholder'` (default) | `<!-- image -->` marks
|
|
195
|
-
| `'none'` |
|
|
196
|
-
| `'extract'` |
|
|
358
|
+
| `'placeholder'` (default) | `<!-- image -->` comment marks figure locations as produced by docling |
|
|
359
|
+
| `'none'` | Removes image comments |
|
|
360
|
+
| `'extract'` | Extracts images as binary buffers in `data.images` and updates Markdown links to `<prefix><n>.<ext>` |
|
|
197
361
|
|
|
198
|
-
|
|
362
|
+
When `images: 'extract'` is selected, `imageOptions` is required:
|
|
199
363
|
|
|
200
364
|
```ts
|
|
365
|
+
import { writeFile } from 'node:fs/promises';
|
|
366
|
+
|
|
201
367
|
const res = await docling.convertMarkdown(pdf, {
|
|
202
368
|
images: 'extract',
|
|
203
|
-
imageOptions: { prefix: `images/${docId}-` }, // omitSmall
|
|
369
|
+
imageOptions: { prefix: `images/${docId}-` }, // omitSmall defaults to true
|
|
204
370
|
});
|
|
205
371
|
if (res.ok) {
|
|
206
|
-
await writeFile(`out/${docId}.md`, res.data.markdown);
|
|
372
|
+
await writeFile(`out/${docId}.md`, res.data.markdown); // e.g. 
|
|
207
373
|
for (const image of res.data.images) {
|
|
208
|
-
await writeFile(`out/${image.path}`, image.bytes);
|
|
374
|
+
await writeFile(`out/${image.path}`, image.bytes); // { path, mimeType, bytes, width, height }
|
|
209
375
|
}
|
|
210
376
|
}
|
|
211
377
|
```
|
|
212
378
|
|
|
213
|
-
- `n` starts at 1 and counts
|
|
214
|
-
|
|
215
|
-
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
- A picture with invalid or empty base64 data is removed and reported as an `image_not_decoded` warning
|
|
219
|
-
(`details.index`: 1-based position among all embedded pictures); the conversion still succeeds.
|
|
220
|
-
- A picture docling sent without image data keeps its `<!-- image -->` placeholder, as in `'placeholder'` mode.
|
|
221
|
-
- Removing a picture or placeholder keeps the blank line that separates the paragraphs around it.
|
|
379
|
+
- Image numbering `n` starts at 1 and counts only retained images. Extension `<ext>` is derived from MIME type (`png`, `jpg`, `gif`, `webp`, `svg`, `tiff`, `bmp`, or `bin`).
|
|
380
|
+
- `omitSmall` (default `true`): Drops small icons, bullets, and decorative lines. Small images meet any of: area < 15,000 px, long side < 200 px, or short side < 24 px (`isSmallImage`). Only PNG images have known dimensions (`readPngSize`); non-PNG formats are retained with `width` and `height` set to `0`.
|
|
381
|
+
- Corrupt or empty base64 image data is removed and recorded in `data.warnings` with code `image_not_decoded` (`details.index` is the 1-based index among embedded images).
|
|
382
|
+
- Figures emitted by docling without image data retain their `<!-- image -->` placeholder comment.
|
|
383
|
+
- Removing placeholders or small images preserves adjacent paragraph line spacing.
|
|
222
384
|
|
|
223
385
|
### Warnings
|
|
224
386
|
|
|
225
|
-
`data.warnings`
|
|
387
|
+
`data.warnings` contains non-fatal issues encountered during an otherwise successful conversion:
|
|
226
388
|
|
|
227
|
-
|
|
|
389
|
+
| Code | `details` | Description |
|
|
228
390
|
|---|---|---|
|
|
229
|
-
| `server` | `{ component, module, category, page }` |
|
|
230
|
-
| `image_not_decoded` | `{ index }` | Markdown
|
|
231
|
-
| `page_image_not_decoded` | `{ page }` |
|
|
391
|
+
| `server` | `{ component, module, category, page }` | Warning reported by docling-serve (e.g. single page failure or `document timeout exceeded`). `page` is the 1-based page number or `null` |
|
|
392
|
+
| `image_not_decoded` | `{ index }` | Undecodable embedded image in Markdown (`images: 'extract'`). `index` is 1-based |
|
|
393
|
+
| `page_image_not_decoded` | `{ page }` | Undecodable page image in Document output (`pageImages: true`). `page` is 1-based |
|
|
232
394
|
|
|
233
|
-
Pages
|
|
234
|
-
failed page.
|
|
395
|
+
Pages abandoned by the server (e.g. due to `documentTimeout`) contain no extracted content and trigger a `server` warning.
|
|
235
396
|
|
|
236
397
|
### Server versions
|
|
237
398
|
|
|
238
|
-
`data.versions`
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
399
|
+
`data.versions` contains version metadata reported by `GET /version` (e.g. `{ 'docling-serve': '1.38.2', docling: '2.135.0', 'docling-core': '2.101.1', ... }`), or `null` if unreachable.
|
|
400
|
+
|
|
401
|
+
Storing versions alongside converted documents aids reproducibility, as conversion output can vary across docling releases (`document.version` indicates the DoclingDocument schema version, whereas `data.versions` reflects server runtime packages). Errors from requests answered by the server (`http`, `not_found`, `conversion_failed`, `invalid_response`) also populate `error.versions`. The client caches versions across requests; if a version check fails (2 s timeout), `versions` is `null` and retried on the next request. Create a new client instance after upgrading docling-serve.
|
|
402
|
+
|
|
403
|
+
### Conversion settings
|
|
404
|
+
|
|
405
|
+
Results from `convert*()` and `run*()` (`data.settings`) and job objects from `submit*()` (`job.settings`) include a typed `DoclingSettings` record of all form parameters sent to docling-serve.
|
|
406
|
+
|
|
407
|
+
The client sends explicit values for every setting it controls, avoiding reliance on server defaults:
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
const res = await docling.convertMarkdown(pdf, { ocrEngine: 'rapidocr' });
|
|
411
|
+
if (res.ok) {
|
|
412
|
+
console.log(res.data.settings.ocrPreset); // 'rapidocr'
|
|
413
|
+
console.log(res.data.settings.tableStructurePreset); // 'tableformer_v1_accurate'
|
|
414
|
+
console.log(res.data.settings.vlmPipelinePreset); // null (pipeline is 'standard')
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
- Keys represent camelCase mappings of server form parameters (`ocrPreset` = `ocr_preset`).
|
|
419
|
+
- `null` indicates the parameter was omitted: Markdown-specific fields for JSON output, presets of inactive pipeline stages, or unset factory options (`pageRange`, `documentTimeout`). An empty `ocrLang` is omitted (server engine default).
|
|
420
|
+
- For image input, `doOcr: true` and `forceOcr: false` are recorded regardless of option flags.
|
|
421
|
+
- For PDF input with `forceOcr: true`, `doOcr: true` is recorded even when `ocr: false`.
|
|
422
|
+
- Server configuration outside request fields (e.g. default layout model) is not included; inspect `stages.layout` via `docling.capabilities()`.
|
|
245
423
|
|
|
246
|
-
###
|
|
424
|
+
### Server capabilities
|
|
247
425
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
426
|
+
`docling.capabilities({ signal? })` queries `GET /v1/capabilities` to inspect supported presets, stages, and limits. Used for diagnostics (e.g. checking available OCR engines); conversion calls do not invoke it automatically:
|
|
427
|
+
|
|
428
|
+
```ts
|
|
429
|
+
const caps = await docling.capabilities();
|
|
430
|
+
if (caps.ok) {
|
|
431
|
+
console.log(caps.data.stages.ocr?.presets.map((p) => p.id)); // ['auto', 'easyocr', 'rapidocr', 'tesseract', ...]
|
|
432
|
+
console.log(caps.data.stages.table_structure?.default); // 'tableformer_v1_accurate'
|
|
433
|
+
console.log(caps.data.limits.maxImagesScale); // 2 or null
|
|
434
|
+
console.log(caps.data.features.apiKeyRequired); // false
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
- Snake_case server keys are converted to camelCase, while `stages` keys retain their server names (`ocr`, `layout`, `table_structure`, `vlm_pipeline`, `chart_extraction`, etc.). Each stage provides its form parameter name (`option`), server default (`default`), and allowed presets (`presets: { id, name, description, source }[]`).
|
|
439
|
+
- Missing or mistyped payload properties fall back to safe empty defaults (`[]`, `''`, `null`, `false`).
|
|
440
|
+
- Capabilities do not guarantee runtime availability (e.g. `ocrmac` requires macOS).
|
|
441
|
+
- Older server versions lacking the endpoint return an `http` error with status `404`.
|
|
442
|
+
|
|
443
|
+
### Corrupt text encodings & special characters
|
|
444
|
+
|
|
445
|
+
If output displays corrupted umlauts or symbols (e.g. `fŸhrt`, `Nu§baum`, `…sterreich`), the PDF text layer uses an encoding incompatible with docling's parser (common in Mac Word documents with `/MacRomanEncoding`). Re-convert with `{ forceOcr: true }` (and configure `ocrLang` on the factory) to bypass the corrupt text layer and run full-page OCR.
|
|
251
446
|
|
|
252
447
|
### Errors
|
|
253
448
|
|
|
254
|
-
|
|
449
|
+
All client methods return a discriminated `Result<T>` union:
|
|
450
|
+
- `{ ok: true, data: T }` on success
|
|
451
|
+
- `{ ok: false, error: ConvertError }` on runtime failure
|
|
255
452
|
|
|
256
|
-
|
|
453
|
+
#### Error structure
|
|
454
|
+
|
|
455
|
+
Every `ConvertError` contains:
|
|
456
|
+
- `code`: Error classification (see table below)
|
|
457
|
+
- `message`: Diagnostic description
|
|
458
|
+
- `status`: Optional HTTP status code when answered by the server (e.g. `400`, `404`, `422`, `500`)
|
|
459
|
+
- `versions`: Server versions captured via `GET /version`, or `null`
|
|
460
|
+
- `details`: `{ errors: ServerError[]; failure: TaskFailure | null }` (present only when `code === 'conversion_failed'`). `errors` lists docling error items with `{ message, details: { component, module, category, page } }`; `failure` categorizes task failure as `{ category, phase, retryable }` (or `null`)
|
|
461
|
+
|
|
462
|
+
| Code | Cause |
|
|
257
463
|
|---|---|
|
|
258
|
-
| `invalid_input` | not a non-empty
|
|
259
|
-
| `network` |
|
|
260
|
-
| `aborted` |
|
|
261
|
-
| `http` |
|
|
262
|
-
| `not_found` | `check()`: `Unknown job id`
|
|
263
|
-
| `conversion_failed` |
|
|
264
|
-
| `invalid_response` |
|
|
464
|
+
| `invalid_input` | Input is not a non-empty `Uint8Array`, contains an unrecognized file signature, has a truncated PDF cross-reference table, is an invalid job object, or failed buffer preparation before upload. No request sent |
|
|
465
|
+
| `network` | Server unreachable or connection refused |
|
|
466
|
+
| `aborted` | Abort signal fired (including `AbortSignal.timeout()`), or factory `timeoutMs` expired |
|
|
467
|
+
| `http` | Non-2xx HTTP response, or single-request timeout (HTTP 504 after `DOCLING_SERVE_MAX_SYNC_WAIT`) |
|
|
468
|
+
| `not_found` | `check()` or `waitForJob()`: unknown or expired job ID (`Unknown job id` after server restart or expiration of 300 s result delay), or task purged between poll and fetch (`Result already fetched or expired`). Server message follows in parentheses |
|
|
469
|
+
| `conversion_failed` | Server failed to convert the document (or returned partial success without output content). Details provided in `error.details` |
|
|
470
|
+
| `invalid_response` | Unexpected response payload (unparseable JSON, missing task ID, missing output data, or body exceeding readable bounds) |
|
|
471
|
+
|
|
472
|
+
#### Error narrowing in TypeScript
|
|
473
|
+
|
|
474
|
+
TypeScript automatically narrows `error.details` based on `error.code`:
|
|
475
|
+
|
|
476
|
+
```ts
|
|
477
|
+
if (!res.ok) {
|
|
478
|
+
switch (res.error.code) {
|
|
479
|
+
case 'conversion_failed':
|
|
480
|
+
console.error('Conversion failed:', res.error.message);
|
|
481
|
+
console.error('Server errors:', res.error.details.errors);
|
|
482
|
+
console.error('Task failure:', res.error.details.failure);
|
|
483
|
+
break;
|
|
484
|
+
case 'http':
|
|
485
|
+
console.error(`HTTP error ${res.error.status}:`, res.error.message);
|
|
486
|
+
break;
|
|
487
|
+
case 'invalid_input':
|
|
488
|
+
console.error('Validation failed before request:', res.error.message);
|
|
489
|
+
break;
|
|
490
|
+
default:
|
|
491
|
+
console.error(res.error.code, res.error.message);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
```
|
|
265
495
|
|
|
266
|
-
|
|
267
|
-
`{ message, details }` (component, module, category, page); `failure` is docling's task classification
|
|
268
|
-
`{ category, phase, retryable }` for async jobs, or `null`.
|
|
496
|
+
#### Runtime errors vs programming errors
|
|
269
497
|
|
|
270
|
-
|
|
498
|
+
| Category | Causes | Handling |
|
|
499
|
+
|---|---|---|
|
|
500
|
+
| **Runtime failure** | Server down, invalid file bytes, HTTP 4xx/5xx, model crash, request timeout, abort signal | Resolves to `{ ok: false, error: ConvertError }` (never throws) |
|
|
501
|
+
| **Programming error** | Malformed base URL, invalid config types, unsupported call options, mutually exclusive options (e.g. `imageOptions` without `images: 'extract'`) | Factory throws `TypeError` synchronously; methods reject with `TypeError` before sending a request |
|
|
271
502
|
|
|
272
|
-
###
|
|
503
|
+
### Exported types, utilities & constants
|
|
273
504
|
|
|
274
|
-
|
|
275
|
-
# Install or reinstall docling-serve with CUDA 12.6
|
|
276
|
-
uv tool install --reinstall --torch-backend cu126 docling-serve
|
|
505
|
+
In addition to `createDoclingClient`, the package exports helper functions, constants, and TypeScript types:
|
|
277
506
|
|
|
278
|
-
|
|
279
|
-
|
|
507
|
+
```ts
|
|
508
|
+
import {
|
|
509
|
+
createDoclingClient,
|
|
510
|
+
toPageImageBox,
|
|
511
|
+
isSmallImage,
|
|
512
|
+
readPngSize,
|
|
513
|
+
PAGE_IMAGE_SCALE,
|
|
514
|
+
type CallOptions,
|
|
515
|
+
type CapabilityLimits,
|
|
516
|
+
type CapabilityPreset,
|
|
517
|
+
type CapabilityStage,
|
|
518
|
+
type ClientOptions,
|
|
519
|
+
type ConversionFailure,
|
|
520
|
+
type ConvertError,
|
|
521
|
+
type ConvertedDocument,
|
|
522
|
+
type ConvertedMarkdown,
|
|
523
|
+
type ConvertInput,
|
|
524
|
+
type DoclingClient,
|
|
525
|
+
type DoclingConfig,
|
|
526
|
+
type DoclingDocument,
|
|
527
|
+
type DoclingOptions,
|
|
528
|
+
type DoclingSettings,
|
|
529
|
+
type DocumentImageMode,
|
|
530
|
+
type DocumentJob,
|
|
531
|
+
type DocumentOptions,
|
|
532
|
+
type DocumentWarning,
|
|
533
|
+
type ErrorCode,
|
|
534
|
+
type ExtractedImage,
|
|
535
|
+
type ImageOptions,
|
|
536
|
+
type ImageSize,
|
|
537
|
+
type ImageWarning,
|
|
538
|
+
type Job,
|
|
539
|
+
type JobRef,
|
|
540
|
+
type JobState,
|
|
541
|
+
type MarkdownImageMode,
|
|
542
|
+
type MarkdownJob,
|
|
543
|
+
type MarkdownJobOutput,
|
|
544
|
+
type MarkdownOptions,
|
|
545
|
+
type MarkdownWarning,
|
|
546
|
+
type OcrEngine,
|
|
547
|
+
type PageImage,
|
|
548
|
+
type PageImageBox,
|
|
549
|
+
type PageImageWarning,
|
|
550
|
+
type PdfBackend,
|
|
551
|
+
type PdfInput,
|
|
552
|
+
type Pipeline,
|
|
553
|
+
type PollOptions,
|
|
554
|
+
type Result,
|
|
555
|
+
type ServerCapabilities,
|
|
556
|
+
type ServerDetails,
|
|
557
|
+
type ServerError,
|
|
558
|
+
type ServerVersions,
|
|
559
|
+
type ServerWarning,
|
|
560
|
+
type TaskFailure,
|
|
561
|
+
type WithSettings,
|
|
562
|
+
} from 'docling-serve-client';
|
|
280
563
|
```
|
|
281
564
|
|
|
565
|
+
- `toPageImageBox(document, prov)`: Maps a provenance entry `{ page_no, bbox }` to `{ page, x, y, width, height }` in top-left pixel coordinates. Returns `undefined` if page dimensions or coordinates are missing or invalid.
|
|
566
|
+
- `isSmallImage(size)`: Returns `true` if pixel dimensions match the `omitSmall` filter (area < 15,000 px, long side < 200 px, or short side < 24 px).
|
|
567
|
+
- `readPngSize(bytes)`: Extracts `{ width, height }` directly from a PNG's IHDR chunk. Returns `undefined` for invalid or non-PNG data.
|
|
568
|
+
- `PAGE_IMAGE_SCALE`: Constant `2` (144 DPI resolution used by docling page images and coordinate scaling).
|
|
569
|
+
|
|
570
|
+
## Running docling-serve
|
|
571
|
+
|
|
572
|
+
The client connects to a running [docling-serve](https://github.com/docling-project/docling-serve) instance:
|
|
573
|
+
|
|
282
574
|
```bash
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
575
|
+
# Install docling-serve (default / CPU)
|
|
576
|
+
uv tool install docling-serve
|
|
577
|
+
|
|
578
|
+
# Or with CUDA (check your driver with nvidia-smi; use matching PyTorch tag, e.g. cu124, cu126)
|
|
579
|
+
uv tool install --torch-backend <cuda-tag> docling-serve
|
|
580
|
+
|
|
581
|
+
# Or via Docker (CPU)
|
|
582
|
+
docker run -p 5001:5001 quay.io/ds4sd/docling-serve
|
|
583
|
+
|
|
584
|
+
# Or via Docker (NVIDIA GPU / CUDA)
|
|
585
|
+
docker run --gpus all -p 5001:5001 quay.io/ds4sd/docling-serve
|
|
586
|
+
|
|
587
|
+
# Start the local server (listens on http://127.0.0.1:5001 by default)
|
|
588
|
+
docling-serve run
|
|
287
589
|
```
|