@heripo/pdf-parser 0.1.24 → 0.1.25

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.cjs CHANGED
@@ -736,14 +736,32 @@ function validatePythonVersion(version, context = "system") {
736
736
  }
737
737
 
738
738
  // src/environment/python-environment.ts
739
+ var DOCLING_SERVE_PACKAGE = "docling-serve==1.16.1";
739
740
  var DOCLING_RUNTIME_PACKAGES = [
740
- "docling-serve==1.16.1",
741
- "docling-jobkit==1.17.0",
742
- "docling==2.90.0",
743
- "docling-core==2.74.0",
741
+ "docling-jobkit==1.16.0",
742
+ "docling==2.88.0",
743
+ "docling-core==2.73.0",
744
744
  "docling-ibm-models==3.13.0",
745
745
  "docling-parse==5.9.0"
746
746
  ];
747
+ var DOCLING_SERVE_RUNTIME_PACKAGES = [
748
+ "fastapi[standard]<0.130.0",
749
+ "httpx~=0.28",
750
+ "pydantic~=2.10",
751
+ "pydantic-settings~=2.4",
752
+ "python-multipart<0.1.0,>=0.0.14",
753
+ "typer~=0.12",
754
+ "uvicorn[standard]<1.0.0,>=0.29.0",
755
+ "websockets<17.0,>=14.0",
756
+ "scalar-fastapi>=1.0.3",
757
+ "docling-mcp>=1.0.0",
758
+ "opentelemetry-api==1.36.0",
759
+ "opentelemetry-sdk==1.36.0",
760
+ "opentelemetry-exporter-otlp==1.36.0",
761
+ "opentelemetry-instrumentation-fastapi==0.57b0",
762
+ "opentelemetry-exporter-prometheus==0.57b0",
763
+ "prometheus-client>=0.21.0"
764
+ ];
747
765
  var PythonEnvironment = class {
748
766
  constructor(logger, venvPath) {
749
767
  this.logger = logger;
@@ -755,6 +773,8 @@ var PythonEnvironment = class {
755
773
  await this.upgradePip();
756
774
  await this.installSetuptools();
757
775
  await this.installPyArrow();
776
+ await this.installDoclingRuntimePackages();
777
+ await this.installDoclingServeRuntimePackages();
758
778
  await this.installDoclingServe();
759
779
  }
760
780
  async checkPythonVersion() {
@@ -848,13 +868,31 @@ var PythonEnvironment = class {
848
868
  throw new Error(`Failed to install pyarrow. Exit code: ${result.code}`);
849
869
  }
850
870
  }
851
- async installDoclingServe() {
871
+ async installDoclingRuntimePackages() {
852
872
  const pipPath = (0, import_node_path2.join)(this.venvPath, "bin", "pip");
853
873
  const result = await spawnAsync(pipPath, [
854
874
  "install",
855
875
  "--upgrade",
856
876
  ...DOCLING_RUNTIME_PACKAGES
857
877
  ]);
878
+ if (result.code !== 0) {
879
+ this.logger.error(
880
+ "[DoclingEnvironment] Failed to install docling runtime packages:",
881
+ result.stderr
882
+ );
883
+ throw new Error(
884
+ `Failed to install docling runtime packages. Exit code: ${result.code}`
885
+ );
886
+ }
887
+ }
888
+ async installDoclingServe() {
889
+ const pipPath = (0, import_node_path2.join)(this.venvPath, "bin", "pip");
890
+ const result = await spawnAsync(pipPath, [
891
+ "install",
892
+ "--upgrade",
893
+ "--no-deps",
894
+ DOCLING_SERVE_PACKAGE
895
+ ]);
858
896
  if (result.code !== 0) {
859
897
  this.logger.error(
860
898
  "[DoclingEnvironment] Failed to install docling-serve:",
@@ -865,6 +903,23 @@ var PythonEnvironment = class {
865
903
  );
866
904
  }
867
905
  }
906
+ async installDoclingServeRuntimePackages() {
907
+ const pipPath = (0, import_node_path2.join)(this.venvPath, "bin", "pip");
908
+ const result = await spawnAsync(pipPath, [
909
+ "install",
910
+ "--upgrade",
911
+ ...DOCLING_SERVE_RUNTIME_PACKAGES
912
+ ]);
913
+ if (result.code !== 0) {
914
+ this.logger.error(
915
+ "[DoclingEnvironment] Failed to install docling-serve runtime packages:",
916
+ result.stderr
917
+ );
918
+ throw new Error(
919
+ `Failed to install docling-serve runtime packages. Exit code: ${result.code}`
920
+ );
921
+ }
922
+ }
868
923
  };
869
924
 
870
925
  // src/environment/docling-environment.ts
@@ -3856,6 +3911,7 @@ var PDFParser = class {
3856
3911
  enableImagePdfFallback;
3857
3912
  client = null;
3858
3913
  environment;
3914
+ recoveryPromise = null;
3859
3915
  constructor(options) {
3860
3916
  const {
3861
3917
  logger,
@@ -3940,15 +3996,30 @@ var PDFParser = class {
3940
3996
  */
3941
3997
  isConnectionRefusedError(error) {
3942
3998
  if (error instanceof Error) {
3999
+ const errorWithMetadata = error;
3943
4000
  if (error.message.includes("ECONNREFUSED")) {
3944
4001
  return true;
3945
4002
  }
3946
- if (error.cause instanceof Error && error.cause.message.includes("ECONNREFUSED")) {
4003
+ if (errorWithMetadata.code === "ECONNREFUSED") {
3947
4004
  return true;
3948
4005
  }
4006
+ return this.isConnectionRefusedError(errorWithMetadata.cause);
4007
+ }
4008
+ if (typeof error === "object" && error !== null) {
4009
+ const errorLike = error;
4010
+ if (errorLike.code === "ECONNREFUSED") {
4011
+ return true;
4012
+ }
4013
+ if (typeof errorLike.message === "string" && errorLike.message.includes("ECONNREFUSED")) {
4014
+ return true;
4015
+ }
4016
+ return this.isConnectionRefusedError(errorLike.cause);
3949
4017
  }
3950
4018
  return false;
3951
4019
  }
4020
+ canRecoverLocalServer() {
4021
+ return !this.baseUrl && this.port !== void 0;
4022
+ }
3952
4023
  /**
3953
4024
  * Restart the Docling server after it has crashed.
3954
4025
  * This kills any existing process on the port, starts a new server,
@@ -3978,6 +4049,46 @@ var PDFParser = class {
3978
4049
  await this.waitForServerReady();
3979
4050
  this.logger.info("[PDFParser] Server restarted successfully");
3980
4051
  }
4052
+ async recoverServer(message) {
4053
+ this.logger.warn(message);
4054
+ if (!this.recoveryPromise) {
4055
+ this.recoveryPromise = this.restartServer().finally(() => {
4056
+ this.recoveryPromise = null;
4057
+ });
4058
+ } else {
4059
+ this.logger.warn("[PDFParser] Server recovery already in progress...");
4060
+ }
4061
+ await this.recoveryPromise;
4062
+ }
4063
+ async isReady() {
4064
+ if (!this.client) {
4065
+ return false;
4066
+ }
4067
+ try {
4068
+ await this.client.health();
4069
+ return true;
4070
+ } catch {
4071
+ return false;
4072
+ }
4073
+ }
4074
+ async ensureReady() {
4075
+ if (!this.client) {
4076
+ throw new Error(
4077
+ "PDFParser is not initialized. Call init() before checking readiness"
4078
+ );
4079
+ }
4080
+ try {
4081
+ await this.client.health();
4082
+ } catch (error) {
4083
+ if (this.canRecoverLocalServer()) {
4084
+ await this.recoverServer(
4085
+ "[PDFParser] Health check failed, attempting server recovery..."
4086
+ );
4087
+ return;
4088
+ }
4089
+ throw error;
4090
+ }
4091
+ }
3981
4092
  async waitForServerReady() {
3982
4093
  const maxAttempts = PDF_PARSER.MAX_HEALTH_CHECK_ATTEMPTS;
3983
4094
  const checkInterval = PDF_PARSER.HEALTH_CHECK_INTERVAL_MS;
@@ -4061,18 +4172,16 @@ var PDFParser = class {
4061
4172
  * Recovery is only attempted in local server mode (no baseUrl, port defined).
4062
4173
  */
4063
4174
  async executeWithRecovery(fn, abortSignal) {
4064
- const canRecover = !this.baseUrl && this.port !== void 0;
4065
4175
  const maxAttempts = PDF_PARSER.MAX_SERVER_RECOVERY_ATTEMPTS;
4066
4176
  const tryExecute = async (attempt) => {
4067
4177
  try {
4068
4178
  return await fn();
4069
4179
  } catch (error) {
4070
4180
  if (abortSignal?.aborted) throw error;
4071
- if (canRecover && this.isConnectionRefusedError(error) && attempt < maxAttempts) {
4072
- this.logger.warn(
4181
+ if (this.canRecoverLocalServer() && this.isConnectionRefusedError(error) && attempt < maxAttempts) {
4182
+ await this.recoverServer(
4073
4183
  "[PDFParser] Connection refused, attempting server recovery..."
4074
4184
  );
4075
- await this.restartServer();
4076
4185
  return tryExecute(attempt + 1);
4077
4186
  }
4078
4187
  throw error;