@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.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,6 +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";
|
|
707
|
+
var DOCLING_RUNTIME_PACKAGES = [
|
|
708
|
+
"docling-jobkit==1.16.0",
|
|
709
|
+
"docling==2.88.0",
|
|
710
|
+
"docling-core==2.73.0",
|
|
711
|
+
"docling-ibm-models==3.13.0",
|
|
712
|
+
"docling-parse==5.9.0"
|
|
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
|
+
];
|
|
706
732
|
var PythonEnvironment = class {
|
|
707
733
|
constructor(logger, venvPath) {
|
|
708
734
|
this.logger = logger;
|
|
@@ -714,6 +740,8 @@ var PythonEnvironment = class {
|
|
|
714
740
|
await this.upgradePip();
|
|
715
741
|
await this.installSetuptools();
|
|
716
742
|
await this.installPyArrow();
|
|
743
|
+
await this.installDoclingRuntimePackages();
|
|
744
|
+
await this.installDoclingServeRuntimePackages();
|
|
717
745
|
await this.installDoclingServe();
|
|
718
746
|
}
|
|
719
747
|
async checkPythonVersion() {
|
|
@@ -807,12 +835,30 @@ var PythonEnvironment = class {
|
|
|
807
835
|
throw new Error(`Failed to install pyarrow. Exit code: ${result.code}`);
|
|
808
836
|
}
|
|
809
837
|
}
|
|
838
|
+
async installDoclingRuntimePackages() {
|
|
839
|
+
const pipPath = join2(this.venvPath, "bin", "pip");
|
|
840
|
+
const result = await spawnAsync(pipPath, [
|
|
841
|
+
"install",
|
|
842
|
+
"--upgrade",
|
|
843
|
+
...DOCLING_RUNTIME_PACKAGES
|
|
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
|
+
}
|
|
810
855
|
async installDoclingServe() {
|
|
811
856
|
const pipPath = join2(this.venvPath, "bin", "pip");
|
|
812
857
|
const result = await spawnAsync(pipPath, [
|
|
813
858
|
"install",
|
|
814
859
|
"--upgrade",
|
|
815
|
-
"
|
|
860
|
+
"--no-deps",
|
|
861
|
+
DOCLING_SERVE_PACKAGE
|
|
816
862
|
]);
|
|
817
863
|
if (result.code !== 0) {
|
|
818
864
|
this.logger.error(
|
|
@@ -824,6 +870,23 @@ var PythonEnvironment = class {
|
|
|
824
870
|
);
|
|
825
871
|
}
|
|
826
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
|
+
}
|
|
827
890
|
};
|
|
828
891
|
|
|
829
892
|
// src/environment/docling-environment.ts
|
|
@@ -3831,6 +3894,7 @@ var PDFParser = class {
|
|
|
3831
3894
|
enableImagePdfFallback;
|
|
3832
3895
|
client = null;
|
|
3833
3896
|
environment;
|
|
3897
|
+
recoveryPromise = null;
|
|
3834
3898
|
constructor(options) {
|
|
3835
3899
|
const {
|
|
3836
3900
|
logger,
|
|
@@ -3915,15 +3979,30 @@ var PDFParser = class {
|
|
|
3915
3979
|
*/
|
|
3916
3980
|
isConnectionRefusedError(error) {
|
|
3917
3981
|
if (error instanceof Error) {
|
|
3982
|
+
const errorWithMetadata = error;
|
|
3918
3983
|
if (error.message.includes("ECONNREFUSED")) {
|
|
3919
3984
|
return true;
|
|
3920
3985
|
}
|
|
3921
|
-
if (
|
|
3986
|
+
if (errorWithMetadata.code === "ECONNREFUSED") {
|
|
3922
3987
|
return true;
|
|
3923
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);
|
|
3924
4000
|
}
|
|
3925
4001
|
return false;
|
|
3926
4002
|
}
|
|
4003
|
+
canRecoverLocalServer() {
|
|
4004
|
+
return !this.baseUrl && this.port !== void 0;
|
|
4005
|
+
}
|
|
3927
4006
|
/**
|
|
3928
4007
|
* Restart the Docling server after it has crashed.
|
|
3929
4008
|
* This kills any existing process on the port, starts a new server,
|
|
@@ -3953,6 +4032,46 @@ var PDFParser = class {
|
|
|
3953
4032
|
await this.waitForServerReady();
|
|
3954
4033
|
this.logger.info("[PDFParser] Server restarted successfully");
|
|
3955
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
|
+
}
|
|
3956
4075
|
async waitForServerReady() {
|
|
3957
4076
|
const maxAttempts = PDF_PARSER.MAX_HEALTH_CHECK_ATTEMPTS;
|
|
3958
4077
|
const checkInterval = PDF_PARSER.HEALTH_CHECK_INTERVAL_MS;
|
|
@@ -4036,18 +4155,16 @@ var PDFParser = class {
|
|
|
4036
4155
|
* Recovery is only attempted in local server mode (no baseUrl, port defined).
|
|
4037
4156
|
*/
|
|
4038
4157
|
async executeWithRecovery(fn, abortSignal) {
|
|
4039
|
-
const canRecover = !this.baseUrl && this.port !== void 0;
|
|
4040
4158
|
const maxAttempts = PDF_PARSER.MAX_SERVER_RECOVERY_ATTEMPTS;
|
|
4041
4159
|
const tryExecute = async (attempt) => {
|
|
4042
4160
|
try {
|
|
4043
4161
|
return await fn();
|
|
4044
4162
|
} catch (error) {
|
|
4045
4163
|
if (abortSignal?.aborted) throw error;
|
|
4046
|
-
if (
|
|
4047
|
-
this.
|
|
4164
|
+
if (this.canRecoverLocalServer() && this.isConnectionRefusedError(error) && attempt < maxAttempts) {
|
|
4165
|
+
await this.recoverServer(
|
|
4048
4166
|
"[PDFParser] Connection refused, attempting server recovery..."
|
|
4049
4167
|
);
|
|
4050
|
-
await this.restartServer();
|
|
4051
4168
|
return tryExecute(attempt + 1);
|
|
4052
4169
|
}
|
|
4053
4170
|
throw error;
|