@heripo/pdf-parser 0.1.23 → 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 +123 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +123 -6
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -736,6 +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";
|
|
740
|
+
var DOCLING_RUNTIME_PACKAGES = [
|
|
741
|
+
"docling-jobkit==1.16.0",
|
|
742
|
+
"docling==2.88.0",
|
|
743
|
+
"docling-core==2.73.0",
|
|
744
|
+
"docling-ibm-models==3.13.0",
|
|
745
|
+
"docling-parse==5.9.0"
|
|
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
|
+
];
|
|
739
765
|
var PythonEnvironment = class {
|
|
740
766
|
constructor(logger, venvPath) {
|
|
741
767
|
this.logger = logger;
|
|
@@ -747,6 +773,8 @@ var PythonEnvironment = class {
|
|
|
747
773
|
await this.upgradePip();
|
|
748
774
|
await this.installSetuptools();
|
|
749
775
|
await this.installPyArrow();
|
|
776
|
+
await this.installDoclingRuntimePackages();
|
|
777
|
+
await this.installDoclingServeRuntimePackages();
|
|
750
778
|
await this.installDoclingServe();
|
|
751
779
|
}
|
|
752
780
|
async checkPythonVersion() {
|
|
@@ -840,12 +868,30 @@ var PythonEnvironment = class {
|
|
|
840
868
|
throw new Error(`Failed to install pyarrow. Exit code: ${result.code}`);
|
|
841
869
|
}
|
|
842
870
|
}
|
|
871
|
+
async installDoclingRuntimePackages() {
|
|
872
|
+
const pipPath = (0, import_node_path2.join)(this.venvPath, "bin", "pip");
|
|
873
|
+
const result = await spawnAsync(pipPath, [
|
|
874
|
+
"install",
|
|
875
|
+
"--upgrade",
|
|
876
|
+
...DOCLING_RUNTIME_PACKAGES
|
|
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
|
+
}
|
|
843
888
|
async installDoclingServe() {
|
|
844
889
|
const pipPath = (0, import_node_path2.join)(this.venvPath, "bin", "pip");
|
|
845
890
|
const result = await spawnAsync(pipPath, [
|
|
846
891
|
"install",
|
|
847
892
|
"--upgrade",
|
|
848
|
-
"
|
|
893
|
+
"--no-deps",
|
|
894
|
+
DOCLING_SERVE_PACKAGE
|
|
849
895
|
]);
|
|
850
896
|
if (result.code !== 0) {
|
|
851
897
|
this.logger.error(
|
|
@@ -857,6 +903,23 @@ var PythonEnvironment = class {
|
|
|
857
903
|
);
|
|
858
904
|
}
|
|
859
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
|
+
}
|
|
860
923
|
};
|
|
861
924
|
|
|
862
925
|
// src/environment/docling-environment.ts
|
|
@@ -3848,6 +3911,7 @@ var PDFParser = class {
|
|
|
3848
3911
|
enableImagePdfFallback;
|
|
3849
3912
|
client = null;
|
|
3850
3913
|
environment;
|
|
3914
|
+
recoveryPromise = null;
|
|
3851
3915
|
constructor(options) {
|
|
3852
3916
|
const {
|
|
3853
3917
|
logger,
|
|
@@ -3932,15 +3996,30 @@ var PDFParser = class {
|
|
|
3932
3996
|
*/
|
|
3933
3997
|
isConnectionRefusedError(error) {
|
|
3934
3998
|
if (error instanceof Error) {
|
|
3999
|
+
const errorWithMetadata = error;
|
|
3935
4000
|
if (error.message.includes("ECONNREFUSED")) {
|
|
3936
4001
|
return true;
|
|
3937
4002
|
}
|
|
3938
|
-
if (
|
|
4003
|
+
if (errorWithMetadata.code === "ECONNREFUSED") {
|
|
3939
4004
|
return true;
|
|
3940
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);
|
|
3941
4017
|
}
|
|
3942
4018
|
return false;
|
|
3943
4019
|
}
|
|
4020
|
+
canRecoverLocalServer() {
|
|
4021
|
+
return !this.baseUrl && this.port !== void 0;
|
|
4022
|
+
}
|
|
3944
4023
|
/**
|
|
3945
4024
|
* Restart the Docling server after it has crashed.
|
|
3946
4025
|
* This kills any existing process on the port, starts a new server,
|
|
@@ -3970,6 +4049,46 @@ var PDFParser = class {
|
|
|
3970
4049
|
await this.waitForServerReady();
|
|
3971
4050
|
this.logger.info("[PDFParser] Server restarted successfully");
|
|
3972
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
|
+
}
|
|
3973
4092
|
async waitForServerReady() {
|
|
3974
4093
|
const maxAttempts = PDF_PARSER.MAX_HEALTH_CHECK_ATTEMPTS;
|
|
3975
4094
|
const checkInterval = PDF_PARSER.HEALTH_CHECK_INTERVAL_MS;
|
|
@@ -4053,18 +4172,16 @@ var PDFParser = class {
|
|
|
4053
4172
|
* Recovery is only attempted in local server mode (no baseUrl, port defined).
|
|
4054
4173
|
*/
|
|
4055
4174
|
async executeWithRecovery(fn, abortSignal) {
|
|
4056
|
-
const canRecover = !this.baseUrl && this.port !== void 0;
|
|
4057
4175
|
const maxAttempts = PDF_PARSER.MAX_SERVER_RECOVERY_ATTEMPTS;
|
|
4058
4176
|
const tryExecute = async (attempt) => {
|
|
4059
4177
|
try {
|
|
4060
4178
|
return await fn();
|
|
4061
4179
|
} catch (error) {
|
|
4062
4180
|
if (abortSignal?.aborted) throw error;
|
|
4063
|
-
if (
|
|
4064
|
-
this.
|
|
4181
|
+
if (this.canRecoverLocalServer() && this.isConnectionRefusedError(error) && attempt < maxAttempts) {
|
|
4182
|
+
await this.recoverServer(
|
|
4065
4183
|
"[PDFParser] Connection refused, attempting server recovery..."
|
|
4066
4184
|
);
|
|
4067
|
-
await this.restartServer();
|
|
4068
4185
|
return tryExecute(attempt + 1);
|
|
4069
4186
|
}
|
|
4070
4187
|
throw error;
|