call-ai 0.10.2 → 0.11.0-dev-preview3
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/README.md +60 -58
- package/api-core.d.ts +13 -0
- package/{dist/api-core.js → api-core.js} +51 -126
- package/api-core.js.map +1 -0
- package/api.d.ts +4 -0
- package/api.js +364 -0
- package/api.js.map +1 -0
- package/api.ts.off +595 -0
- package/{dist/error-handling.d.ts → error-handling.d.ts} +4 -2
- package/{dist/error-handling.js → error-handling.js} +34 -70
- package/error-handling.js.map +1 -0
- package/image.d.ts +2 -0
- package/{dist/image.js → image.js} +10 -33
- package/image.js.map +1 -0
- package/index.d.ts +6 -0
- package/index.js +7 -0
- package/index.js.map +1 -0
- package/index.ts.bak +16 -0
- package/key-management.d.ts +29 -0
- package/key-management.js +189 -0
- package/key-management.js.map +1 -0
- package/{dist/non-streaming.d.ts → non-streaming.d.ts} +5 -8
- package/{dist/non-streaming.js → non-streaming.js} +28 -87
- package/non-streaming.js.map +1 -0
- package/package.json +15 -31
- package/response-metadata.d.ts +6 -0
- package/response-metadata.js +22 -0
- package/response-metadata.js.map +1 -0
- package/strategies/index.d.ts +2 -0
- package/strategies/index.js +3 -0
- package/strategies/index.js.map +1 -0
- package/strategies/model-strategies.d.ts +6 -0
- package/{dist/strategies → strategies}/model-strategies.js +26 -72
- package/strategies/model-strategies.js.map +1 -0
- package/strategies/strategy-selector.d.ts +2 -0
- package/strategies/strategy-selector.js +66 -0
- package/strategies/strategy-selector.js.map +1 -0
- package/streaming.d.ts +4 -0
- package/{dist/streaming.js → streaming.js} +66 -184
- package/streaming.js.map +1 -0
- package/streaming.ts.off +571 -0
- package/tsconfig.json +18 -0
- package/types.d.ts +226 -0
- package/types.js +33 -0
- package/types.js.map +1 -0
- package/utils.d.ts +32 -0
- package/utils.js +129 -0
- package/utils.js.map +1 -0
- package/version.d.ts +1 -0
- package/version.js +2 -0
- package/version.js.map +1 -0
- package/dist/api-core.d.ts +0 -40
- package/dist/api.d.ts +0 -15
- package/dist/api.js +0 -498
- package/dist/image.d.ts +0 -12
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -32
- package/dist/key-management.d.ts +0 -43
- package/dist/key-management.js +0 -312
- package/dist/response-metadata.d.ts +0 -18
- package/dist/response-metadata.js +0 -44
- package/dist/strategies/index.d.ts +0 -5
- package/dist/strategies/index.js +0 -21
- package/dist/strategies/model-strategies.d.ts +0 -24
- package/dist/strategies/strategy-selector.d.ts +0 -8
- package/dist/strategies/strategy-selector.js +0 -79
- package/dist/streaming.d.ts +0 -7
- package/dist/types.d.ts +0 -226
- package/dist/types.js +0 -5
- package/dist/utils.d.ts +0 -8
- package/dist/utils.js +0 -52
package/dist/key-management.js
DELETED
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Key management functionality for call-ai
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.globalDebug = exports.keyStore = void 0;
|
|
7
|
-
exports.initKeyStore = initKeyStore;
|
|
8
|
-
exports.isNewKeyError = isNewKeyError;
|
|
9
|
-
exports.refreshApiKey = refreshApiKey;
|
|
10
|
-
exports.getHashFromKey = getHashFromKey;
|
|
11
|
-
exports.storeKeyMetadata = storeKeyMetadata;
|
|
12
|
-
// Internal key store to keep track of the latest key
|
|
13
|
-
const keyStore = {
|
|
14
|
-
// Default key from environment or config
|
|
15
|
-
current: null,
|
|
16
|
-
// The refresh endpoint URL - defaults to vibecode.garden
|
|
17
|
-
refreshEndpoint: "https://vibecode.garden",
|
|
18
|
-
// Authentication token for refresh endpoint - defaults to use-vibes
|
|
19
|
-
refreshToken: "use-vibes",
|
|
20
|
-
// Flag to prevent concurrent refresh attempts
|
|
21
|
-
isRefreshing: false,
|
|
22
|
-
// Timestamp of last refresh attempt (to prevent too frequent refreshes)
|
|
23
|
-
lastRefreshAttempt: 0,
|
|
24
|
-
// Storage for key metadata (useful for future top-up implementation)
|
|
25
|
-
metadata: {},
|
|
26
|
-
};
|
|
27
|
-
exports.keyStore = keyStore;
|
|
28
|
-
// Global debug flag
|
|
29
|
-
let globalDebug = false;
|
|
30
|
-
exports.globalDebug = globalDebug;
|
|
31
|
-
/**
|
|
32
|
-
* Initialize key store with environment variables
|
|
33
|
-
*/
|
|
34
|
-
function initKeyStore() {
|
|
35
|
-
// Initialize with environment variables if available
|
|
36
|
-
if (typeof process !== "undefined" && process.env) {
|
|
37
|
-
if (process.env.CALLAI_API_KEY) {
|
|
38
|
-
keyStore.current = process.env.CALLAI_API_KEY;
|
|
39
|
-
}
|
|
40
|
-
// Support both CALLAI_REFRESH_ENDPOINT and CALLAI_REKEY_ENDPOINT for backward compatibility
|
|
41
|
-
if (process.env.CALLAI_REFRESH_ENDPOINT) {
|
|
42
|
-
keyStore.refreshEndpoint = process.env.CALLAI_REFRESH_ENDPOINT;
|
|
43
|
-
}
|
|
44
|
-
else if (process.env.CALLAI_REKEY_ENDPOINT) {
|
|
45
|
-
keyStore.refreshEndpoint = process.env.CALLAI_REKEY_ENDPOINT;
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
// Default to vibecode.garden if not specified
|
|
49
|
-
keyStore.refreshEndpoint = "https://vibecode.garden";
|
|
50
|
-
}
|
|
51
|
-
// Support both CALL_AI_REFRESH_TOKEN and CALL_AI_KEY_TOKEN for backward compatibility
|
|
52
|
-
if (process.env.CALL_AI_REFRESH_TOKEN) {
|
|
53
|
-
keyStore.refreshToken = process.env.CALL_AI_REFRESH_TOKEN;
|
|
54
|
-
}
|
|
55
|
-
else if (process.env.CALL_AI_KEY_TOKEN) {
|
|
56
|
-
keyStore.refreshToken = process.env.CALL_AI_KEY_TOKEN;
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
// Default to use-vibes if not specified - this is the default token for vibecode.garden
|
|
60
|
-
keyStore.refreshToken = "use-vibes";
|
|
61
|
-
}
|
|
62
|
-
// Check for CALLAI_DEBUG environment variable (any truthy value works)
|
|
63
|
-
if (process.env.CALLAI_DEBUG) {
|
|
64
|
-
// Set the global debug flag
|
|
65
|
-
exports.globalDebug = globalDebug = true;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
// Initialize from window globals if in browser context
|
|
69
|
-
else if (typeof window !== "undefined") {
|
|
70
|
-
// Use window.CALLAI_API_KEY or window.callAi.API_KEY if available
|
|
71
|
-
if (window.CALLAI_API_KEY) {
|
|
72
|
-
keyStore.current = window.CALLAI_API_KEY;
|
|
73
|
-
}
|
|
74
|
-
else if (window.callAi?.API_KEY) {
|
|
75
|
-
keyStore.current = window.callAi.API_KEY;
|
|
76
|
-
}
|
|
77
|
-
// Check for debug flag in browser environment
|
|
78
|
-
if (window.CALLAI_DEBUG) {
|
|
79
|
-
exports.globalDebug = globalDebug = true;
|
|
80
|
-
}
|
|
81
|
-
keyStore.refreshEndpoint =
|
|
82
|
-
window.CALLAI_REFRESH_ENDPOINT || keyStore.refreshEndpoint;
|
|
83
|
-
keyStore.refreshToken =
|
|
84
|
-
window.CALL_AI_REFRESH_TOKEN || keyStore.refreshToken;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
// Initialize on module load
|
|
88
|
-
initKeyStore();
|
|
89
|
-
/**
|
|
90
|
-
* Check if an error indicates we need a new API key
|
|
91
|
-
* @param error The error to check
|
|
92
|
-
* @param debug Whether to log debug information
|
|
93
|
-
* @returns True if the error suggests we need a new key
|
|
94
|
-
*/
|
|
95
|
-
function isNewKeyError(error, debug = false) {
|
|
96
|
-
// Extract status from error object or message text
|
|
97
|
-
let status = error?.status || error?.statusCode || error?.response?.status;
|
|
98
|
-
const errorMessage = String(error || "").toLowerCase();
|
|
99
|
-
// Extract status code from error message if not found in the object properties
|
|
100
|
-
// Handle messages like "HTTP error! Status: 403" common in fetch errors
|
|
101
|
-
if (!status && errorMessage.includes("status:")) {
|
|
102
|
-
const statusMatch = errorMessage.match(/status:\\s*(\\d+)/i);
|
|
103
|
-
if (statusMatch && statusMatch[1]) {
|
|
104
|
-
status = parseInt(statusMatch[1], 10);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
const is4xx = status >= 400 && status < 500;
|
|
108
|
-
// Check for various error types that indicate key issues
|
|
109
|
-
const isAuthError = status === 401 ||
|
|
110
|
-
status === 403 ||
|
|
111
|
-
errorMessage.includes("unauthorized") ||
|
|
112
|
-
errorMessage.includes("forbidden") ||
|
|
113
|
-
errorMessage.includes("authentication") ||
|
|
114
|
-
errorMessage.includes("api key") ||
|
|
115
|
-
errorMessage.includes("apikey") ||
|
|
116
|
-
errorMessage.includes("auth");
|
|
117
|
-
// More specific message checks, especially for common API providers
|
|
118
|
-
const isInvalidKeyError = errorMessage.includes("invalid api key") ||
|
|
119
|
-
errorMessage.includes("invalid key") ||
|
|
120
|
-
errorMessage.includes("incorrect api key") ||
|
|
121
|
-
errorMessage.includes("incorrect key") ||
|
|
122
|
-
errorMessage.includes("authentication failed") ||
|
|
123
|
-
errorMessage.includes("not authorized");
|
|
124
|
-
// Check for OpenAI specific error patterns
|
|
125
|
-
const isOpenAIKeyError = errorMessage.includes("openai") &&
|
|
126
|
-
(errorMessage.includes("api key") ||
|
|
127
|
-
errorMessage.includes("authentication"));
|
|
128
|
-
// Check for rate limit errors which might indicate a key top-up is needed
|
|
129
|
-
const isRateLimitError = status === 429 ||
|
|
130
|
-
errorMessage.includes("rate limit") ||
|
|
131
|
-
errorMessage.includes("too many requests") ||
|
|
132
|
-
errorMessage.includes("quota") ||
|
|
133
|
-
errorMessage.includes("exceed");
|
|
134
|
-
// Check for billing or payment errors
|
|
135
|
-
const isBillingError = errorMessage.includes("billing") ||
|
|
136
|
-
errorMessage.includes("payment") ||
|
|
137
|
-
errorMessage.includes("subscription") ||
|
|
138
|
-
errorMessage.includes("account");
|
|
139
|
-
// Simple heuristic: if it's a 4xx error with any key-related terms, likely needs key refresh
|
|
140
|
-
const needsNewKey = is4xx &&
|
|
141
|
-
(isAuthError ||
|
|
142
|
-
isInvalidKeyError ||
|
|
143
|
-
isOpenAIKeyError ||
|
|
144
|
-
isRateLimitError ||
|
|
145
|
-
isBillingError);
|
|
146
|
-
if (debug && needsNewKey) {
|
|
147
|
-
console.log(`[callAi:key-refresh] Detected error requiring key refresh: ${errorMessage}`);
|
|
148
|
-
}
|
|
149
|
-
return needsNewKey;
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Refreshes the API key by calling the specified endpoint
|
|
153
|
-
* @param currentKey The current API key (may be null for initial key request)
|
|
154
|
-
* @param endpoint The endpoint to call for key refresh
|
|
155
|
-
* @param refreshToken Authentication token for the refresh endpoint
|
|
156
|
-
* @returns Object containing the API key and topup flag
|
|
157
|
-
*/
|
|
158
|
-
async function refreshApiKey(currentKey, endpoint, refreshToken, debug = globalDebug) {
|
|
159
|
-
// Ensure we have an endpoint and refreshToken
|
|
160
|
-
if (!endpoint) {
|
|
161
|
-
throw new Error("No API key refresh endpoint specified");
|
|
162
|
-
}
|
|
163
|
-
if (!refreshToken) {
|
|
164
|
-
throw new Error("No API key refresh token specified");
|
|
165
|
-
}
|
|
166
|
-
// Check if we're already in the process of refreshing (to prevent parallel refreshes)
|
|
167
|
-
if (keyStore.isRefreshing) {
|
|
168
|
-
if (debug) {
|
|
169
|
-
console.log("API key refresh already in progress, waiting...");
|
|
170
|
-
}
|
|
171
|
-
// Wait for refresh to complete (simple polling)
|
|
172
|
-
return new Promise((resolve) => {
|
|
173
|
-
const checkInterval = setInterval(() => {
|
|
174
|
-
if (!keyStore.isRefreshing && keyStore.current) {
|
|
175
|
-
clearInterval(checkInterval);
|
|
176
|
-
resolve({ apiKey: keyStore.current, topup: false });
|
|
177
|
-
}
|
|
178
|
-
}, 100);
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
// Rate limit key refresh to prevent overloading the service
|
|
182
|
-
const now = Date.now();
|
|
183
|
-
const timeSinceLastRefresh = now - keyStore.lastRefreshAttempt;
|
|
184
|
-
const minRefreshInterval = 2000; // 2 seconds minimum interval between refreshes
|
|
185
|
-
if (timeSinceLastRefresh < minRefreshInterval) {
|
|
186
|
-
if (debug) {
|
|
187
|
-
console.log(`Rate limiting key refresh, last attempt was ${timeSinceLastRefresh}ms ago`);
|
|
188
|
-
}
|
|
189
|
-
// If we've refreshed too recently, wait a bit
|
|
190
|
-
await new Promise((resolve) => setTimeout(resolve, minRefreshInterval - timeSinceLastRefresh));
|
|
191
|
-
}
|
|
192
|
-
// Set refreshing flag and update last attempt timestamp
|
|
193
|
-
keyStore.isRefreshing = true;
|
|
194
|
-
keyStore.lastRefreshAttempt = Date.now();
|
|
195
|
-
// Process API paths
|
|
196
|
-
let apiPath = "/api/keys";
|
|
197
|
-
// Normalize endpoint URL to remove any trailing slashes
|
|
198
|
-
const baseUrl = endpoint.endsWith("/") ? endpoint.slice(0, -1) : endpoint;
|
|
199
|
-
// Construct the full URL
|
|
200
|
-
const url = `${baseUrl}${apiPath}`;
|
|
201
|
-
if (debug) {
|
|
202
|
-
console.log(`Refreshing API key from: ${url}`);
|
|
203
|
-
}
|
|
204
|
-
try {
|
|
205
|
-
// Request payload
|
|
206
|
-
const requestPayload = {
|
|
207
|
-
key: currentKey,
|
|
208
|
-
hash: currentKey ? getHashFromKey(currentKey) : null,
|
|
209
|
-
name: "call-ai-client", // Add the required name field
|
|
210
|
-
};
|
|
211
|
-
if (debug) {
|
|
212
|
-
console.log(`[callAi:key-refresh] Request URL: ${url}`);
|
|
213
|
-
console.log(`[callAi:key-refresh] Request headers:`, {
|
|
214
|
-
"Content-Type": "application/json",
|
|
215
|
-
Authorization: `Bearer ${refreshToken}`,
|
|
216
|
-
});
|
|
217
|
-
console.log(`[callAi:key-refresh] Request payload:`, requestPayload);
|
|
218
|
-
}
|
|
219
|
-
// Make the request
|
|
220
|
-
const response = await fetch(url, {
|
|
221
|
-
method: "POST",
|
|
222
|
-
headers: {
|
|
223
|
-
"Content-Type": "application/json",
|
|
224
|
-
Authorization: `Bearer ${refreshToken}`,
|
|
225
|
-
},
|
|
226
|
-
body: JSON.stringify(requestPayload),
|
|
227
|
-
});
|
|
228
|
-
if (debug) {
|
|
229
|
-
console.log(`[callAi:key-refresh] Response status: ${response.status} ${response.statusText}`);
|
|
230
|
-
console.log(`[callAi:key-refresh] Response headers:`, Object.fromEntries([...response.headers.entries()]));
|
|
231
|
-
}
|
|
232
|
-
if (!response.ok) {
|
|
233
|
-
// Try to get the response body for more details
|
|
234
|
-
const errorText = await response.text();
|
|
235
|
-
if (debug) {
|
|
236
|
-
console.log(`[callAi:key-refresh] Error response body: ${errorText}`);
|
|
237
|
-
}
|
|
238
|
-
throw new Error(`API key refresh failed: ${response.status} ${response.statusText}${errorText ? ` - ${errorText}` : ""}`);
|
|
239
|
-
}
|
|
240
|
-
// Parse the response
|
|
241
|
-
const data = await response.json();
|
|
242
|
-
// Log the complete response structure for debugging
|
|
243
|
-
if (debug) {
|
|
244
|
-
console.log(`[callAi:key-refresh] Full response structure:`, JSON.stringify(data, null, 2));
|
|
245
|
-
}
|
|
246
|
-
// Handle different API response formats
|
|
247
|
-
let newKey;
|
|
248
|
-
// Check if response has the new nested format with data.key.key
|
|
249
|
-
if (data.key && typeof data.key === "object" && data.key.key) {
|
|
250
|
-
newKey = data.key.key;
|
|
251
|
-
}
|
|
252
|
-
// Check for old format where data.key is the string key directly
|
|
253
|
-
else if (data.key && typeof data.key === "string") {
|
|
254
|
-
newKey = data.key;
|
|
255
|
-
}
|
|
256
|
-
// Handle error case
|
|
257
|
-
else {
|
|
258
|
-
throw new Error("Invalid response from key refresh endpoint: missing or malformed key");
|
|
259
|
-
}
|
|
260
|
-
if (debug) {
|
|
261
|
-
console.log(`API key refreshed successfully: ${newKey.substring(0, 10)}...`);
|
|
262
|
-
}
|
|
263
|
-
// Store metadata for potential future use (like top-up)
|
|
264
|
-
if (data.metadata ||
|
|
265
|
-
(data.key && typeof data.key === "object" && data.key.metadata)) {
|
|
266
|
-
const metadata = data.metadata || data.key.metadata;
|
|
267
|
-
storeKeyMetadata(metadata);
|
|
268
|
-
}
|
|
269
|
-
// Update the key store with the string value
|
|
270
|
-
keyStore.current = newKey;
|
|
271
|
-
// Determine if this was a top-up (using existing key) or new key
|
|
272
|
-
// For the new API response format, hash is in data.key.hash
|
|
273
|
-
const hashValue = data.hash || (data.key && typeof data.key === "object" && data.key.hash);
|
|
274
|
-
const isTopup = currentKey && hashValue && hashValue === getHashFromKey(currentKey);
|
|
275
|
-
// Reset refreshing flag
|
|
276
|
-
keyStore.isRefreshing = false;
|
|
277
|
-
return {
|
|
278
|
-
apiKey: newKey, // Return the string key, not the object
|
|
279
|
-
topup: isTopup,
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
catch (error) {
|
|
283
|
-
// Reset refreshing flag
|
|
284
|
-
keyStore.isRefreshing = false;
|
|
285
|
-
throw error;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Helper function to extract hash from key (implementation depends on how you store metadata)
|
|
290
|
-
*/
|
|
291
|
-
function getHashFromKey(key) {
|
|
292
|
-
if (!key)
|
|
293
|
-
return null;
|
|
294
|
-
// Simple implementation: just look up in our metadata store
|
|
295
|
-
const metaKey = Object.keys(keyStore.metadata).find((k) => k === key);
|
|
296
|
-
return metaKey ? keyStore.metadata[metaKey].hash || null : null;
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Helper function to store key metadata for future reference
|
|
300
|
-
*/
|
|
301
|
-
function storeKeyMetadata(data) {
|
|
302
|
-
if (!data || !data.key)
|
|
303
|
-
return;
|
|
304
|
-
// Store metadata with the key as the dictionary key
|
|
305
|
-
keyStore.metadata[data.key] = {
|
|
306
|
-
hash: data.hash || null,
|
|
307
|
-
created: data.created || Date.now(),
|
|
308
|
-
expires: data.expires || null,
|
|
309
|
-
remaining: data.remaining || null,
|
|
310
|
-
limit: data.limit || null,
|
|
311
|
-
};
|
|
312
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Response metadata handling for call-ai
|
|
3
|
-
*/
|
|
4
|
-
import { ResponseMeta } from "./types";
|
|
5
|
-
declare const responseMetadata: WeakMap<object, ResponseMeta>;
|
|
6
|
-
declare const stringResponseMap: Map<string, object>;
|
|
7
|
-
/**
|
|
8
|
-
* Helper to box a string so it can be used with WeakMap
|
|
9
|
-
* @internal
|
|
10
|
-
*/
|
|
11
|
-
declare function boxString(str: string): object;
|
|
12
|
-
/**
|
|
13
|
-
* Retrieve metadata associated with a response from callAi()
|
|
14
|
-
* @param response A response from callAi, either string or AsyncGenerator
|
|
15
|
-
* @returns The metadata object if available, undefined otherwise
|
|
16
|
-
*/
|
|
17
|
-
declare function getMeta(response: string | AsyncGenerator<string, string, unknown>): ResponseMeta | undefined;
|
|
18
|
-
export { responseMetadata, stringResponseMap, boxString, getMeta };
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Response metadata handling for call-ai
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.stringResponseMap = exports.responseMetadata = void 0;
|
|
7
|
-
exports.boxString = boxString;
|
|
8
|
-
exports.getMeta = getMeta;
|
|
9
|
-
// WeakMap to store metadata for responses without modifying the response objects
|
|
10
|
-
const responseMetadata = new WeakMap();
|
|
11
|
-
exports.responseMetadata = responseMetadata;
|
|
12
|
-
// Store for string responses - we need to box strings since WeakMap keys must be objects
|
|
13
|
-
const stringResponseMap = new Map();
|
|
14
|
-
exports.stringResponseMap = stringResponseMap;
|
|
15
|
-
/**
|
|
16
|
-
* Helper to box a string so it can be used with WeakMap
|
|
17
|
-
* @internal
|
|
18
|
-
*/
|
|
19
|
-
function boxString(str) {
|
|
20
|
-
// Check if already boxed
|
|
21
|
-
if (stringResponseMap.has(str)) {
|
|
22
|
-
return stringResponseMap.get(str);
|
|
23
|
-
}
|
|
24
|
-
// Create a new box
|
|
25
|
-
const box = Object.create(null);
|
|
26
|
-
stringResponseMap.set(str, box);
|
|
27
|
-
return box;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Retrieve metadata associated with a response from callAi()
|
|
31
|
-
* @param response A response from callAi, either string or AsyncGenerator
|
|
32
|
-
* @returns The metadata object if available, undefined otherwise
|
|
33
|
-
*/
|
|
34
|
-
function getMeta(response) {
|
|
35
|
-
if (typeof response === "string") {
|
|
36
|
-
const box = stringResponseMap.get(response);
|
|
37
|
-
if (box) {
|
|
38
|
-
return responseMetadata.get(box);
|
|
39
|
-
}
|
|
40
|
-
return undefined;
|
|
41
|
-
}
|
|
42
|
-
// For AsyncGenerator and other objects, look up directly
|
|
43
|
-
return responseMetadata.get(response);
|
|
44
|
-
}
|
package/dist/strategies/index.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
/**
|
|
18
|
-
* Strategy exports
|
|
19
|
-
*/
|
|
20
|
-
__exportStar(require("./model-strategies"), exports);
|
|
21
|
-
__exportStar(require("./strategy-selector"), exports);
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Model strategies for different AI models
|
|
3
|
-
*/
|
|
4
|
-
import { ModelStrategy } from "../types";
|
|
5
|
-
/**
|
|
6
|
-
* OpenAI/GPT strategy for handling JSON schema
|
|
7
|
-
*/
|
|
8
|
-
export declare const openAIStrategy: ModelStrategy;
|
|
9
|
-
/**
|
|
10
|
-
* Gemini strategy for handling JSON schema (similar to OpenAI)
|
|
11
|
-
*/
|
|
12
|
-
export declare const geminiStrategy: ModelStrategy;
|
|
13
|
-
/**
|
|
14
|
-
* Claude strategy using tool mode for structured output
|
|
15
|
-
*/
|
|
16
|
-
export declare const claudeStrategy: ModelStrategy;
|
|
17
|
-
/**
|
|
18
|
-
* System message approach for other models (Llama, DeepSeek, etc.)
|
|
19
|
-
*/
|
|
20
|
-
export declare const systemMessageStrategy: ModelStrategy;
|
|
21
|
-
/**
|
|
22
|
-
* Default strategy for models without schema
|
|
23
|
-
*/
|
|
24
|
-
export declare const defaultStrategy: ModelStrategy;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Strategy selection logic for different AI models
|
|
3
|
-
*/
|
|
4
|
-
import { Schema, SchemaStrategy } from "../types";
|
|
5
|
-
/**
|
|
6
|
-
* Choose the appropriate schema strategy based on model and schema
|
|
7
|
-
*/
|
|
8
|
-
export declare function chooseSchemaStrategy(model: string | undefined, schema: Schema | null): SchemaStrategy;
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.chooseSchemaStrategy = chooseSchemaStrategy;
|
|
4
|
-
const model_strategies_1 = require("./model-strategies");
|
|
5
|
-
/**
|
|
6
|
-
* Choose the appropriate schema strategy based on model and schema
|
|
7
|
-
*/
|
|
8
|
-
function chooseSchemaStrategy(model, schema) {
|
|
9
|
-
// Default model if not provided
|
|
10
|
-
const resolvedModel = model || (schema ? "openai/gpt-4o" : "openrouter/auto");
|
|
11
|
-
// No schema case - use default strategy
|
|
12
|
-
if (!schema) {
|
|
13
|
-
return {
|
|
14
|
-
strategy: "none",
|
|
15
|
-
model: resolvedModel,
|
|
16
|
-
prepareRequest: model_strategies_1.defaultStrategy.prepareRequest,
|
|
17
|
-
processResponse: model_strategies_1.defaultStrategy.processResponse,
|
|
18
|
-
shouldForceStream: false,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
// Check for Claude models
|
|
22
|
-
if (/claude/i.test(resolvedModel)) {
|
|
23
|
-
return {
|
|
24
|
-
strategy: "tool_mode",
|
|
25
|
-
model: resolvedModel,
|
|
26
|
-
prepareRequest: model_strategies_1.claudeStrategy.prepareRequest,
|
|
27
|
-
processResponse: model_strategies_1.claudeStrategy.processResponse,
|
|
28
|
-
shouldForceStream: !!model_strategies_1.claudeStrategy.shouldForceStream,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
// Check for Gemini models
|
|
32
|
-
if (/gemini/i.test(resolvedModel)) {
|
|
33
|
-
return {
|
|
34
|
-
strategy: "json_schema",
|
|
35
|
-
model: resolvedModel,
|
|
36
|
-
prepareRequest: model_strategies_1.geminiStrategy.prepareRequest,
|
|
37
|
-
processResponse: model_strategies_1.geminiStrategy.processResponse,
|
|
38
|
-
shouldForceStream: !!model_strategies_1.geminiStrategy.shouldForceStream,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
// Check for GPT-4 Turbo models - use system message approach
|
|
42
|
-
if (/gpt-4-turbo/i.test(resolvedModel)) {
|
|
43
|
-
return {
|
|
44
|
-
strategy: "system_message",
|
|
45
|
-
model: resolvedModel,
|
|
46
|
-
prepareRequest: model_strategies_1.systemMessageStrategy.prepareRequest,
|
|
47
|
-
processResponse: model_strategies_1.systemMessageStrategy.processResponse,
|
|
48
|
-
shouldForceStream: !!model_strategies_1.systemMessageStrategy.shouldForceStream,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
// Check for OpenAI models
|
|
52
|
-
if (/openai|gpt/i.test(resolvedModel)) {
|
|
53
|
-
return {
|
|
54
|
-
strategy: "json_schema",
|
|
55
|
-
model: resolvedModel,
|
|
56
|
-
prepareRequest: model_strategies_1.openAIStrategy.prepareRequest,
|
|
57
|
-
processResponse: model_strategies_1.openAIStrategy.processResponse,
|
|
58
|
-
shouldForceStream: !!model_strategies_1.openAIStrategy.shouldForceStream,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
// Check for other specific models that need system message approach
|
|
62
|
-
if (/llama-3|deepseek/i.test(resolvedModel)) {
|
|
63
|
-
return {
|
|
64
|
-
strategy: "system_message",
|
|
65
|
-
model: resolvedModel,
|
|
66
|
-
prepareRequest: model_strategies_1.systemMessageStrategy.prepareRequest,
|
|
67
|
-
processResponse: model_strategies_1.systemMessageStrategy.processResponse,
|
|
68
|
-
shouldForceStream: !!model_strategies_1.systemMessageStrategy.shouldForceStream,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
// Default to system message approach for unknown models with schema
|
|
72
|
-
return {
|
|
73
|
-
strategy: "system_message",
|
|
74
|
-
model: resolvedModel,
|
|
75
|
-
prepareRequest: model_strategies_1.systemMessageStrategy.prepareRequest,
|
|
76
|
-
processResponse: model_strategies_1.systemMessageStrategy.processResponse,
|
|
77
|
-
shouldForceStream: !!model_strategies_1.systemMessageStrategy.shouldForceStream,
|
|
78
|
-
};
|
|
79
|
-
}
|
package/dist/streaming.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Streaming response handling for call-ai
|
|
3
|
-
*/
|
|
4
|
-
import { CallAIOptions, SchemaStrategy } from "./types";
|
|
5
|
-
declare function createStreamingGenerator(response: Response, options: CallAIOptions, schemaStrategy: SchemaStrategy, model: string): AsyncGenerator<string, string, unknown>;
|
|
6
|
-
declare function callAIStreaming(prompt: string | any[], options?: CallAIOptions, isRetry?: boolean): AsyncGenerator<string, string, unknown>;
|
|
7
|
-
export { createStreamingGenerator, callAIStreaming };
|