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/dist/index.js CHANGED
@@ -250,6 +250,70 @@ function fail(error) {
250
250
  return { ok: false, error };
251
251
  }
252
252
 
253
+ // src/capabilities.ts
254
+ function readCapabilities(body) {
255
+ if (!isPlainObject(body)) {
256
+ return fail(ERR.INVALID_RESPONSE("Capabilities response is not a JSON object"));
257
+ }
258
+ const targets = objectOf(body.targets);
259
+ const features = objectOf(body.features);
260
+ return ok({
261
+ versions: Object.fromEntries(Object.entries(objectOf(body.versions)).filter((entry) => typeof entry[1] === "string")),
262
+ stages: Object.fromEntries(Object.entries(objectOf(body.stages)).map(([name, stage]) => [name, readStage(objectOf(stage))])),
263
+ sources: stringsOf(body.sources),
264
+ targets: { allowed: stringsOf(targets.allowed), default: stringOf(targets.default) },
265
+ outputFormats: stringsOf(body.output_formats),
266
+ imageExportModes: stringsOf(body.image_export_modes),
267
+ limits: readLimits(objectOf(body.limits)),
268
+ features: {
269
+ apiKeyRequired: features.api_key_required === true,
270
+ artifactStorage: features.artifact_storage === true,
271
+ websocket: features.websocket === true
272
+ }
273
+ });
274
+ }
275
+ function readStage(stage) {
276
+ const presets = [];
277
+ for (const item of Array.isArray(stage.presets) ? stage.presets : []) {
278
+ const preset = objectOf(item);
279
+ if (typeof preset.id === "string") {
280
+ presets.push({
281
+ id: preset.id,
282
+ name: stringOf(preset.name),
283
+ description: typeof preset.description === "string" ? preset.description : null,
284
+ source: stringOf(preset.source)
285
+ });
286
+ }
287
+ }
288
+ return {
289
+ option: stringOf(stage.option),
290
+ customConfigOption: typeof stage.custom_config_option === "string" ? stage.custom_config_option : null,
291
+ default: stringOf(stage.default),
292
+ presets
293
+ };
294
+ }
295
+ function readLimits(limits) {
296
+ return {
297
+ maxDocumentTimeout: numberOf(limits.max_document_timeout),
298
+ maxImagesScale: numberOf(limits.max_images_scale),
299
+ maxSourcesPerRequest: numberOf(limits.max_sources_per_request),
300
+ maxNumPages: numberOf(limits.max_num_pages),
301
+ maxFileSize: numberOf(limits.max_file_size)
302
+ };
303
+ }
304
+ function objectOf(value) {
305
+ return isPlainObject(value) ? value : {};
306
+ }
307
+ function stringsOf(value) {
308
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
309
+ }
310
+ function stringOf(value) {
311
+ return typeof value === "string" ? value : "";
312
+ }
313
+ function numberOf(value) {
314
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
315
+ }
316
+
253
317
  // src/core/http.ts
254
318
  var STRING_TOO_LONG = "ERR_STRING_TOO_LONG";
255
319
  var MATCH_OUT_OF_MEMORY = /out of memory/i;
@@ -368,7 +432,8 @@ var DEFAULT_OPTIONS = Object.freeze({
368
432
  pipeline: "standard",
369
433
  pdfBackend: "docling_parse",
370
434
  ocr: true,
371
- forceOcr: false
435
+ forceOcr: false,
436
+ ocrEngine: "auto"
372
437
  });
373
438
  var CALL_OPTION_RULES = {
374
439
  headingHierarchy: isBoolean,
@@ -378,7 +443,8 @@ var CALL_OPTION_RULES = {
378
443
  pipeline: (value) => isOneOf(value, PIPELINES),
379
444
  pdfBackend: (value) => isOneOf(value, PDF_BACKENDS),
380
445
  ocr: isBoolean,
381
- forceOcr: isBoolean
446
+ forceOcr: isBoolean,
447
+ ocrEngine: (value) => typeof value === "string" && value !== ""
382
448
  };
383
449
  var CLIENT_OPTION_RULES = {
384
450
  ...CALL_OPTION_RULES,
@@ -635,10 +701,11 @@ function isPageNumber(value) {
635
701
  }
636
702
 
637
703
  // src/client.ts
638
- var FIXED_FORM_FIELDS = [
639
- ["do_table_structure", "true"],
640
- ["table_mode", "accurate"]
641
- ];
704
+ var TABLE_STRUCTURE_PRESET = "tableformer_v1_accurate";
705
+ var VLM_PIPELINE_PRESET = "granite_docling";
706
+ var CHART_EXTRACTION_PRESET = "granite_vision_v4";
707
+ var CODE_FORMULA_PRESET = "codeformulav2";
708
+ var MATCH_UPPER_CASE = /[A-Z]/g;
642
709
  var INVALID_INPUT = "Expected a non-empty PDF, PNG, JPEG, TIFF or WebP as Uint8Array";
643
710
  var SERVER_ANSWERED = new Set([
644
711
  "http",
@@ -657,13 +724,18 @@ function createDoclingClient(config) {
657
724
  convertDocument,
658
725
  submitMarkdown,
659
726
  submitDocument,
660
- check
727
+ check,
728
+ capabilities
661
729
  };
662
730
  async function convertMarkdown(input, options) {
663
731
  const call = resolveMarkdownCall(defaults, options);
664
732
  const fields = { format: "md", embedImages: call.output.images === "extract", pageImages: false };
665
733
  const res = await post("/v1/convert/file", input, call.options, fields, call.signal);
666
- return res.ok ? withVersions(readMarkdown(res.data, call.output)) : res;
734
+ if (!res.ok) {
735
+ return res;
736
+ }
737
+ const converted = await withVersions(readMarkdown(res.data.body, call.output));
738
+ return converted.ok ? ok({ ...converted.data, settings: res.data.settings }) : converted;
667
739
  }
668
740
  async function convertDocument(input, options) {
669
741
  const call = resolveDocumentCall(defaults, options);
@@ -673,13 +745,17 @@ function createDoclingClient(config) {
673
745
  pageImages: call.pageImages
674
746
  };
675
747
  const res = await post("/v1/convert/file", input, call.options, fields, call.signal);
676
- return res.ok ? withVersions(readDocument(res.data)) : res;
748
+ if (!res.ok) {
749
+ return res;
750
+ }
751
+ const converted = await withVersions(readDocument(res.data.body));
752
+ return converted.ok ? ok({ ...converted.data, settings: res.data.settings }) : converted;
677
753
  }
678
754
  async function submitMarkdown(input, options) {
679
755
  const call = resolveMarkdownCall(defaults, options);
680
756
  const fields = { format: "md", embedImages: call.output.images === "extract", pageImages: false };
681
- const id = await submit(input, call.options, fields, call.signal);
682
- return id.ok ? ok({ kind: "markdown", id: id.data, output: call.output }) : id;
757
+ const task = await submit(input, call.options, fields, call.signal);
758
+ return task.ok ? ok({ kind: "markdown", id: task.data.id, output: call.output, settings: task.data.settings }) : task;
683
759
  }
684
760
  async function submitDocument(input, options) {
685
761
  const call = resolveDocumentCall(defaults, options);
@@ -688,8 +764,8 @@ function createDoclingClient(config) {
688
764
  embedImages: call.images === "embedded",
689
765
  pageImages: call.pageImages
690
766
  };
691
- const id = await submit(input, call.options, fields, call.signal);
692
- return id.ok ? ok({ kind: "document", id: id.data }) : id;
767
+ const task = await submit(input, call.options, fields, call.signal);
768
+ return task.ok ? ok({ kind: "document", id: task.data.id, settings: task.data.settings }) : task;
693
769
  }
694
770
  async function check(job, options) {
695
771
  const { signal } = resolveCheckOptions(options);
@@ -733,12 +809,21 @@ function createDoclingClient(config) {
733
809
  return failWithVersions(ERR.INVALID_RESPONSE(`Unexpected task status: ${String(task.task_status)}`));
734
810
  }
735
811
  }
812
+ async function capabilities(options) {
813
+ const { signal } = resolveCheckOptions(options);
814
+ const res = await get("/v1/capabilities", signal);
815
+ if (!res.ok) {
816
+ return failWithVersions(res.error);
817
+ }
818
+ const read = readCapabilities(res.data);
819
+ return read.ok ? read : failWithVersions(read.error);
820
+ }
736
821
  async function submit(input, options, fields, signal) {
737
822
  const res = await post("/v1/convert/file/async", input, options, fields, signal);
738
823
  if (!res.ok) {
739
824
  return res;
740
825
  }
741
- const id = res.data?.task_id;
826
+ const id = res.data.body?.task_id;
742
827
  if (readText(id) === undefined) {
743
828
  return failWithVersions(ERR.INVALID_RESPONSE("Response has no task_id"));
744
829
  }
@@ -746,16 +831,17 @@ function createDoclingClient(config) {
746
831
  const shown = JSON.stringify(id).slice(0, MAX_SHOWN_ID_LENGTH);
747
832
  return failWithVersions(ERR.INVALID_RESPONSE(`Response has an unusable task_id: ${shown}`));
748
833
  }
749
- return ok(id);
834
+ return ok({ id, settings: res.data.settings });
750
835
  }
751
836
  async function post(route, input, options, fields, signal) {
752
837
  const format = readInputFormat(input);
753
838
  if (!format.ok) {
754
839
  return format;
755
840
  }
841
+ const settings = buildSettings(format.data, options, fields);
756
842
  let body;
757
843
  try {
758
- body = buildFormData(input, format.data, options, fields);
844
+ body = buildFormData(input, format.data, settings);
759
845
  } catch (error) {
760
846
  return fail(ERR.INVALID_INPUT(`Input could not be prepared for upload: ${errorMessage(error)}`));
761
847
  }
@@ -766,7 +852,7 @@ function createDoclingClient(config) {
766
852
  body,
767
853
  ...limited === undefined ? {} : { signal: limited }
768
854
  });
769
- return res.ok ? res : failWithVersions(res.error);
855
+ return res.ok ? ok({ body: res.data, settings }) : failWithVersions(res.error);
770
856
  }
771
857
  function get(route, signal, limit = true) {
772
858
  const limited = limit ? withTimeout(signal, timeoutMs) : signal;
@@ -822,43 +908,51 @@ function readInputFormat(input) {
822
908
  const offset = format.fromFormat === "pdf" ? findTruncatedXref(bytes) : undefined;
823
909
  return offset === undefined ? ok(format) : fail(ERR.INVALID_INPUT(`PDF is truncated: cross-reference offset ${offset} lies past the end of the file (${bytes.length} bytes)`));
824
910
  }
825
- function buildFormData(input, { fromFormat, mimeType, fileName }, options, { format, embedImages, pageImages }) {
911
+ function buildSettings({ fromFormat }, options, { format, embedImages, pageImages }) {
912
+ const isImage = fromFormat === "image";
913
+ const isMarkdown = format === "md";
914
+ return {
915
+ fromFormats: fromFormat,
916
+ toFormats: format,
917
+ imageExportMode: embedImages || pageImages ? "embedded" : "placeholder",
918
+ includeImages: embedImages,
919
+ includePageImages: pageImages,
920
+ imagesScale: PAGE_IMAGE_SCALE,
921
+ mdCompactTables: isMarkdown ? true : null,
922
+ mdPageBreakPlaceholder: isMarkdown ? "" : null,
923
+ doOcr: isImage || options.ocr,
924
+ forceOcr: !isImage && options.forceOcr,
925
+ ocrPreset: options.ocrEngine,
926
+ ocrLang: [...options.ocrLang ?? []],
927
+ pdfBackend: options.pdfBackend,
928
+ pipeline: options.pipeline,
929
+ vlmPipelinePreset: options.pipeline === "vlm" ? VLM_PIPELINE_PRESET : null,
930
+ doTableStructure: true,
931
+ tableMode: "accurate",
932
+ tableStructurePreset: TABLE_STRUCTURE_PRESET,
933
+ tableCellMatching: true,
934
+ doPdfHeadingHierarchy: options.headingHierarchy,
935
+ doFormulaEnrichment: options.formulaEnrichment,
936
+ doCodeEnrichment: options.codeEnrichment,
937
+ codeFormulaPreset: options.formulaEnrichment || options.codeEnrichment ? CODE_FORMULA_PRESET : null,
938
+ doChartExtraction: options.chartExtraction,
939
+ chartExtractionPreset: options.chartExtraction ? CHART_EXTRACTION_PRESET : null,
940
+ doPictureClassification: false,
941
+ doPictureDescription: false,
942
+ pageRange: options.pageRange === undefined ? null : [options.pageRange[0], options.pageRange[1]],
943
+ documentTimeout: options.documentTimeout ?? null,
944
+ abortOnError: false
945
+ };
946
+ }
947
+ function buildFormData(input, { mimeType, fileName }, settings) {
826
948
  const form = new FormData;
827
949
  const bytes = input.buffer instanceof ArrayBuffer ? input : new Uint8Array(input);
828
950
  form.append("files", new Blob([bytes], { type: mimeType }), fileName);
829
- form.append("from_formats", fromFormat);
830
- for (const [name, value] of FIXED_FORM_FIELDS) {
831
- form.append(name, value);
832
- }
833
- form.append("to_formats", format);
834
- if (format === "md") {
835
- form.append("md_compact_tables", "true");
836
- }
837
- form.append("include_images", String(embedImages));
838
- form.append("include_page_images", String(pageImages));
839
- form.append("image_export_mode", embedImages || pageImages ? "embedded" : "placeholder");
840
- form.append("images_scale", String(PAGE_IMAGE_SCALE));
841
- form.append("do_pdf_heading_hierarchy", String(options.headingHierarchy));
842
- form.append("do_formula_enrichment", String(options.formulaEnrichment));
843
- form.append("do_code_enrichment", String(options.codeEnrichment));
844
- if (options.formulaEnrichment || options.codeEnrichment) {
845
- form.append("code_formula_preset", "codeformulav2");
846
- }
847
- form.append("do_chart_extraction", String(options.chartExtraction));
848
- form.append("pipeline", options.pipeline);
849
- form.append("pdf_backend", options.pdfBackend);
850
- const isImage = fromFormat === "image";
851
- form.append("do_ocr", String(isImage || options.ocr));
852
- form.append("force_ocr", String(!isImage && options.forceOcr));
853
- for (const lang of options.ocrLang ?? []) {
854
- form.append("ocr_lang", lang);
855
- }
856
- if (options.pageRange !== undefined) {
857
- form.append("page_range", String(options.pageRange[0]));
858
- form.append("page_range", String(options.pageRange[1]));
859
- }
860
- if (options.documentTimeout !== undefined) {
861
- form.append("document_timeout", String(options.documentTimeout));
951
+ for (const [key, value] of Object.entries(settings)) {
952
+ const name = key.replace(MATCH_UPPER_CASE, (letter) => `_${letter.toLowerCase()}`);
953
+ for (const item of value === null ? [] : Array.isArray(value) ? value : [value]) {
954
+ form.append(name, String(item));
955
+ }
862
956
  }
863
957
  return form;
864
958
  }
@@ -870,5 +964,5 @@ export {
870
964
  toPageImageBox
871
965
  };
872
966
 
873
- //# debugId=B34739AC554F7F9C64756E2164756E21
967
+ //# debugId=A74469BA02A838B164756E2164756E21
874
968
  //# sourceMappingURL=index.js.map