@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 +119 -10
- 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 +119 -10
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.d.cts
CHANGED
|
@@ -130,6 +130,7 @@ declare class PDFParser {
|
|
|
130
130
|
private readonly enableImagePdfFallback;
|
|
131
131
|
private client;
|
|
132
132
|
private environment?;
|
|
133
|
+
private recoveryPromise;
|
|
133
134
|
constructor(options: Options);
|
|
134
135
|
init(): Promise<void>;
|
|
135
136
|
/**
|
|
@@ -137,6 +138,7 @@ declare class PDFParser {
|
|
|
137
138
|
* This typically indicates the Docling server has crashed.
|
|
138
139
|
*/
|
|
139
140
|
private isConnectionRefusedError;
|
|
141
|
+
private canRecoverLocalServer;
|
|
140
142
|
/**
|
|
141
143
|
* Restart the Docling server after it has crashed.
|
|
142
144
|
* This kills any existing process on the port, starts a new server,
|
|
@@ -146,6 +148,9 @@ declare class PDFParser {
|
|
|
146
148
|
* which guarantees this.port is defined.
|
|
147
149
|
*/
|
|
148
150
|
private restartServer;
|
|
151
|
+
private recoverServer;
|
|
152
|
+
isReady(): Promise<boolean>;
|
|
153
|
+
ensureReady(): Promise<void>;
|
|
149
154
|
private waitForServerReady;
|
|
150
155
|
parse(url: string, reportId: string, onComplete: ConversionCompleteCallback, cleanupAfterCallback: boolean, options: PDFConvertOptions, abortSignal?: AbortSignal): Promise<TokenUsageReport | null>;
|
|
151
156
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -130,6 +130,7 @@ declare class PDFParser {
|
|
|
130
130
|
private readonly enableImagePdfFallback;
|
|
131
131
|
private client;
|
|
132
132
|
private environment?;
|
|
133
|
+
private recoveryPromise;
|
|
133
134
|
constructor(options: Options);
|
|
134
135
|
init(): Promise<void>;
|
|
135
136
|
/**
|
|
@@ -137,6 +138,7 @@ declare class PDFParser {
|
|
|
137
138
|
* This typically indicates the Docling server has crashed.
|
|
138
139
|
*/
|
|
139
140
|
private isConnectionRefusedError;
|
|
141
|
+
private canRecoverLocalServer;
|
|
140
142
|
/**
|
|
141
143
|
* Restart the Docling server after it has crashed.
|
|
142
144
|
* This kills any existing process on the port, starts a new server,
|
|
@@ -146,6 +148,9 @@ declare class PDFParser {
|
|
|
146
148
|
* which guarantees this.port is defined.
|
|
147
149
|
*/
|
|
148
150
|
private restartServer;
|
|
151
|
+
private recoverServer;
|
|
152
|
+
isReady(): Promise<boolean>;
|
|
153
|
+
ensureReady(): Promise<void>;
|
|
149
154
|
private waitForServerReady;
|
|
150
155
|
parse(url: string, reportId: string, onComplete: ConversionCompleteCallback, cleanupAfterCallback: boolean, options: PDFConvertOptions, abortSignal?: AbortSignal): Promise<TokenUsageReport | null>;
|
|
151
156
|
/**
|
package/dist/index.js
CHANGED
|
@@ -703,14 +703,32 @@ function validatePythonVersion(version, context = "system") {
|
|
|
703
703
|
}
|
|
704
704
|
|
|
705
705
|
// src/environment/python-environment.ts
|
|
706
|
+
var DOCLING_SERVE_PACKAGE = "docling-serve==1.16.1";
|
|
706
707
|
var DOCLING_RUNTIME_PACKAGES = [
|
|
707
|
-
"docling-
|
|
708
|
-
"docling
|
|
709
|
-
"docling==2.
|
|
710
|
-
"docling-core==2.74.0",
|
|
708
|
+
"docling-jobkit==1.16.0",
|
|
709
|
+
"docling==2.88.0",
|
|
710
|
+
"docling-core==2.73.0",
|
|
711
711
|
"docling-ibm-models==3.13.0",
|
|
712
712
|
"docling-parse==5.9.0"
|
|
713
713
|
];
|
|
714
|
+
var DOCLING_SERVE_RUNTIME_PACKAGES = [
|
|
715
|
+
"fastapi[standard]<0.130.0",
|
|
716
|
+
"httpx~=0.28",
|
|
717
|
+
"pydantic~=2.10",
|
|
718
|
+
"pydantic-settings~=2.4",
|
|
719
|
+
"python-multipart<0.1.0,>=0.0.14",
|
|
720
|
+
"typer~=0.12",
|
|
721
|
+
"uvicorn[standard]<1.0.0,>=0.29.0",
|
|
722
|
+
"websockets<17.0,>=14.0",
|
|
723
|
+
"scalar-fastapi>=1.0.3",
|
|
724
|
+
"docling-mcp>=1.0.0",
|
|
725
|
+
"opentelemetry-api==1.36.0",
|
|
726
|
+
"opentelemetry-sdk==1.36.0",
|
|
727
|
+
"opentelemetry-exporter-otlp==1.36.0",
|
|
728
|
+
"opentelemetry-instrumentation-fastapi==0.57b0",
|
|
729
|
+
"opentelemetry-exporter-prometheus==0.57b0",
|
|
730
|
+
"prometheus-client>=0.21.0"
|
|
731
|
+
];
|
|
714
732
|
var PythonEnvironment = class {
|
|
715
733
|
constructor(logger, venvPath) {
|
|
716
734
|
this.logger = logger;
|
|
@@ -722,6 +740,8 @@ var PythonEnvironment = class {
|
|
|
722
740
|
await this.upgradePip();
|
|
723
741
|
await this.installSetuptools();
|
|
724
742
|
await this.installPyArrow();
|
|
743
|
+
await this.installDoclingRuntimePackages();
|
|
744
|
+
await this.installDoclingServeRuntimePackages();
|
|
725
745
|
await this.installDoclingServe();
|
|
726
746
|
}
|
|
727
747
|
async checkPythonVersion() {
|
|
@@ -815,13 +835,31 @@ var PythonEnvironment = class {
|
|
|
815
835
|
throw new Error(`Failed to install pyarrow. Exit code: ${result.code}`);
|
|
816
836
|
}
|
|
817
837
|
}
|
|
818
|
-
async
|
|
838
|
+
async installDoclingRuntimePackages() {
|
|
819
839
|
const pipPath = join2(this.venvPath, "bin", "pip");
|
|
820
840
|
const result = await spawnAsync(pipPath, [
|
|
821
841
|
"install",
|
|
822
842
|
"--upgrade",
|
|
823
843
|
...DOCLING_RUNTIME_PACKAGES
|
|
824
844
|
]);
|
|
845
|
+
if (result.code !== 0) {
|
|
846
|
+
this.logger.error(
|
|
847
|
+
"[DoclingEnvironment] Failed to install docling runtime packages:",
|
|
848
|
+
result.stderr
|
|
849
|
+
);
|
|
850
|
+
throw new Error(
|
|
851
|
+
`Failed to install docling runtime packages. Exit code: ${result.code}`
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
async installDoclingServe() {
|
|
856
|
+
const pipPath = join2(this.venvPath, "bin", "pip");
|
|
857
|
+
const result = await spawnAsync(pipPath, [
|
|
858
|
+
"install",
|
|
859
|
+
"--upgrade",
|
|
860
|
+
"--no-deps",
|
|
861
|
+
DOCLING_SERVE_PACKAGE
|
|
862
|
+
]);
|
|
825
863
|
if (result.code !== 0) {
|
|
826
864
|
this.logger.error(
|
|
827
865
|
"[DoclingEnvironment] Failed to install docling-serve:",
|
|
@@ -832,6 +870,23 @@ var PythonEnvironment = class {
|
|
|
832
870
|
);
|
|
833
871
|
}
|
|
834
872
|
}
|
|
873
|
+
async installDoclingServeRuntimePackages() {
|
|
874
|
+
const pipPath = join2(this.venvPath, "bin", "pip");
|
|
875
|
+
const result = await spawnAsync(pipPath, [
|
|
876
|
+
"install",
|
|
877
|
+
"--upgrade",
|
|
878
|
+
...DOCLING_SERVE_RUNTIME_PACKAGES
|
|
879
|
+
]);
|
|
880
|
+
if (result.code !== 0) {
|
|
881
|
+
this.logger.error(
|
|
882
|
+
"[DoclingEnvironment] Failed to install docling-serve runtime packages:",
|
|
883
|
+
result.stderr
|
|
884
|
+
);
|
|
885
|
+
throw new Error(
|
|
886
|
+
`Failed to install docling-serve runtime packages. Exit code: ${result.code}`
|
|
887
|
+
);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
835
890
|
};
|
|
836
891
|
|
|
837
892
|
// src/environment/docling-environment.ts
|
|
@@ -3839,6 +3894,7 @@ var PDFParser = class {
|
|
|
3839
3894
|
enableImagePdfFallback;
|
|
3840
3895
|
client = null;
|
|
3841
3896
|
environment;
|
|
3897
|
+
recoveryPromise = null;
|
|
3842
3898
|
constructor(options) {
|
|
3843
3899
|
const {
|
|
3844
3900
|
logger,
|
|
@@ -3923,15 +3979,30 @@ var PDFParser = class {
|
|
|
3923
3979
|
*/
|
|
3924
3980
|
isConnectionRefusedError(error) {
|
|
3925
3981
|
if (error instanceof Error) {
|
|
3982
|
+
const errorWithMetadata = error;
|
|
3926
3983
|
if (error.message.includes("ECONNREFUSED")) {
|
|
3927
3984
|
return true;
|
|
3928
3985
|
}
|
|
3929
|
-
if (
|
|
3986
|
+
if (errorWithMetadata.code === "ECONNREFUSED") {
|
|
3930
3987
|
return true;
|
|
3931
3988
|
}
|
|
3989
|
+
return this.isConnectionRefusedError(errorWithMetadata.cause);
|
|
3990
|
+
}
|
|
3991
|
+
if (typeof error === "object" && error !== null) {
|
|
3992
|
+
const errorLike = error;
|
|
3993
|
+
if (errorLike.code === "ECONNREFUSED") {
|
|
3994
|
+
return true;
|
|
3995
|
+
}
|
|
3996
|
+
if (typeof errorLike.message === "string" && errorLike.message.includes("ECONNREFUSED")) {
|
|
3997
|
+
return true;
|
|
3998
|
+
}
|
|
3999
|
+
return this.isConnectionRefusedError(errorLike.cause);
|
|
3932
4000
|
}
|
|
3933
4001
|
return false;
|
|
3934
4002
|
}
|
|
4003
|
+
canRecoverLocalServer() {
|
|
4004
|
+
return !this.baseUrl && this.port !== void 0;
|
|
4005
|
+
}
|
|
3935
4006
|
/**
|
|
3936
4007
|
* Restart the Docling server after it has crashed.
|
|
3937
4008
|
* This kills any existing process on the port, starts a new server,
|
|
@@ -3961,6 +4032,46 @@ var PDFParser = class {
|
|
|
3961
4032
|
await this.waitForServerReady();
|
|
3962
4033
|
this.logger.info("[PDFParser] Server restarted successfully");
|
|
3963
4034
|
}
|
|
4035
|
+
async recoverServer(message) {
|
|
4036
|
+
this.logger.warn(message);
|
|
4037
|
+
if (!this.recoveryPromise) {
|
|
4038
|
+
this.recoveryPromise = this.restartServer().finally(() => {
|
|
4039
|
+
this.recoveryPromise = null;
|
|
4040
|
+
});
|
|
4041
|
+
} else {
|
|
4042
|
+
this.logger.warn("[PDFParser] Server recovery already in progress...");
|
|
4043
|
+
}
|
|
4044
|
+
await this.recoveryPromise;
|
|
4045
|
+
}
|
|
4046
|
+
async isReady() {
|
|
4047
|
+
if (!this.client) {
|
|
4048
|
+
return false;
|
|
4049
|
+
}
|
|
4050
|
+
try {
|
|
4051
|
+
await this.client.health();
|
|
4052
|
+
return true;
|
|
4053
|
+
} catch {
|
|
4054
|
+
return false;
|
|
4055
|
+
}
|
|
4056
|
+
}
|
|
4057
|
+
async ensureReady() {
|
|
4058
|
+
if (!this.client) {
|
|
4059
|
+
throw new Error(
|
|
4060
|
+
"PDFParser is not initialized. Call init() before checking readiness"
|
|
4061
|
+
);
|
|
4062
|
+
}
|
|
4063
|
+
try {
|
|
4064
|
+
await this.client.health();
|
|
4065
|
+
} catch (error) {
|
|
4066
|
+
if (this.canRecoverLocalServer()) {
|
|
4067
|
+
await this.recoverServer(
|
|
4068
|
+
"[PDFParser] Health check failed, attempting server recovery..."
|
|
4069
|
+
);
|
|
4070
|
+
return;
|
|
4071
|
+
}
|
|
4072
|
+
throw error;
|
|
4073
|
+
}
|
|
4074
|
+
}
|
|
3964
4075
|
async waitForServerReady() {
|
|
3965
4076
|
const maxAttempts = PDF_PARSER.MAX_HEALTH_CHECK_ATTEMPTS;
|
|
3966
4077
|
const checkInterval = PDF_PARSER.HEALTH_CHECK_INTERVAL_MS;
|
|
@@ -4044,18 +4155,16 @@ var PDFParser = class {
|
|
|
4044
4155
|
* Recovery is only attempted in local server mode (no baseUrl, port defined).
|
|
4045
4156
|
*/
|
|
4046
4157
|
async executeWithRecovery(fn, abortSignal) {
|
|
4047
|
-
const canRecover = !this.baseUrl && this.port !== void 0;
|
|
4048
4158
|
const maxAttempts = PDF_PARSER.MAX_SERVER_RECOVERY_ATTEMPTS;
|
|
4049
4159
|
const tryExecute = async (attempt) => {
|
|
4050
4160
|
try {
|
|
4051
4161
|
return await fn();
|
|
4052
4162
|
} catch (error) {
|
|
4053
4163
|
if (abortSignal?.aborted) throw error;
|
|
4054
|
-
if (
|
|
4055
|
-
this.
|
|
4164
|
+
if (this.canRecoverLocalServer() && this.isConnectionRefusedError(error) && attempt < maxAttempts) {
|
|
4165
|
+
await this.recoverServer(
|
|
4056
4166
|
"[PDFParser] Connection refused, attempting server recovery..."
|
|
4057
4167
|
);
|
|
4058
|
-
await this.restartServer();
|
|
4059
4168
|
return tryExecute(attempt + 1);
|
|
4060
4169
|
}
|
|
4061
4170
|
throw error;
|