@intelligentelectron/pdf-analyzer 0.2.0 → 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/cli/commands.d.ts +6 -2
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +83 -100
- package/dist/cli/commands.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -3
- package/dist/index.js.map +1 -1
- package/dist/keychain.d.ts +21 -7
- package/dist/keychain.d.ts.map +1 -1
- package/dist/keychain.js +79 -38
- package/dist/keychain.js.map +1 -1
- package/dist/pdf-utils.d.ts +28 -0
- package/dist/pdf-utils.d.ts.map +1 -0
- package/dist/pdf-utils.js +93 -0
- package/dist/pdf-utils.js.map +1 -0
- package/dist/providers/anthropic.d.ts +9 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +69 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/google.d.ts +13 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +120 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/openai.d.ts +9 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +70 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/registry.d.ts +23 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +44 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/types.d.ts +70 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/server.d.ts +2 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +27 -31
- package/dist/server.js.map +1 -1
- package/dist/service.d.ts +7 -35
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +99 -274
- package/dist/service.js.map +1 -1
- package/dist/types.d.ts +20 -12
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +15 -45
- package/dist/types.js.map +1 -1
- package/package.json +12 -4
package/dist/keychain.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OS-native credential storage
|
|
2
|
+
* OS-native credential storage.
|
|
3
3
|
*
|
|
4
4
|
* Uses platform CLI tools (no native addons) so it works with Bun-compiled binaries.
|
|
5
5
|
* - macOS: `security` CLI (Keychain Access)
|
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
* - Linux: `secret-tool` (libsecret), if available
|
|
8
8
|
*/
|
|
9
9
|
import { execSync } from "node:child_process";
|
|
10
|
-
const
|
|
11
|
-
const ACCOUNT_NAME = "GEMINI_API_KEY";
|
|
10
|
+
const DEFAULT_SERVICE = "pdf-analyzer";
|
|
12
11
|
/** Stdio config that prevents credential leaks to MCP stdio transport. */
|
|
13
12
|
const SILENT_STDIO = ["pipe", "pipe", "pipe"];
|
|
14
13
|
/**
|
|
@@ -21,20 +20,20 @@ export function escapeShellArg(arg) {
|
|
|
21
20
|
// ---------------------------------------------------------------------------
|
|
22
21
|
// macOS (Keychain)
|
|
23
22
|
// ---------------------------------------------------------------------------
|
|
24
|
-
function getMacOS(service) {
|
|
23
|
+
function getMacOS(service, account) {
|
|
25
24
|
try {
|
|
26
|
-
return execSync(`security find-generic-password -s ${escapeShellArg(service)} -a ${escapeShellArg(
|
|
25
|
+
return execSync(`security find-generic-password -s ${escapeShellArg(service)} -a ${escapeShellArg(account)} -w`, { stdio: SILENT_STDIO, encoding: "utf-8" }).trim();
|
|
27
26
|
}
|
|
28
27
|
catch {
|
|
29
28
|
return null;
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
|
-
function setMacOS(service,
|
|
33
|
-
execSync(`security add-generic-password -s ${escapeShellArg(service)} -a ${escapeShellArg(
|
|
31
|
+
function setMacOS(service, account, value) {
|
|
32
|
+
execSync(`security add-generic-password -s ${escapeShellArg(service)} -a ${escapeShellArg(account)} -w ${escapeShellArg(value)} -U`, { stdio: SILENT_STDIO });
|
|
34
33
|
}
|
|
35
|
-
function deleteMacOS(service) {
|
|
34
|
+
function deleteMacOS(service, account) {
|
|
36
35
|
try {
|
|
37
|
-
execSync(`security delete-generic-password -s ${escapeShellArg(service)} -a ${escapeShellArg(
|
|
36
|
+
execSync(`security delete-generic-password -s ${escapeShellArg(service)} -a ${escapeShellArg(account)}`, { stdio: SILENT_STDIO });
|
|
38
37
|
}
|
|
39
38
|
catch {
|
|
40
39
|
// Credential may not exist; ignore
|
|
@@ -43,9 +42,13 @@ function deleteMacOS(service) {
|
|
|
43
42
|
// ---------------------------------------------------------------------------
|
|
44
43
|
// Windows (Credential Manager)
|
|
45
44
|
// ---------------------------------------------------------------------------
|
|
46
|
-
|
|
45
|
+
/** Build a Windows credential target from service + account. */
|
|
46
|
+
function winTarget(service, account) {
|
|
47
|
+
return `${service}/${account}`;
|
|
48
|
+
}
|
|
49
|
+
function getWindows(service, account) {
|
|
47
50
|
try {
|
|
48
|
-
|
|
51
|
+
const target = winTarget(service, account);
|
|
49
52
|
const script = `
|
|
50
53
|
Add-Type -Namespace Win32 -Name Cred -MemberDefinition @'
|
|
51
54
|
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
|
|
@@ -61,7 +64,7 @@ public struct CREDENTIAL {
|
|
|
61
64
|
}
|
|
62
65
|
'@
|
|
63
66
|
$ptr = [IntPtr]::Zero
|
|
64
|
-
if ([Win32.Cred]::CredRead("${
|
|
67
|
+
if ([Win32.Cred]::CredRead("${target}", 1, 0, [ref]$ptr)) {
|
|
65
68
|
$c = [Runtime.InteropServices.Marshal]::PtrToStructure($ptr, [Type][Win32.Cred+CREDENTIAL])
|
|
66
69
|
$secret = [Runtime.InteropServices.Marshal]::PtrToStringUni($c.CredentialBlob, $c.CredentialBlobSize/2)
|
|
67
70
|
[Win32.Cred]::CredFree($ptr)
|
|
@@ -76,15 +79,17 @@ if ([Win32.Cred]::CredRead("${service}", 1, 0, [ref]$ptr)) {
|
|
|
76
79
|
return null;
|
|
77
80
|
}
|
|
78
81
|
}
|
|
79
|
-
function setWindows(service,
|
|
80
|
-
|
|
82
|
+
function setWindows(service, account, value) {
|
|
83
|
+
const target = winTarget(service, account);
|
|
84
|
+
execSync(`cmdkey /generic:${target} /user:${account} /pass:${escapeShellArg(value)}`, {
|
|
81
85
|
stdio: SILENT_STDIO,
|
|
82
86
|
shell: "cmd.exe",
|
|
83
87
|
});
|
|
84
88
|
}
|
|
85
|
-
function deleteWindows(service) {
|
|
89
|
+
function deleteWindows(service, account) {
|
|
86
90
|
try {
|
|
87
|
-
|
|
91
|
+
const target = winTarget(service, account);
|
|
92
|
+
execSync(`cmdkey /delete:${target}`, {
|
|
88
93
|
stdio: SILENT_STDIO,
|
|
89
94
|
shell: "cmd.exe",
|
|
90
95
|
});
|
|
@@ -96,72 +101,108 @@ function deleteWindows(service) {
|
|
|
96
101
|
// ---------------------------------------------------------------------------
|
|
97
102
|
// Linux (libsecret / secret-tool)
|
|
98
103
|
// ---------------------------------------------------------------------------
|
|
99
|
-
function getLinux(service) {
|
|
104
|
+
function getLinux(service, account) {
|
|
100
105
|
try {
|
|
101
|
-
return (execSync(`secret-tool lookup service ${escapeShellArg(service)} username ${escapeShellArg(
|
|
106
|
+
return (execSync(`secret-tool lookup service ${escapeShellArg(service)} username ${escapeShellArg(account)}`, { stdio: SILENT_STDIO, encoding: "utf-8" }).trim() || null);
|
|
102
107
|
}
|
|
103
108
|
catch {
|
|
104
109
|
return null;
|
|
105
110
|
}
|
|
106
111
|
}
|
|
107
|
-
function setLinux(service,
|
|
108
|
-
execSync(`echo -n ${escapeShellArg(
|
|
112
|
+
function setLinux(service, account, value) {
|
|
113
|
+
execSync(`echo -n ${escapeShellArg(value)} | secret-tool store --label=${escapeShellArg(service)} service ${escapeShellArg(service)} username ${escapeShellArg(account)}`, { stdio: SILENT_STDIO });
|
|
109
114
|
}
|
|
110
|
-
function deleteLinux(service) {
|
|
115
|
+
function deleteLinux(service, account) {
|
|
111
116
|
try {
|
|
112
|
-
execSync(`secret-tool clear service ${escapeShellArg(service)} username ${escapeShellArg(
|
|
117
|
+
execSync(`secret-tool clear service ${escapeShellArg(service)} username ${escapeShellArg(account)}`, { stdio: SILENT_STDIO });
|
|
113
118
|
}
|
|
114
119
|
catch {
|
|
115
120
|
// Credential may not exist or secret-tool unavailable; ignore
|
|
116
121
|
}
|
|
117
122
|
}
|
|
118
123
|
// ---------------------------------------------------------------------------
|
|
119
|
-
//
|
|
124
|
+
// Generic credential operations
|
|
120
125
|
// ---------------------------------------------------------------------------
|
|
121
|
-
/** Read
|
|
122
|
-
export function
|
|
126
|
+
/** Read a value from the OS credential store. */
|
|
127
|
+
export function getStoredValue(account, service = DEFAULT_SERVICE) {
|
|
123
128
|
switch (process.platform) {
|
|
124
129
|
case "darwin":
|
|
125
|
-
return getMacOS(service);
|
|
130
|
+
return getMacOS(service, account);
|
|
126
131
|
case "win32":
|
|
127
|
-
return getWindows(service);
|
|
132
|
+
return getWindows(service, account);
|
|
128
133
|
case "linux":
|
|
129
|
-
return getLinux(service);
|
|
134
|
+
return getLinux(service, account);
|
|
130
135
|
default:
|
|
131
136
|
return null;
|
|
132
137
|
}
|
|
133
138
|
}
|
|
134
|
-
/** Write
|
|
135
|
-
export function
|
|
139
|
+
/** Write a value to the OS credential store. */
|
|
140
|
+
export function setStoredValue(account, value, service = DEFAULT_SERVICE) {
|
|
136
141
|
switch (process.platform) {
|
|
137
142
|
case "darwin":
|
|
138
|
-
setMacOS(service,
|
|
143
|
+
setMacOS(service, account, value);
|
|
139
144
|
break;
|
|
140
145
|
case "win32":
|
|
141
|
-
setWindows(service,
|
|
146
|
+
setWindows(service, account, value);
|
|
142
147
|
break;
|
|
143
148
|
case "linux":
|
|
144
|
-
setLinux(service,
|
|
149
|
+
setLinux(service, account, value);
|
|
145
150
|
break;
|
|
146
151
|
default:
|
|
147
152
|
throw new Error(`Credential storage is not supported on ${process.platform}`);
|
|
148
153
|
}
|
|
149
154
|
}
|
|
150
|
-
/** Remove
|
|
151
|
-
export function
|
|
155
|
+
/** Remove a value from the OS credential store (best-effort). */
|
|
156
|
+
export function deleteStoredValue(account, service = DEFAULT_SERVICE) {
|
|
152
157
|
switch (process.platform) {
|
|
153
158
|
case "darwin":
|
|
154
|
-
deleteMacOS(service);
|
|
159
|
+
deleteMacOS(service, account);
|
|
155
160
|
break;
|
|
156
161
|
case "win32":
|
|
157
|
-
deleteWindows(service);
|
|
162
|
+
deleteWindows(service, account);
|
|
158
163
|
break;
|
|
159
164
|
case "linux":
|
|
160
|
-
deleteLinux(service);
|
|
165
|
+
deleteLinux(service, account);
|
|
161
166
|
break;
|
|
162
167
|
default:
|
|
163
168
|
// No-op on unsupported platforms
|
|
164
169
|
break;
|
|
165
170
|
}
|
|
166
171
|
}
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
// Convenience API for provider and API key storage
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
const PROVIDER_ACCOUNT = "PROVIDER";
|
|
176
|
+
const API_KEY_ACCOUNT = "API_KEY";
|
|
177
|
+
const MODEL_ACCOUNT = "MODEL";
|
|
178
|
+
/** Get the active provider ID. Returns null if not set. */
|
|
179
|
+
export function getActiveProvider() {
|
|
180
|
+
return getStoredValue(PROVIDER_ACCOUNT);
|
|
181
|
+
}
|
|
182
|
+
/** Store the active provider ID. */
|
|
183
|
+
export function setActiveProvider(providerId) {
|
|
184
|
+
setStoredValue(PROVIDER_ACCOUNT, providerId);
|
|
185
|
+
}
|
|
186
|
+
/** Get the stored API key. Returns null if not found. */
|
|
187
|
+
export function getApiKey() {
|
|
188
|
+
return getStoredValue(API_KEY_ACCOUNT);
|
|
189
|
+
}
|
|
190
|
+
/** Store the API key. */
|
|
191
|
+
export function setApiKey(key) {
|
|
192
|
+
setStoredValue(API_KEY_ACCOUNT, key);
|
|
193
|
+
}
|
|
194
|
+
/** Get the stored model ID. Returns null if not set. */
|
|
195
|
+
export function getModel() {
|
|
196
|
+
return getStoredValue(MODEL_ACCOUNT);
|
|
197
|
+
}
|
|
198
|
+
/** Store the selected model ID. */
|
|
199
|
+
export function setModel(modelId) {
|
|
200
|
+
setStoredValue(MODEL_ACCOUNT, modelId);
|
|
201
|
+
}
|
|
202
|
+
/** Delete all stored credentials (provider + API key + model). Best-effort. */
|
|
203
|
+
export function deleteAllCredentials() {
|
|
204
|
+
deleteStoredValue(PROVIDER_ACCOUNT);
|
|
205
|
+
deleteStoredValue(API_KEY_ACCOUNT);
|
|
206
|
+
deleteStoredValue(MODEL_ACCOUNT);
|
|
207
|
+
}
|
|
167
208
|
//# sourceMappingURL=keychain.js.map
|
package/dist/keychain.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keychain.js","sourceRoot":"","sources":["../src/keychain.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,
|
|
1
|
+
{"version":3,"file":"keychain.js","sourceRoot":"","sources":["../src/keychain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared PDF utility functions.
|
|
3
|
+
*
|
|
4
|
+
* Contains URL validation, path validation, and PDF fetching logic
|
|
5
|
+
* used by both the service layer and provider implementations.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check if a string is a Gemini File API URI.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isGeminiFileUri(source: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Check if a string is a URL (excluding Gemini File API URIs).
|
|
13
|
+
*/
|
|
14
|
+
export declare function isUrl(source: string): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Validates a local PDF file path.
|
|
17
|
+
* Throws descriptive errors for common issues.
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateLocalPath(pdfPath: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Fetch PDF content from a URL with timeout.
|
|
22
|
+
*/
|
|
23
|
+
export declare function fetchPdfFromUrl(url: string): Promise<Buffer>;
|
|
24
|
+
/**
|
|
25
|
+
* Read PDF bytes from a local file path.
|
|
26
|
+
*/
|
|
27
|
+
export declare function readPdfBytes(pdfPath: string): Buffer;
|
|
28
|
+
//# sourceMappingURL=pdf-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdf-utils.d.ts","sourceRoot":"","sources":["../src/pdf-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAU7C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAmBvD;AAKD;;GAEG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgClE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGpD"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared PDF utility functions.
|
|
3
|
+
*
|
|
4
|
+
* Contains URL validation, path validation, and PDF fetching logic
|
|
5
|
+
* used by both the service layer and provider implementations.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "node:fs";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
/** Gemini File API URI prefix. */
|
|
10
|
+
const GEMINI_FILE_URI_PREFIX = "https://generativelanguage.googleapis.com/";
|
|
11
|
+
/**
|
|
12
|
+
* Check if a string is a Gemini File API URI.
|
|
13
|
+
*/
|
|
14
|
+
export function isGeminiFileUri(source) {
|
|
15
|
+
return source.startsWith(GEMINI_FILE_URI_PREFIX);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Check if a string is a URL (excluding Gemini File API URIs).
|
|
19
|
+
*/
|
|
20
|
+
export function isUrl(source) {
|
|
21
|
+
if (isGeminiFileUri(source)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const url = new URL(source);
|
|
26
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Validates a local PDF file path.
|
|
34
|
+
* Throws descriptive errors for common issues.
|
|
35
|
+
*/
|
|
36
|
+
export function validateLocalPath(pdfPath) {
|
|
37
|
+
const trimmedPath = pdfPath.trim();
|
|
38
|
+
if (!path.isAbsolute(trimmedPath)) {
|
|
39
|
+
throw new Error(`PDF path must be absolute: ${trimmedPath}`);
|
|
40
|
+
}
|
|
41
|
+
if (!fs.existsSync(trimmedPath)) {
|
|
42
|
+
throw new Error(`PDF file not found: ${trimmedPath}`);
|
|
43
|
+
}
|
|
44
|
+
const stats = fs.statSync(trimmedPath);
|
|
45
|
+
if (stats.isDirectory()) {
|
|
46
|
+
throw new Error(`Path is a directory, not a file: ${trimmedPath}`);
|
|
47
|
+
}
|
|
48
|
+
if (!trimmedPath.toLowerCase().endsWith(".pdf")) {
|
|
49
|
+
throw new Error(`File is not a PDF: ${trimmedPath}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** Timeout for fetching PDFs from URLs (60 seconds). */
|
|
53
|
+
const FETCH_TIMEOUT_MS = 60_000;
|
|
54
|
+
/**
|
|
55
|
+
* Fetch PDF content from a URL with timeout.
|
|
56
|
+
*/
|
|
57
|
+
export async function fetchPdfFromUrl(url) {
|
|
58
|
+
const controller = new AbortController();
|
|
59
|
+
const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
60
|
+
let response;
|
|
61
|
+
try {
|
|
62
|
+
response = await fetch(url, { signal: controller.signal });
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
66
|
+
throw new Error(`Request timed out after ${FETCH_TIMEOUT_MS / 1000}s`);
|
|
67
|
+
}
|
|
68
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
69
|
+
throw new Error(`Failed to fetch URL: ${message}`);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
clearTimeout(timeoutId);
|
|
73
|
+
}
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
76
|
+
}
|
|
77
|
+
const contentType = response.headers.get("content-type");
|
|
78
|
+
if (contentType &&
|
|
79
|
+
!contentType.includes("application/pdf") &&
|
|
80
|
+
!contentType.includes("octet-stream")) {
|
|
81
|
+
throw new Error(`URL does not point to a PDF file. Content-Type: ${contentType}`);
|
|
82
|
+
}
|
|
83
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
84
|
+
return Buffer.from(arrayBuffer);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Read PDF bytes from a local file path.
|
|
88
|
+
*/
|
|
89
|
+
export function readPdfBytes(pdfPath) {
|
|
90
|
+
validateLocalPath(pdfPath);
|
|
91
|
+
return fs.readFileSync(pdfPath.trim());
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=pdf-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdf-utils.js","sourceRoot":"","sources":["../src/pdf-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic Claude provider.
|
|
3
|
+
*
|
|
4
|
+
* Sends PDFs inline as base64/bytes content parts.
|
|
5
|
+
* No File API, no caching.
|
|
6
|
+
*/
|
|
7
|
+
import type { ProviderConfig } from "./types.js";
|
|
8
|
+
export declare const anthropicProvider: ProviderConfig;
|
|
9
|
+
//# sourceMappingURL=anthropic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAoD,MAAM,YAAY,CAAC;AAuDnG,eAAO,MAAM,iBAAiB,EAAE,cAa/B,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic Claude provider.
|
|
3
|
+
*
|
|
4
|
+
* Sends PDFs inline as base64/bytes content parts.
|
|
5
|
+
* No File API, no caching.
|
|
6
|
+
*/
|
|
7
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
8
|
+
import { fetchPdfFromUrl, readPdfBytes } from "../pdf-utils.js";
|
|
9
|
+
const MODELS = [
|
|
10
|
+
{
|
|
11
|
+
id: "claude-sonnet-4-6",
|
|
12
|
+
displayName: "Claude Sonnet 4.6",
|
|
13
|
+
hint: "Fast and cost-effective",
|
|
14
|
+
},
|
|
15
|
+
{ id: "claude-opus-4-6", displayName: "Claude Opus 4.6", hint: "Best and most expensive" },
|
|
16
|
+
];
|
|
17
|
+
const DEFAULT_MODEL = "claude-opus-4-6";
|
|
18
|
+
/**
|
|
19
|
+
* Prepare a PDF source for Anthropic by reading bytes inline.
|
|
20
|
+
*/
|
|
21
|
+
async function preparePdf(source) {
|
|
22
|
+
if (source.kind === "cachedUri") {
|
|
23
|
+
throw new Error("Cached URIs are only supported with the Google provider.");
|
|
24
|
+
}
|
|
25
|
+
let bytes;
|
|
26
|
+
if (source.kind === "bytes") {
|
|
27
|
+
bytes = source.bytes;
|
|
28
|
+
}
|
|
29
|
+
else if (source.kind === "url") {
|
|
30
|
+
bytes = new Uint8Array(await fetchPdfFromUrl(source.url));
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
bytes = new Uint8Array(await readPdfBytes(source.path));
|
|
34
|
+
}
|
|
35
|
+
const part = {
|
|
36
|
+
type: "file",
|
|
37
|
+
data: bytes,
|
|
38
|
+
mediaType: "application/pdf",
|
|
39
|
+
};
|
|
40
|
+
return { fileParts: [part], cachedUri: null };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Check if an error is an Anthropic token limit error.
|
|
44
|
+
*/
|
|
45
|
+
function isTokenLimitError(error) {
|
|
46
|
+
if (!(error instanceof Error))
|
|
47
|
+
return false;
|
|
48
|
+
const msg = error.message.toLowerCase();
|
|
49
|
+
return (msg.includes("too many input tokens") ||
|
|
50
|
+
msg.includes("prompt is too long") ||
|
|
51
|
+
msg.includes("maximum context length") ||
|
|
52
|
+
msg.includes("maximum of 100 pdf pages") ||
|
|
53
|
+
msg.includes("pdf pages may be provided"));
|
|
54
|
+
}
|
|
55
|
+
export const anthropicProvider = {
|
|
56
|
+
id: "anthropic",
|
|
57
|
+
displayName: "Anthropic Claude",
|
|
58
|
+
models: MODELS,
|
|
59
|
+
defaultModel: DEFAULT_MODEL,
|
|
60
|
+
apiKeyUrl: "https://console.anthropic.com/settings/keys",
|
|
61
|
+
createModel: (apiKey, modelId) => {
|
|
62
|
+
const anthropic = createAnthropic({ apiKey });
|
|
63
|
+
return anthropic(modelId);
|
|
64
|
+
},
|
|
65
|
+
providerOptions: {},
|
|
66
|
+
preparePdf,
|
|
67
|
+
isTokenLimitError,
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEhE,MAAM,MAAM,GAAkB;IAC5B;QACE,EAAE,EAAE,mBAAmB;QACvB,WAAW,EAAE,mBAAmB;QAChC,IAAI,EAAE,yBAAyB;KAChC;IACD,EAAE,EAAE,EAAE,iBAAiB,EAAE,WAAW,EAAE,iBAAiB,EAAE,IAAI,EAAE,yBAAyB,EAAE;CAC3F,CAAC;AAEF,MAAM,aAAa,GAAG,iBAAiB,CAAC;AAExC;;GAEG;AACH,KAAK,UAAU,UAAU,CAAC,MAAiB;IACzC,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IAED,IAAI,KAAiB,CAAC;IAEtB,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC5B,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IACvB,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QACjC,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5D,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,IAAI,GAAgB;QACxB,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,KAAK;QACX,SAAS,EAAE,iBAAiB;KAC7B,CAAC;IACF,OAAO,EAAE,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,KAAc;IACvC,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IACxC,OAAO,CACL,GAAG,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QACrC,GAAG,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAClC,GAAG,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QACtC,GAAG,CAAC,QAAQ,CAAC,0BAA0B,CAAC;QACxC,GAAG,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAC1C,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAmB;IAC/C,EAAE,EAAE,WAAW;IACf,WAAW,EAAE,kBAAkB;IAC/B,MAAM,EAAE,MAAM;IACd,YAAY,EAAE,aAAa;IAC3B,SAAS,EAAE,6CAA6C;IACxD,WAAW,EAAE,CAAC,MAAc,EAAE,OAAe,EAAE,EAAE;QAC/C,MAAM,SAAS,GAAG,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9C,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IACD,eAAe,EAAE,EAAE;IACnB,UAAU;IACV,iBAAiB;CAClB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Gemini provider.
|
|
3
|
+
*
|
|
4
|
+
* Uses the Gemini File API for uploading PDFs (supports large files and caching),
|
|
5
|
+
* and the Vercel AI SDK for LLM calls.
|
|
6
|
+
*/
|
|
7
|
+
import type { ProviderConfig } from "./types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Check if a string is a Gemini File API URI.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isGeminiFileUri(source: string): boolean;
|
|
12
|
+
export declare const googleProvider: ProviderConfig;
|
|
13
|
+
//# sourceMappingURL=google.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../src/providers/google.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAoD,MAAM,YAAY,CAAC;AAiBnG;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEvD;AA6FD,eAAO,MAAM,cAAc,EAAE,cAe5B,CAAC"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Gemini provider.
|
|
3
|
+
*
|
|
4
|
+
* Uses the Gemini File API for uploading PDFs (supports large files and caching),
|
|
5
|
+
* and the Vercel AI SDK for LLM calls.
|
|
6
|
+
*/
|
|
7
|
+
import { GoogleGenAI, ApiError } from "@google/genai";
|
|
8
|
+
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
9
|
+
import { fetchPdfFromUrl, validateLocalPath } from "../pdf-utils.js";
|
|
10
|
+
const MODELS = [
|
|
11
|
+
{
|
|
12
|
+
id: "gemini-3-flash-preview",
|
|
13
|
+
displayName: "Gemini 3 Flash",
|
|
14
|
+
hint: "Fast and cost-effective",
|
|
15
|
+
},
|
|
16
|
+
{ id: "gemini-3.1-pro-preview", displayName: "Gemini 3.1 Pro", hint: "Best and most expensive" },
|
|
17
|
+
];
|
|
18
|
+
const DEFAULT_MODEL = "gemini-3.1-pro-preview";
|
|
19
|
+
/** Gemini File API URI prefix. */
|
|
20
|
+
const GEMINI_FILE_URI_PREFIX = "https://generativelanguage.googleapis.com/";
|
|
21
|
+
/**
|
|
22
|
+
* Check if a string is a Gemini File API URI.
|
|
23
|
+
*/
|
|
24
|
+
export function isGeminiFileUri(source) {
|
|
25
|
+
return source.startsWith(GEMINI_FILE_URI_PREFIX);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Wait for a file to finish processing on the Gemini File API.
|
|
29
|
+
*/
|
|
30
|
+
async function waitForFileReady(client, fileName, maxAttempts = 10) {
|
|
31
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
32
|
+
const fileInfo = await client.files.get({ name: fileName });
|
|
33
|
+
if (fileInfo.state === "FAILED") {
|
|
34
|
+
throw new Error(`File processing failed: ${fileInfo.name}`);
|
|
35
|
+
}
|
|
36
|
+
if (fileInfo.state !== "PROCESSING") {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
40
|
+
}
|
|
41
|
+
throw new Error("File processing timed out");
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Upload a PDF to the Gemini File API.
|
|
45
|
+
* Returns the Gemini File API URI.
|
|
46
|
+
*/
|
|
47
|
+
async function uploadToFileApi(client, data) {
|
|
48
|
+
const file = await client.files.upload(typeof data === "string"
|
|
49
|
+
? { file: data, config: { mimeType: "application/pdf" } }
|
|
50
|
+
: { file: data, config: { mimeType: "application/pdf" } });
|
|
51
|
+
if (!file.name || !file.uri) {
|
|
52
|
+
throw new Error("File upload failed: missing name or URI");
|
|
53
|
+
}
|
|
54
|
+
await waitForFileReady(client, file.name);
|
|
55
|
+
return file.uri;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Prepare a PDF source for Google Gemini.
|
|
59
|
+
* Uploads to the File API and returns a URL-based file part.
|
|
60
|
+
*/
|
|
61
|
+
async function preparePdf(source, apiKey) {
|
|
62
|
+
const client = new GoogleGenAI({ apiKey });
|
|
63
|
+
if (source.kind === "cachedUri") {
|
|
64
|
+
const part = {
|
|
65
|
+
type: "file",
|
|
66
|
+
data: new URL(source.uri),
|
|
67
|
+
mediaType: "application/pdf",
|
|
68
|
+
};
|
|
69
|
+
return { fileParts: [part], cachedUri: source.uri };
|
|
70
|
+
}
|
|
71
|
+
let fileUri;
|
|
72
|
+
if (source.kind === "bytes") {
|
|
73
|
+
const blob = new Blob([source.bytes], { type: "application/pdf" });
|
|
74
|
+
fileUri = await uploadToFileApi(client, blob);
|
|
75
|
+
}
|
|
76
|
+
else if (source.kind === "url") {
|
|
77
|
+
const pdfBuffer = await fetchPdfFromUrl(source.url);
|
|
78
|
+
const blob = new Blob([pdfBuffer], { type: "application/pdf" });
|
|
79
|
+
fileUri = await uploadToFileApi(client, blob);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
validateLocalPath(source.path);
|
|
83
|
+
fileUri = await uploadToFileApi(client, source.path);
|
|
84
|
+
}
|
|
85
|
+
const part = {
|
|
86
|
+
type: "file",
|
|
87
|
+
data: new URL(fileUri),
|
|
88
|
+
mediaType: "application/pdf",
|
|
89
|
+
};
|
|
90
|
+
return { fileParts: [part], cachedUri: fileUri };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if an error is a Gemini token limit error.
|
|
94
|
+
*/
|
|
95
|
+
function isTokenLimitError(error) {
|
|
96
|
+
if (error instanceof ApiError) {
|
|
97
|
+
return error.status === 400 && error.message.includes("input token count exceeds");
|
|
98
|
+
}
|
|
99
|
+
if (error instanceof Error) {
|
|
100
|
+
return error.message.includes("input token count exceeds");
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
export const googleProvider = {
|
|
105
|
+
id: "google",
|
|
106
|
+
displayName: "Google Gemini",
|
|
107
|
+
models: MODELS,
|
|
108
|
+
defaultModel: DEFAULT_MODEL,
|
|
109
|
+
apiKeyUrl: "https://aistudio.google.com/apikey",
|
|
110
|
+
createModel: (apiKey, modelId) => {
|
|
111
|
+
const google = createGoogleGenerativeAI({ apiKey });
|
|
112
|
+
return google(modelId);
|
|
113
|
+
},
|
|
114
|
+
providerOptions: {
|
|
115
|
+
google: { thinkingConfig: { thinkingLevel: "low" } },
|
|
116
|
+
},
|
|
117
|
+
preparePdf,
|
|
118
|
+
isTokenLimitError,
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=google.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.js","sourceRoot":"","sources":["../../src/providers/google.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAoD,MAAM,YAAY,CAAC;AAsDnG,eAAO,MAAM,cAAc,EAAE,cAe5B,CAAC"}
|