ocr-ai 1.0.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 ADDED
@@ -0,0 +1,1013 @@
1
+ 'use strict';
2
+
3
+ var generativeAi = require('@google/generative-ai');
4
+ var OpenAI = require('openai');
5
+ var Anthropic = require('@anthropic-ai/sdk');
6
+ var genai = require('@google/genai');
7
+ var fs = require('fs/promises');
8
+ var path = require('path');
9
+
10
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
+
12
+ function _interopNamespace(e) {
13
+ if (e && e.__esModule) return e;
14
+ var n = Object.create(null);
15
+ if (e) {
16
+ Object.keys(e).forEach(function (k) {
17
+ if (k !== 'default') {
18
+ var d = Object.getOwnPropertyDescriptor(e, k);
19
+ Object.defineProperty(n, k, d.get ? d : {
20
+ enumerable: true,
21
+ get: function () { return e[k]; }
22
+ });
23
+ }
24
+ });
25
+ }
26
+ n.default = e;
27
+ return Object.freeze(n);
28
+ }
29
+
30
+ var OpenAI__default = /*#__PURE__*/_interopDefault(OpenAI);
31
+ var Anthropic__default = /*#__PURE__*/_interopDefault(Anthropic);
32
+ var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
33
+ var path__namespace = /*#__PURE__*/_interopNamespace(path);
34
+
35
+ // src/providers/base.provider.ts
36
+ var BaseProvider = class {
37
+ apiKey;
38
+ constructor(apiKey) {
39
+ if (!apiKey || apiKey.trim() === "") {
40
+ throw new Error(`API key is required for ${this.constructor.name}`);
41
+ }
42
+ this.apiKey = apiKey;
43
+ }
44
+ supportsFileType(type) {
45
+ return ["pdf", "image", "text"].includes(type);
46
+ }
47
+ /**
48
+ * Build the text extraction prompt
49
+ */
50
+ buildTextPrompt(options) {
51
+ const basePrompt = options?.prompt || "Extract all text content from this document.";
52
+ const languageHint = options?.language && options.language !== "auto" ? ` Respond in ${options.language}.` : "";
53
+ return `${basePrompt}${languageHint}
54
+
55
+ Please extract and return all the text content from the provided document.
56
+ Maintain the original structure and formatting as much as possible.
57
+ Return only the extracted text, without any additional commentary or metadata.`;
58
+ }
59
+ /**
60
+ * Build the JSON extraction prompt
61
+ */
62
+ buildJsonPrompt(schema, options) {
63
+ const basePrompt = options?.prompt || "Extract structured data from this document.";
64
+ const languageHint = options?.language && options.language !== "auto" ? ` Text content should be in ${options.language}.` : "";
65
+ return `${basePrompt}${languageHint}
66
+
67
+ Extract data from the provided document and return it as a JSON object following this schema:
68
+
69
+ ${JSON.stringify(schema, null, 2)}
70
+
71
+ Important:
72
+ - Return ONLY valid JSON, no additional text or markdown formatting
73
+ - Follow the schema structure exactly
74
+ - If a field cannot be extracted, use null
75
+ - Do not include any explanation, just the JSON object`;
76
+ }
77
+ /**
78
+ * Parse JSON response from AI, handling potential formatting issues
79
+ */
80
+ parseJsonResponse(response) {
81
+ let cleaned = response.trim();
82
+ if (cleaned.startsWith("```json")) {
83
+ cleaned = cleaned.slice(7);
84
+ } else if (cleaned.startsWith("```")) {
85
+ cleaned = cleaned.slice(3);
86
+ }
87
+ if (cleaned.endsWith("```")) {
88
+ cleaned = cleaned.slice(0, -3);
89
+ }
90
+ cleaned = cleaned.trim();
91
+ try {
92
+ return JSON.parse(cleaned);
93
+ } catch {
94
+ throw new Error(`Failed to parse JSON response: ${response.substring(0, 200)}...`);
95
+ }
96
+ }
97
+ };
98
+ var DEFAULT_MODEL = "gemini-1.5-flash";
99
+ var GeminiProvider = class extends BaseProvider {
100
+ name = "gemini";
101
+ model;
102
+ client;
103
+ constructor(apiKey, model) {
104
+ super(apiKey);
105
+ this.model = model || DEFAULT_MODEL;
106
+ this.client = new generativeAi.GoogleGenerativeAI(apiKey);
107
+ }
108
+ async extractText(file, options) {
109
+ const generationConfig = this.buildGenerationConfig(options?.modelConfig);
110
+ const model = this.client.getGenerativeModel({
111
+ model: this.model,
112
+ generationConfig
113
+ });
114
+ const prompt = this.buildTextPrompt(options);
115
+ const content = this.buildContent(file, prompt);
116
+ const result = await model.generateContent(content);
117
+ const response = result.response;
118
+ const tokens = this.extractTokenUsage(response);
119
+ return {
120
+ content: response.text(),
121
+ tokens
122
+ };
123
+ }
124
+ async extractJson(file, schema, options) {
125
+ const generationConfig = this.buildGenerationConfig(options?.modelConfig, {
126
+ responseMimeType: "application/json"
127
+ });
128
+ const model = this.client.getGenerativeModel({
129
+ model: this.model,
130
+ generationConfig
131
+ });
132
+ const prompt = this.buildJsonPrompt(schema, options);
133
+ const content = this.buildContent(file, prompt);
134
+ const result = await model.generateContent(content);
135
+ const response = result.response;
136
+ const text = response.text();
137
+ const tokens = this.extractTokenUsage(response);
138
+ return {
139
+ content: this.parseJsonResponse(text),
140
+ tokens
141
+ };
142
+ }
143
+ buildGenerationConfig(modelConfig, defaults) {
144
+ const config = { ...defaults };
145
+ if (modelConfig?.temperature !== void 0) {
146
+ config.temperature = modelConfig.temperature;
147
+ }
148
+ if (modelConfig?.maxTokens !== void 0) {
149
+ config.maxOutputTokens = modelConfig.maxTokens;
150
+ }
151
+ if (modelConfig?.topP !== void 0) {
152
+ config.topP = modelConfig.topP;
153
+ }
154
+ if (modelConfig?.topK !== void 0) {
155
+ config.topK = modelConfig.topK;
156
+ }
157
+ if (modelConfig?.stopSequences !== void 0) {
158
+ config.stopSequences = modelConfig.stopSequences;
159
+ }
160
+ return config;
161
+ }
162
+ extractTokenUsage(response) {
163
+ const usage = response.usageMetadata;
164
+ if (!usage) return void 0;
165
+ return {
166
+ inputTokens: usage.promptTokenCount || 0,
167
+ outputTokens: usage.candidatesTokenCount || 0,
168
+ totalTokens: usage.totalTokenCount || 0
169
+ };
170
+ }
171
+ buildContent(file, prompt) {
172
+ if (file.type === "text") {
173
+ return `${prompt}
174
+
175
+ Document content:
176
+ ${file.content.toString("utf-8")}`;
177
+ }
178
+ return [
179
+ {
180
+ inlineData: {
181
+ mimeType: file.mimeType,
182
+ data: file.base64 || file.content.toString("base64")
183
+ }
184
+ },
185
+ { text: prompt }
186
+ ];
187
+ }
188
+ };
189
+ var DEFAULT_MODEL2 = "gpt-4o";
190
+ var OpenAIProvider = class extends BaseProvider {
191
+ name = "openai";
192
+ model;
193
+ client;
194
+ constructor(apiKey, model) {
195
+ super(apiKey);
196
+ this.model = model || DEFAULT_MODEL2;
197
+ this.client = new OpenAI__default.default({ apiKey });
198
+ }
199
+ async extractText(file, options) {
200
+ const prompt = this.buildTextPrompt(options);
201
+ const messages = this.buildMessages(file, prompt);
202
+ const completionOptions = this.buildCompletionOptions(options?.modelConfig);
203
+ const response = await this.client.chat.completions.create({
204
+ model: this.model,
205
+ messages,
206
+ ...completionOptions
207
+ });
208
+ const tokens = this.extractTokenUsage(response);
209
+ return {
210
+ content: response.choices[0]?.message?.content || "",
211
+ tokens
212
+ };
213
+ }
214
+ async extractJson(file, schema, options) {
215
+ const prompt = this.buildJsonPrompt(schema, options);
216
+ const messages = this.buildMessages(file, prompt);
217
+ const completionOptions = this.buildCompletionOptions(options?.modelConfig);
218
+ const response = await this.client.chat.completions.create({
219
+ model: this.model,
220
+ messages,
221
+ ...completionOptions,
222
+ response_format: { type: "json_object" }
223
+ });
224
+ const text = response.choices[0]?.message?.content || "{}";
225
+ const tokens = this.extractTokenUsage(response);
226
+ return {
227
+ content: this.parseJsonResponse(text),
228
+ tokens
229
+ };
230
+ }
231
+ buildCompletionOptions(modelConfig) {
232
+ const options = {
233
+ max_tokens: 16384
234
+ };
235
+ if (modelConfig?.temperature !== void 0) {
236
+ options.temperature = modelConfig.temperature;
237
+ }
238
+ if (modelConfig?.maxTokens !== void 0) {
239
+ options.max_tokens = modelConfig.maxTokens;
240
+ }
241
+ if (modelConfig?.topP !== void 0) {
242
+ options.top_p = modelConfig.topP;
243
+ }
244
+ if (modelConfig?.stopSequences !== void 0) {
245
+ options.stop = modelConfig.stopSequences;
246
+ }
247
+ return options;
248
+ }
249
+ extractTokenUsage(response) {
250
+ const usage = response.usage;
251
+ if (!usage) return void 0;
252
+ return {
253
+ inputTokens: usage.prompt_tokens,
254
+ outputTokens: usage.completion_tokens,
255
+ totalTokens: usage.total_tokens
256
+ };
257
+ }
258
+ buildMessages(file, prompt) {
259
+ if (file.type === "text") {
260
+ return [
261
+ {
262
+ role: "user",
263
+ content: `${prompt}
264
+
265
+ Document content:
266
+ ${file.content.toString("utf-8")}`
267
+ }
268
+ ];
269
+ }
270
+ const base64 = file.base64 || file.content.toString("base64");
271
+ const imageUrl = `data:${file.mimeType};base64,${base64}`;
272
+ return [
273
+ {
274
+ role: "user",
275
+ content: [
276
+ {
277
+ type: "image_url",
278
+ image_url: {
279
+ url: imageUrl,
280
+ detail: "high"
281
+ }
282
+ },
283
+ {
284
+ type: "text",
285
+ text: prompt
286
+ }
287
+ ]
288
+ }
289
+ ];
290
+ }
291
+ };
292
+ var DEFAULT_MODEL3 = "claude-sonnet-4-20250514";
293
+ var ClaudeProvider = class extends BaseProvider {
294
+ name = "claude";
295
+ model;
296
+ client;
297
+ constructor(apiKey, model) {
298
+ super(apiKey);
299
+ this.model = model || DEFAULT_MODEL3;
300
+ this.client = new Anthropic__default.default({ apiKey });
301
+ }
302
+ async extractText(file, options) {
303
+ const prompt = this.buildTextPrompt(options);
304
+ const messageOptions = this.buildMessageOptions(options?.modelConfig);
305
+ const response = await this.client.messages.create({
306
+ model: this.model,
307
+ messages: [
308
+ {
309
+ role: "user",
310
+ content: this.buildContent(file, prompt)
311
+ }
312
+ ],
313
+ max_tokens: messageOptions.max_tokens,
314
+ temperature: messageOptions.temperature,
315
+ top_p: messageOptions.top_p,
316
+ top_k: messageOptions.top_k,
317
+ stop_sequences: messageOptions.stop_sequences
318
+ });
319
+ const textBlock = response.content.find((block) => block.type === "text");
320
+ const tokens = this.extractTokenUsage(response);
321
+ return {
322
+ content: textBlock?.text || "",
323
+ tokens
324
+ };
325
+ }
326
+ async extractJson(file, schema, options) {
327
+ const prompt = this.buildJsonPrompt(schema, options);
328
+ const messageOptions = this.buildMessageOptions(options?.modelConfig);
329
+ const response = await this.client.messages.create({
330
+ model: this.model,
331
+ messages: [
332
+ {
333
+ role: "user",
334
+ content: this.buildContent(file, prompt)
335
+ }
336
+ ],
337
+ max_tokens: messageOptions.max_tokens,
338
+ temperature: messageOptions.temperature,
339
+ top_p: messageOptions.top_p,
340
+ top_k: messageOptions.top_k,
341
+ stop_sequences: messageOptions.stop_sequences
342
+ });
343
+ const textBlock = response.content.find((block) => block.type === "text");
344
+ const text = textBlock?.text || "{}";
345
+ const tokens = this.extractTokenUsage(response);
346
+ return {
347
+ content: this.parseJsonResponse(text),
348
+ tokens
349
+ };
350
+ }
351
+ buildMessageOptions(modelConfig) {
352
+ const options = {
353
+ max_tokens: 16384
354
+ };
355
+ if (modelConfig?.temperature !== void 0) {
356
+ options.temperature = modelConfig.temperature;
357
+ }
358
+ if (modelConfig?.maxTokens !== void 0) {
359
+ options.max_tokens = modelConfig.maxTokens;
360
+ }
361
+ if (modelConfig?.topP !== void 0) {
362
+ options.top_p = modelConfig.topP;
363
+ }
364
+ if (modelConfig?.topK !== void 0) {
365
+ options.top_k = modelConfig.topK;
366
+ }
367
+ if (modelConfig?.stopSequences !== void 0) {
368
+ options.stop_sequences = modelConfig.stopSequences;
369
+ }
370
+ return options;
371
+ }
372
+ supportsFileType(type) {
373
+ return ["pdf", "image", "text"].includes(type);
374
+ }
375
+ extractTokenUsage(response) {
376
+ return {
377
+ inputTokens: response.usage.input_tokens,
378
+ outputTokens: response.usage.output_tokens,
379
+ totalTokens: response.usage.input_tokens + response.usage.output_tokens
380
+ };
381
+ }
382
+ buildContent(file, prompt) {
383
+ if (file.type === "text") {
384
+ return `${prompt}
385
+
386
+ Document content:
387
+ ${file.content.toString("utf-8")}`;
388
+ }
389
+ const base64 = file.base64 || file.content.toString("base64");
390
+ if (file.type === "pdf") {
391
+ return [
392
+ {
393
+ type: "document",
394
+ source: {
395
+ type: "base64",
396
+ media_type: "application/pdf",
397
+ data: base64
398
+ }
399
+ },
400
+ {
401
+ type: "text",
402
+ text: prompt
403
+ }
404
+ ];
405
+ }
406
+ return [
407
+ {
408
+ type: "image",
409
+ source: {
410
+ type: "base64",
411
+ media_type: this.getMediaType(file.mimeType),
412
+ data: base64
413
+ }
414
+ },
415
+ {
416
+ type: "text",
417
+ text: prompt
418
+ }
419
+ ];
420
+ }
421
+ getMediaType(mimeType) {
422
+ const supportedTypes = [
423
+ "image/jpeg",
424
+ "image/png",
425
+ "image/gif",
426
+ "image/webp"
427
+ ];
428
+ if (supportedTypes.includes(mimeType)) {
429
+ return mimeType;
430
+ }
431
+ return "image/jpeg";
432
+ }
433
+ };
434
+ var GROK_BASE_URL = "https://api.x.ai/v1";
435
+ var DEFAULT_MODEL4 = "grok-2-vision-1212";
436
+ var GrokProvider = class extends BaseProvider {
437
+ name = "grok";
438
+ model;
439
+ client;
440
+ constructor(apiKey, model) {
441
+ super(apiKey);
442
+ this.model = model || DEFAULT_MODEL4;
443
+ this.client = new OpenAI__default.default({
444
+ apiKey,
445
+ baseURL: GROK_BASE_URL
446
+ });
447
+ }
448
+ async extractText(file, options) {
449
+ const prompt = this.buildTextPrompt(options);
450
+ const messages = this.buildMessages(file, prompt);
451
+ const completionOptions = this.buildCompletionOptions(options?.modelConfig);
452
+ const response = await this.client.chat.completions.create({
453
+ model: this.model,
454
+ messages,
455
+ ...completionOptions
456
+ });
457
+ const tokens = this.extractTokenUsage(response);
458
+ return {
459
+ content: response.choices[0]?.message?.content || "",
460
+ tokens
461
+ };
462
+ }
463
+ async extractJson(file, schema, options) {
464
+ const prompt = this.buildJsonPrompt(schema, options);
465
+ const messages = this.buildMessages(file, prompt);
466
+ const completionOptions = this.buildCompletionOptions(options?.modelConfig);
467
+ const response = await this.client.chat.completions.create({
468
+ model: this.model,
469
+ messages,
470
+ ...completionOptions
471
+ });
472
+ const text = response.choices[0]?.message?.content || "{}";
473
+ const tokens = this.extractTokenUsage(response);
474
+ return {
475
+ content: this.parseJsonResponse(text),
476
+ tokens
477
+ };
478
+ }
479
+ buildCompletionOptions(modelConfig) {
480
+ const options = {
481
+ max_tokens: 16384
482
+ };
483
+ if (modelConfig?.temperature !== void 0) {
484
+ options.temperature = modelConfig.temperature;
485
+ }
486
+ if (modelConfig?.maxTokens !== void 0) {
487
+ options.max_tokens = modelConfig.maxTokens;
488
+ }
489
+ if (modelConfig?.topP !== void 0) {
490
+ options.top_p = modelConfig.topP;
491
+ }
492
+ if (modelConfig?.stopSequences !== void 0) {
493
+ options.stop = modelConfig.stopSequences;
494
+ }
495
+ return options;
496
+ }
497
+ extractTokenUsage(response) {
498
+ const usage = response.usage;
499
+ if (!usage) return void 0;
500
+ return {
501
+ inputTokens: usage.prompt_tokens,
502
+ outputTokens: usage.completion_tokens,
503
+ totalTokens: usage.total_tokens
504
+ };
505
+ }
506
+ buildMessages(file, prompt) {
507
+ if (file.type === "text") {
508
+ return [
509
+ {
510
+ role: "user",
511
+ content: `${prompt}
512
+
513
+ Document content:
514
+ ${file.content.toString("utf-8")}`
515
+ }
516
+ ];
517
+ }
518
+ const base64 = file.base64 || file.content.toString("base64");
519
+ const imageUrl = `data:${file.mimeType};base64,${base64}`;
520
+ return [
521
+ {
522
+ role: "user",
523
+ content: [
524
+ {
525
+ type: "image_url",
526
+ image_url: {
527
+ url: imageUrl,
528
+ detail: "high"
529
+ }
530
+ },
531
+ {
532
+ type: "text",
533
+ text: prompt
534
+ }
535
+ ]
536
+ }
537
+ ];
538
+ }
539
+ };
540
+ var DEFAULT_MODEL5 = "gemini-2.0-flash";
541
+ var VertexProvider = class extends BaseProvider {
542
+ name = "vertex";
543
+ model;
544
+ client;
545
+ constructor(config, model) {
546
+ super("vertex");
547
+ this.model = model || DEFAULT_MODEL5;
548
+ this.client = new genai.GoogleGenAI({
549
+ vertexai: true,
550
+ project: config.project,
551
+ location: config.location
552
+ });
553
+ }
554
+ async extractText(file, options) {
555
+ const prompt = this.buildTextPrompt(options);
556
+ const generationConfig = this.buildGenerationConfig(options?.modelConfig);
557
+ const response = await this.client.models.generateContent({
558
+ model: this.model,
559
+ contents: this.buildContents(file, prompt),
560
+ config: generationConfig
561
+ });
562
+ const tokens = this.extractTokenUsage(response);
563
+ return {
564
+ content: response.text || "",
565
+ tokens
566
+ };
567
+ }
568
+ async extractJson(file, schema, options) {
569
+ const prompt = this.buildJsonPrompt(schema, options);
570
+ const generationConfig = this.buildGenerationConfig(options?.modelConfig, {
571
+ responseMimeType: "application/json"
572
+ });
573
+ const response = await this.client.models.generateContent({
574
+ model: this.model,
575
+ contents: this.buildContents(file, prompt),
576
+ config: generationConfig
577
+ });
578
+ const text = response.text || "{}";
579
+ const tokens = this.extractTokenUsage(response);
580
+ return {
581
+ content: this.parseJsonResponse(text),
582
+ tokens
583
+ };
584
+ }
585
+ buildGenerationConfig(modelConfig, defaults) {
586
+ const config = { ...defaults };
587
+ if (modelConfig?.temperature !== void 0) {
588
+ config.temperature = modelConfig.temperature;
589
+ }
590
+ if (modelConfig?.maxTokens !== void 0) {
591
+ config.maxOutputTokens = modelConfig.maxTokens;
592
+ }
593
+ if (modelConfig?.topP !== void 0) {
594
+ config.topP = modelConfig.topP;
595
+ }
596
+ if (modelConfig?.topK !== void 0) {
597
+ config.topK = modelConfig.topK;
598
+ }
599
+ if (modelConfig?.stopSequences !== void 0) {
600
+ config.stopSequences = modelConfig.stopSequences;
601
+ }
602
+ return config;
603
+ }
604
+ extractTokenUsage(response) {
605
+ const usage = response.usageMetadata;
606
+ if (!usage) return void 0;
607
+ return {
608
+ inputTokens: usage.promptTokenCount || 0,
609
+ outputTokens: usage.candidatesTokenCount || 0,
610
+ totalTokens: usage.totalTokenCount || 0
611
+ };
612
+ }
613
+ buildContents(file, prompt) {
614
+ if (file.type === "text") {
615
+ return [
616
+ {
617
+ role: "user",
618
+ parts: [
619
+ { text: `${prompt}
620
+
621
+ Document content:
622
+ ${file.content.toString("utf-8")}` }
623
+ ]
624
+ }
625
+ ];
626
+ }
627
+ const base64 = file.base64 || file.content.toString("base64");
628
+ return [
629
+ {
630
+ role: "user",
631
+ parts: [
632
+ {
633
+ inlineData: {
634
+ mimeType: file.mimeType,
635
+ data: base64
636
+ }
637
+ },
638
+ { text: prompt }
639
+ ]
640
+ }
641
+ ];
642
+ }
643
+ };
644
+ var MIME_TO_FILE_TYPE = {
645
+ "application/pdf": "pdf",
646
+ "image/jpeg": "image",
647
+ "image/png": "image",
648
+ "image/gif": "image",
649
+ "image/webp": "image",
650
+ "image/bmp": "image",
651
+ "image/tiff": "image",
652
+ "text/plain": "text",
653
+ "text/markdown": "text",
654
+ "text/csv": "text",
655
+ "application/json": "text",
656
+ "application/xml": "text",
657
+ "text/html": "text"
658
+ };
659
+ var MIME_TYPES = {
660
+ // PDF
661
+ ".pdf": "application/pdf",
662
+ // Images
663
+ ".jpg": "image/jpeg",
664
+ ".jpeg": "image/jpeg",
665
+ ".png": "image/png",
666
+ ".gif": "image/gif",
667
+ ".webp": "image/webp",
668
+ ".bmp": "image/bmp",
669
+ ".tiff": "image/tiff",
670
+ ".tif": "image/tiff",
671
+ // Text files
672
+ ".txt": "text/plain",
673
+ ".md": "text/markdown",
674
+ ".csv": "text/csv",
675
+ ".json": "application/json",
676
+ ".xml": "application/xml",
677
+ ".html": "text/html",
678
+ ".htm": "text/html"
679
+ };
680
+ var FILE_TYPE_CATEGORIES = {
681
+ ".pdf": "pdf",
682
+ ".jpg": "image",
683
+ ".jpeg": "image",
684
+ ".png": "image",
685
+ ".gif": "image",
686
+ ".webp": "image",
687
+ ".bmp": "image",
688
+ ".tiff": "image",
689
+ ".tif": "image",
690
+ ".txt": "text",
691
+ ".md": "text",
692
+ ".csv": "text",
693
+ ".json": "text",
694
+ ".xml": "text",
695
+ ".html": "text",
696
+ ".htm": "text"
697
+ };
698
+ async function loadFile(filePath) {
699
+ const absolutePath = path__namespace.resolve(filePath);
700
+ try {
701
+ await fs__namespace.access(absolutePath);
702
+ } catch {
703
+ throw new Error(`File not found: ${absolutePath}`);
704
+ }
705
+ const stats = await fs__namespace.stat(absolutePath);
706
+ if (!stats.isFile()) {
707
+ throw new Error(`Path is not a file: ${absolutePath}`);
708
+ }
709
+ const ext = path__namespace.extname(absolutePath).toLowerCase();
710
+ const fileName = path__namespace.basename(absolutePath);
711
+ const mimeType = MIME_TYPES[ext];
712
+ const fileType = FILE_TYPE_CATEGORIES[ext];
713
+ if (!mimeType || !fileType) {
714
+ throw new Error(
715
+ `Unsupported file type: ${ext}. Supported types: ${Object.keys(MIME_TYPES).join(", ")}`
716
+ );
717
+ }
718
+ const content = await fs__namespace.readFile(absolutePath);
719
+ const base64 = fileType !== "text" ? content.toString("base64") : void 0;
720
+ return {
721
+ path: absolutePath,
722
+ name: fileName,
723
+ type: fileType,
724
+ mimeType,
725
+ size: stats.size,
726
+ content,
727
+ base64
728
+ };
729
+ }
730
+ function loadFileFromBuffer(buffer, fileName, mimeType) {
731
+ const ext = path__namespace.extname(fileName).toLowerCase();
732
+ const detectedMimeType = mimeType || MIME_TYPES[ext];
733
+ const fileType = FILE_TYPE_CATEGORIES[ext];
734
+ if (!detectedMimeType || !fileType) {
735
+ throw new Error(
736
+ `Unsupported file type: ${ext}. Supported types: ${Object.keys(MIME_TYPES).join(", ")}`
737
+ );
738
+ }
739
+ const base64 = fileType !== "text" ? buffer.toString("base64") : void 0;
740
+ return {
741
+ path: "",
742
+ name: fileName,
743
+ type: fileType,
744
+ mimeType: detectedMimeType,
745
+ size: buffer.length,
746
+ content: buffer,
747
+ base64
748
+ };
749
+ }
750
+ function loadFileFromBase64(base64, fileName, mimeType) {
751
+ const base64Data = base64.includes(",") ? base64.split(",")[1] : base64;
752
+ const buffer = Buffer.from(base64Data, "base64");
753
+ const ext = path__namespace.extname(fileName).toLowerCase();
754
+ const detectedMimeType = mimeType || MIME_TYPES[ext];
755
+ const fileType = FILE_TYPE_CATEGORIES[ext];
756
+ if (!detectedMimeType || !fileType) {
757
+ throw new Error(
758
+ `Unsupported file type: ${ext}. Supported types: ${Object.keys(MIME_TYPES).join(", ")}`
759
+ );
760
+ }
761
+ return {
762
+ path: "",
763
+ name: fileName,
764
+ type: fileType,
765
+ mimeType: detectedMimeType,
766
+ size: buffer.length,
767
+ content: buffer,
768
+ base64: base64Data
769
+ };
770
+ }
771
+ async function saveToFile(filePath, content) {
772
+ const absolutePath = path__namespace.resolve(filePath);
773
+ const dir = path__namespace.dirname(absolutePath);
774
+ await fs__namespace.mkdir(dir, { recursive: true });
775
+ await fs__namespace.writeFile(absolutePath, content, typeof content === "string" ? "utf-8" : void 0);
776
+ }
777
+ function getSupportedExtensions() {
778
+ return Object.keys(MIME_TYPES);
779
+ }
780
+ function isExtensionSupported(ext) {
781
+ const normalizedExt = ext.startsWith(".") ? ext.toLowerCase() : `.${ext.toLowerCase()}`;
782
+ return normalizedExt in MIME_TYPES;
783
+ }
784
+ function isUrl(str) {
785
+ return str.startsWith("http://") || str.startsWith("https://");
786
+ }
787
+ async function loadFileFromUrl(url) {
788
+ const response = await fetch(url);
789
+ if (!response.ok) {
790
+ throw new Error(`Failed to fetch URL: ${response.status} ${response.statusText}`);
791
+ }
792
+ const contentType = response.headers.get("content-type")?.split(";")[0] || "";
793
+ const buffer = Buffer.from(await response.arrayBuffer());
794
+ const contentDisposition = response.headers.get("content-disposition");
795
+ let fileName = "";
796
+ if (contentDisposition) {
797
+ const match = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
798
+ if (match) {
799
+ fileName = match[1].replace(/['"]/g, "");
800
+ }
801
+ }
802
+ if (!fileName) {
803
+ const urlPath = new URL(url).pathname;
804
+ fileName = path__namespace.basename(urlPath) || "download";
805
+ }
806
+ let fileType = MIME_TO_FILE_TYPE[contentType];
807
+ let mimeType = contentType;
808
+ if (!fileType) {
809
+ const ext = path__namespace.extname(fileName).toLowerCase();
810
+ mimeType = MIME_TYPES[ext];
811
+ fileType = FILE_TYPE_CATEGORIES[ext];
812
+ }
813
+ if (!fileType || !mimeType) {
814
+ throw new Error(
815
+ `Unsupported file type from URL. Content-Type: ${contentType}, Filename: ${fileName}`
816
+ );
817
+ }
818
+ const base64 = fileType !== "text" ? buffer.toString("base64") : void 0;
819
+ return {
820
+ path: url,
821
+ name: fileName,
822
+ type: fileType,
823
+ mimeType,
824
+ size: buffer.length,
825
+ content: buffer,
826
+ base64
827
+ };
828
+ }
829
+
830
+ // src/extracta.ts
831
+ var ExtractaAI = class {
832
+ provider;
833
+ config;
834
+ constructor(config) {
835
+ this.config = config;
836
+ this.provider = this.createProvider(config);
837
+ }
838
+ /**
839
+ * Create a provider instance based on configuration
840
+ */
841
+ createProvider(config) {
842
+ switch (config.provider) {
843
+ case "gemini":
844
+ if (!config.apiKey) throw new Error("API key is required for Gemini provider");
845
+ return new GeminiProvider(config.apiKey, config.model);
846
+ case "openai":
847
+ if (!config.apiKey) throw new Error("API key is required for OpenAI provider");
848
+ return new OpenAIProvider(config.apiKey, config.model);
849
+ case "claude":
850
+ if (!config.apiKey) throw new Error("API key is required for Claude provider");
851
+ return new ClaudeProvider(config.apiKey, config.model);
852
+ case "grok":
853
+ if (!config.apiKey) throw new Error("API key is required for Grok provider");
854
+ return new GrokProvider(config.apiKey, config.model);
855
+ case "vertex":
856
+ if (!config.vertexConfig) throw new Error("vertexConfig is required for Vertex AI provider");
857
+ return new VertexProvider(config.vertexConfig, config.model);
858
+ default:
859
+ throw new Error(`Unsupported provider: ${config.provider}`);
860
+ }
861
+ }
862
+ /**
863
+ * Extract content from a file path or URL
864
+ */
865
+ async extract(source, options) {
866
+ const startTime = Date.now();
867
+ try {
868
+ const file = isUrl(source) ? await loadFileFromUrl(source) : await loadFile(source);
869
+ return this.processExtraction(file, options, startTime);
870
+ } catch (error) {
871
+ return this.createErrorResult(error);
872
+ }
873
+ }
874
+ /**
875
+ * Extract content from a Buffer
876
+ */
877
+ async extractFromBuffer(buffer, fileName, options) {
878
+ const startTime = Date.now();
879
+ try {
880
+ const file = loadFileFromBuffer(buffer, fileName);
881
+ return this.processExtraction(file, options, startTime);
882
+ } catch (error) {
883
+ return this.createErrorResult(error);
884
+ }
885
+ }
886
+ /**
887
+ * Extract content from a base64 string
888
+ */
889
+ async extractFromBase64(base64, fileName, options) {
890
+ const startTime = Date.now();
891
+ try {
892
+ const file = loadFileFromBase64(base64, fileName);
893
+ return this.processExtraction(file, options, startTime);
894
+ } catch (error) {
895
+ return this.createErrorResult(error);
896
+ }
897
+ }
898
+ /**
899
+ * Process the extraction based on format
900
+ */
901
+ async processExtraction(file, options, startTime) {
902
+ const format = options?.format || "text";
903
+ if (!this.provider.supportsFileType(file.type)) {
904
+ return {
905
+ success: false,
906
+ error: `Provider ${this.provider.name} does not support file type: ${file.type}`,
907
+ code: "UNSUPPORTED_FILE_TYPE"
908
+ };
909
+ }
910
+ try {
911
+ if (format === "json") {
912
+ if (!options?.schema) {
913
+ return {
914
+ success: false,
915
+ error: "Schema is required for JSON extraction",
916
+ code: "MISSING_SCHEMA"
917
+ };
918
+ }
919
+ const providerResult = await this.provider.extractJson(file, options.schema, options);
920
+ const result = {
921
+ success: true,
922
+ format: "json",
923
+ data: providerResult.content,
924
+ metadata: {
925
+ provider: this.provider.name,
926
+ model: this.provider.model,
927
+ fileType: file.type,
928
+ fileName: file.name,
929
+ processingTimeMs: Date.now() - startTime,
930
+ tokens: providerResult.tokens
931
+ }
932
+ };
933
+ if (options.outputPath) {
934
+ await saveToFile(options.outputPath, JSON.stringify(providerResult.content, null, 2));
935
+ }
936
+ return result;
937
+ } else {
938
+ const providerResult = await this.provider.extractText(file, options);
939
+ const result = {
940
+ success: true,
941
+ format: "text",
942
+ content: providerResult.content,
943
+ metadata: {
944
+ provider: this.provider.name,
945
+ model: this.provider.model,
946
+ fileType: file.type,
947
+ fileName: file.name,
948
+ processingTimeMs: Date.now() - startTime,
949
+ tokens: providerResult.tokens
950
+ }
951
+ };
952
+ if (options?.outputPath) {
953
+ await saveToFile(options.outputPath, providerResult.content);
954
+ }
955
+ return result;
956
+ }
957
+ } catch (error) {
958
+ return this.createErrorResult(error);
959
+ }
960
+ }
961
+ /**
962
+ * Create an error result
963
+ */
964
+ createErrorResult(error) {
965
+ const message = error instanceof Error ? error.message : String(error);
966
+ return {
967
+ success: false,
968
+ error: message,
969
+ code: "EXTRACTION_ERROR"
970
+ };
971
+ }
972
+ /**
973
+ * Get current provider name
974
+ */
975
+ getProvider() {
976
+ return this.provider.name;
977
+ }
978
+ /**
979
+ * Get current model
980
+ */
981
+ getModel() {
982
+ return this.provider.model;
983
+ }
984
+ /**
985
+ * Change the AI provider
986
+ */
987
+ setProvider(provider, apiKey, model) {
988
+ this.config = { provider, apiKey, model };
989
+ this.provider = this.createProvider(this.config);
990
+ }
991
+ };
992
+ function createExtractaAI(config) {
993
+ return new ExtractaAI(config);
994
+ }
995
+
996
+ exports.BaseProvider = BaseProvider;
997
+ exports.ClaudeProvider = ClaudeProvider;
998
+ exports.ExtractaAI = ExtractaAI;
999
+ exports.GeminiProvider = GeminiProvider;
1000
+ exports.GrokProvider = GrokProvider;
1001
+ exports.OpenAIProvider = OpenAIProvider;
1002
+ exports.VertexProvider = VertexProvider;
1003
+ exports.createExtractaAI = createExtractaAI;
1004
+ exports.getSupportedExtensions = getSupportedExtensions;
1005
+ exports.isExtensionSupported = isExtensionSupported;
1006
+ exports.isUrl = isUrl;
1007
+ exports.loadFile = loadFile;
1008
+ exports.loadFileFromBase64 = loadFileFromBase64;
1009
+ exports.loadFileFromBuffer = loadFileFromBuffer;
1010
+ exports.loadFileFromUrl = loadFileFromUrl;
1011
+ exports.saveToFile = saveToFile;
1012
+ //# sourceMappingURL=index.js.map
1013
+ //# sourceMappingURL=index.js.map