@probeo/anymodel 0.4.0 → 0.5.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/README.md +21 -3
- package/dist/cli.cjs +368 -17
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +368 -17
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +377 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +374 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -485,6 +485,25 @@ var Router = class {
|
|
|
485
485
|
}
|
|
486
486
|
};
|
|
487
487
|
|
|
488
|
+
// src/utils/fetch-with-timeout.ts
|
|
489
|
+
var _defaultTimeout = 12e4;
|
|
490
|
+
var _flexTimeout = 6e5;
|
|
491
|
+
function setDefaultTimeout(ms) {
|
|
492
|
+
_defaultTimeout = ms;
|
|
493
|
+
}
|
|
494
|
+
function getFlexTimeout() {
|
|
495
|
+
return _flexTimeout;
|
|
496
|
+
}
|
|
497
|
+
function fetchWithTimeout(url, init, timeoutMs) {
|
|
498
|
+
const ms = timeoutMs ?? _defaultTimeout;
|
|
499
|
+
const signal = AbortSignal.timeout(ms);
|
|
500
|
+
if (init?.signal) {
|
|
501
|
+
const combined = AbortSignal.any([signal, init.signal]);
|
|
502
|
+
return fetch(url, { ...init, signal: combined });
|
|
503
|
+
}
|
|
504
|
+
return fetch(url, { ...init, signal });
|
|
505
|
+
}
|
|
506
|
+
|
|
488
507
|
// src/providers/openai.ts
|
|
489
508
|
var OPENAI_API_BASE = "https://api.openai.com/v1";
|
|
490
509
|
var SUPPORTED_PARAMS = /* @__PURE__ */ new Set([
|
|
@@ -502,19 +521,20 @@ var SUPPORTED_PARAMS = /* @__PURE__ */ new Set([
|
|
|
502
521
|
"tools",
|
|
503
522
|
"tool_choice",
|
|
504
523
|
"user",
|
|
505
|
-
"logit_bias"
|
|
524
|
+
"logit_bias",
|
|
525
|
+
"service_tier"
|
|
506
526
|
]);
|
|
507
527
|
function createOpenAIAdapter(apiKey, baseURL) {
|
|
508
528
|
const base = baseURL || OPENAI_API_BASE;
|
|
509
|
-
async function makeRequest(path2, body, method = "POST") {
|
|
510
|
-
const res = await
|
|
529
|
+
async function makeRequest(path2, body, method = "POST", timeoutMs) {
|
|
530
|
+
const res = await fetchWithTimeout(`${base}${path2}`, {
|
|
511
531
|
method,
|
|
512
532
|
headers: {
|
|
513
533
|
"Content-Type": "application/json",
|
|
514
534
|
"Authorization": `Bearer ${apiKey}`
|
|
515
535
|
},
|
|
516
536
|
body: body ? JSON.stringify(body) : void 0
|
|
517
|
-
});
|
|
537
|
+
}, timeoutMs);
|
|
518
538
|
if (!res.ok) {
|
|
519
539
|
let errorBody;
|
|
520
540
|
try {
|
|
@@ -562,6 +582,7 @@ function createOpenAIAdapter(apiKey, baseURL) {
|
|
|
562
582
|
if (request.tools !== void 0) body.tools = request.tools;
|
|
563
583
|
if (request.tool_choice !== void 0) body.tool_choice = request.tool_choice;
|
|
564
584
|
if (request.user !== void 0) body.user = request.user;
|
|
585
|
+
if (request.service_tier !== void 0) body.service_tier = request.service_tier;
|
|
565
586
|
return body;
|
|
566
587
|
}
|
|
567
588
|
const adapter = {
|
|
@@ -663,13 +684,15 @@ function createOpenAIAdapter(apiKey, baseURL) {
|
|
|
663
684
|
},
|
|
664
685
|
async sendRequest(request) {
|
|
665
686
|
const body = buildRequestBody(request);
|
|
666
|
-
const
|
|
687
|
+
const timeout = request.service_tier === "flex" ? getFlexTimeout() : void 0;
|
|
688
|
+
const res = await makeRequest("/chat/completions", body, "POST", timeout);
|
|
667
689
|
const json = await res.json();
|
|
668
690
|
return adapter.translateResponse(json);
|
|
669
691
|
},
|
|
670
692
|
async sendStreamingRequest(request) {
|
|
671
693
|
const body = buildRequestBody({ ...request, stream: true });
|
|
672
|
-
const
|
|
694
|
+
const timeout = request.service_tier === "flex" ? getFlexTimeout() : void 0;
|
|
695
|
+
const res = await makeRequest("/chat/completions", body, "POST", timeout);
|
|
673
696
|
if (!res.body) {
|
|
674
697
|
throw new AnyModelError(502, "No response body for streaming request", {
|
|
675
698
|
provider_name: "openai"
|
|
@@ -716,7 +739,7 @@ var FALLBACK_MODELS = [
|
|
|
716
739
|
];
|
|
717
740
|
function createAnthropicAdapter(apiKey) {
|
|
718
741
|
async function makeRequest(path2, body, stream = false) {
|
|
719
|
-
const res = await
|
|
742
|
+
const res = await fetchWithTimeout(`${ANTHROPIC_API_BASE}${path2}`, {
|
|
720
743
|
method: "POST",
|
|
721
744
|
headers: {
|
|
722
745
|
"Content-Type": "application/json",
|
|
@@ -973,7 +996,7 @@ ${body.system}` : jsonInstruction;
|
|
|
973
996
|
},
|
|
974
997
|
async listModels() {
|
|
975
998
|
try {
|
|
976
|
-
const res = await
|
|
999
|
+
const res = await fetchWithTimeout(`${ANTHROPIC_API_BASE}/models`, {
|
|
977
1000
|
method: "GET",
|
|
978
1001
|
headers: {
|
|
979
1002
|
"x-api-key": apiKey,
|
|
@@ -1258,7 +1281,7 @@ function createGoogleAdapter(apiKey) {
|
|
|
1258
1281
|
},
|
|
1259
1282
|
async listModels() {
|
|
1260
1283
|
try {
|
|
1261
|
-
const res = await
|
|
1284
|
+
const res = await fetchWithTimeout(`${GEMINI_API_BASE}/models?key=${apiKey}`);
|
|
1262
1285
|
if (!res.ok) return FALLBACK_MODELS2;
|
|
1263
1286
|
const data = await res.json();
|
|
1264
1287
|
const models = data.models || [];
|
|
@@ -1293,12 +1316,12 @@ function createGoogleAdapter(apiKey) {
|
|
|
1293
1316
|
return SUPPORTED_PARAMS3.has(param);
|
|
1294
1317
|
},
|
|
1295
1318
|
supportsBatch() {
|
|
1296
|
-
return
|
|
1319
|
+
return true;
|
|
1297
1320
|
},
|
|
1298
1321
|
async sendRequest(request) {
|
|
1299
1322
|
const body = translateRequest(request);
|
|
1300
1323
|
const url = getModelEndpoint(request.model, false);
|
|
1301
|
-
const res = await
|
|
1324
|
+
const res = await fetchWithTimeout(url, {
|
|
1302
1325
|
method: "POST",
|
|
1303
1326
|
headers: { "Content-Type": "application/json" },
|
|
1304
1327
|
body: JSON.stringify(body)
|
|
@@ -1321,7 +1344,7 @@ function createGoogleAdapter(apiKey) {
|
|
|
1321
1344
|
async sendStreamingRequest(request) {
|
|
1322
1345
|
const body = translateRequest(request);
|
|
1323
1346
|
const url = getModelEndpoint(request.model, true);
|
|
1324
|
-
const res = await
|
|
1347
|
+
const res = await fetchWithTimeout(url, {
|
|
1325
1348
|
method: "POST",
|
|
1326
1349
|
headers: { "Content-Type": "application/json" },
|
|
1327
1350
|
body: JSON.stringify(body)
|
|
@@ -1371,7 +1394,7 @@ var MODELS = [
|
|
|
1371
1394
|
];
|
|
1372
1395
|
function createPerplexityAdapter(apiKey) {
|
|
1373
1396
|
async function makeRequest(path2, body, method = "POST") {
|
|
1374
|
-
const res = await
|
|
1397
|
+
const res = await fetchWithTimeout(`${PERPLEXITY_API_BASE}${path2}`, {
|
|
1375
1398
|
method,
|
|
1376
1399
|
headers: {
|
|
1377
1400
|
"Content-Type": "application/json",
|
|
@@ -2243,6 +2266,51 @@ var BatchManager = class {
|
|
|
2243
2266
|
}
|
|
2244
2267
|
};
|
|
2245
2268
|
|
|
2269
|
+
// src/utils/token-estimate.ts
|
|
2270
|
+
var CHARS_PER_TOKEN2 = 4;
|
|
2271
|
+
var MODEL_LIMITS = [
|
|
2272
|
+
// OpenAI
|
|
2273
|
+
{ pattern: "gpt-4o-mini", limit: { contextLength: 128e3, maxCompletionTokens: 16384 } },
|
|
2274
|
+
{ pattern: "gpt-4o", limit: { contextLength: 128e3, maxCompletionTokens: 16384 } },
|
|
2275
|
+
{ pattern: "gpt-4-turbo", limit: { contextLength: 128e3, maxCompletionTokens: 4096 } },
|
|
2276
|
+
{ pattern: "gpt-3.5-turbo", limit: { contextLength: 16385, maxCompletionTokens: 4096 } },
|
|
2277
|
+
{ pattern: "o1", limit: { contextLength: 2e5, maxCompletionTokens: 1e5 } },
|
|
2278
|
+
{ pattern: "o3", limit: { contextLength: 2e5, maxCompletionTokens: 1e5 } },
|
|
2279
|
+
{ pattern: "o4-mini", limit: { contextLength: 2e5, maxCompletionTokens: 1e5 } },
|
|
2280
|
+
// Anthropic
|
|
2281
|
+
{ pattern: "claude-opus-4", limit: { contextLength: 2e5, maxCompletionTokens: 32768 } },
|
|
2282
|
+
{ pattern: "claude-sonnet-4", limit: { contextLength: 2e5, maxCompletionTokens: 16384 } },
|
|
2283
|
+
{ pattern: "claude-haiku-4", limit: { contextLength: 2e5, maxCompletionTokens: 8192 } },
|
|
2284
|
+
{ pattern: "claude-3.5-sonnet", limit: { contextLength: 2e5, maxCompletionTokens: 8192 } },
|
|
2285
|
+
{ pattern: "claude-3-opus", limit: { contextLength: 2e5, maxCompletionTokens: 4096 } },
|
|
2286
|
+
// Google
|
|
2287
|
+
{ pattern: "gemini-2.5-pro", limit: { contextLength: 1048576, maxCompletionTokens: 65536 } },
|
|
2288
|
+
{ pattern: "gemini-2.5-flash", limit: { contextLength: 1048576, maxCompletionTokens: 65536 } },
|
|
2289
|
+
{ pattern: "gemini-2.0-flash", limit: { contextLength: 1048576, maxCompletionTokens: 65536 } },
|
|
2290
|
+
{ pattern: "gemini-1.5-pro", limit: { contextLength: 2097152, maxCompletionTokens: 8192 } },
|
|
2291
|
+
{ pattern: "gemini-1.5-flash", limit: { contextLength: 1048576, maxCompletionTokens: 8192 } }
|
|
2292
|
+
];
|
|
2293
|
+
var DEFAULT_LIMIT = { contextLength: 128e3, maxCompletionTokens: 4096 };
|
|
2294
|
+
function getModelLimits(model) {
|
|
2295
|
+
const bare = model.includes("/") ? model.slice(model.indexOf("/") + 1) : model;
|
|
2296
|
+
for (const entry of MODEL_LIMITS) {
|
|
2297
|
+
if (bare.startsWith(entry.pattern) || bare.includes(entry.pattern)) {
|
|
2298
|
+
return entry.limit;
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
return DEFAULT_LIMIT;
|
|
2302
|
+
}
|
|
2303
|
+
function resolveMaxTokens(model, messages, userMaxTokens) {
|
|
2304
|
+
if (userMaxTokens !== void 0) return userMaxTokens;
|
|
2305
|
+
const inputChars = JSON.stringify(messages).length;
|
|
2306
|
+
const estimatedInput = Math.ceil(inputChars / CHARS_PER_TOKEN2);
|
|
2307
|
+
const estimatedWithMargin = Math.ceil(estimatedInput * 1.05);
|
|
2308
|
+
const limits = getModelLimits(model);
|
|
2309
|
+
const available = limits.contextLength - estimatedWithMargin;
|
|
2310
|
+
const result = Math.min(limits.maxCompletionTokens, available);
|
|
2311
|
+
return Math.max(1, result);
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2246
2314
|
// src/providers/openai-batch.ts
|
|
2247
2315
|
var OPENAI_API_BASE2 = "https://api.openai.com/v1";
|
|
2248
2316
|
function createOpenAIBatchAdapter(apiKey) {
|
|
@@ -2257,7 +2325,7 @@ function createOpenAIBatchAdapter(apiKey) {
|
|
|
2257
2325
|
headers["Content-Type"] = "application/json";
|
|
2258
2326
|
fetchBody = JSON.stringify(options.body);
|
|
2259
2327
|
}
|
|
2260
|
-
const res = await
|
|
2328
|
+
const res = await fetchWithTimeout(`${OPENAI_API_BASE2}${path2}`, {
|
|
2261
2329
|
method: options.method || "GET",
|
|
2262
2330
|
headers,
|
|
2263
2331
|
body: fetchBody
|
|
@@ -2283,7 +2351,7 @@ function createOpenAIBatchAdapter(apiKey) {
|
|
|
2283
2351
|
model,
|
|
2284
2352
|
messages: req.messages
|
|
2285
2353
|
};
|
|
2286
|
-
|
|
2354
|
+
body.max_tokens = req.max_tokens !== void 0 ? req.max_tokens : resolveMaxTokens(model, req.messages);
|
|
2287
2355
|
if (req.temperature !== void 0) body.temperature = req.temperature;
|
|
2288
2356
|
if (req.top_p !== void 0) body.top_p = req.top_p;
|
|
2289
2357
|
if (req.stop !== void 0) body.stop = req.stop;
|
|
@@ -2442,7 +2510,7 @@ function createAnthropicBatchAdapter(apiKey) {
|
|
|
2442
2510
|
"anthropic-version": ANTHROPIC_VERSION2,
|
|
2443
2511
|
"Content-Type": "application/json"
|
|
2444
2512
|
};
|
|
2445
|
-
const res = await
|
|
2513
|
+
const res = await fetchWithTimeout(`${ANTHROPIC_API_BASE2}${path2}`, {
|
|
2446
2514
|
method: options.method || "GET",
|
|
2447
2515
|
headers,
|
|
2448
2516
|
body: options.body ? JSON.stringify(options.body) : void 0
|
|
@@ -2465,7 +2533,7 @@ function createAnthropicBatchAdapter(apiKey) {
|
|
|
2465
2533
|
function translateToAnthropicParams(model, req) {
|
|
2466
2534
|
const params = {
|
|
2467
2535
|
model,
|
|
2468
|
-
max_tokens: req.max_tokens || DEFAULT_MAX_TOKENS2
|
|
2536
|
+
max_tokens: resolveMaxTokens(model, req.messages, req.max_tokens || DEFAULT_MAX_TOKENS2)
|
|
2469
2537
|
};
|
|
2470
2538
|
const systemMessages = req.messages.filter((m) => m.role === "system");
|
|
2471
2539
|
const nonSystemMessages = req.messages.filter((m) => m.role !== "system");
|
|
@@ -2639,6 +2707,284 @@ ${params.system}` : jsonInstruction;
|
|
|
2639
2707
|
};
|
|
2640
2708
|
}
|
|
2641
2709
|
|
|
2710
|
+
// src/providers/google-batch.ts
|
|
2711
|
+
var GEMINI_API_BASE2 = "https://generativelanguage.googleapis.com/v1beta";
|
|
2712
|
+
function createGoogleBatchAdapter(apiKey) {
|
|
2713
|
+
async function apiRequest(path2, options = {}) {
|
|
2714
|
+
const headers = {
|
|
2715
|
+
"Content-Type": "application/json",
|
|
2716
|
+
"x-goog-api-key": apiKey
|
|
2717
|
+
};
|
|
2718
|
+
const res = await fetchWithTimeout(`${GEMINI_API_BASE2}${path2}`, {
|
|
2719
|
+
method: options.method || "GET",
|
|
2720
|
+
headers,
|
|
2721
|
+
body: options.body ? JSON.stringify(options.body) : void 0
|
|
2722
|
+
});
|
|
2723
|
+
if (!res.ok) {
|
|
2724
|
+
let errorBody;
|
|
2725
|
+
try {
|
|
2726
|
+
errorBody = await res.json();
|
|
2727
|
+
} catch {
|
|
2728
|
+
errorBody = { message: res.statusText };
|
|
2729
|
+
}
|
|
2730
|
+
const msg = errorBody?.error?.message || errorBody?.message || res.statusText;
|
|
2731
|
+
throw new AnyModelError(res.status >= 500 ? 502 : res.status, msg, {
|
|
2732
|
+
provider_name: "google",
|
|
2733
|
+
raw: errorBody
|
|
2734
|
+
});
|
|
2735
|
+
}
|
|
2736
|
+
return res;
|
|
2737
|
+
}
|
|
2738
|
+
function translateRequestToGemini(model, req) {
|
|
2739
|
+
const body = {};
|
|
2740
|
+
const systemMessages = req.messages.filter((m) => m.role === "system");
|
|
2741
|
+
const nonSystemMessages = req.messages.filter((m) => m.role !== "system");
|
|
2742
|
+
if (systemMessages.length > 0) {
|
|
2743
|
+
body.systemInstruction = {
|
|
2744
|
+
parts: [{ text: systemMessages.map((m) => typeof m.content === "string" ? m.content : "").join("\n") }]
|
|
2745
|
+
};
|
|
2746
|
+
}
|
|
2747
|
+
body.contents = nonSystemMessages.map((m) => ({
|
|
2748
|
+
role: m.role === "assistant" ? "model" : "user",
|
|
2749
|
+
parts: typeof m.content === "string" ? [{ text: m.content }] : Array.isArray(m.content) ? m.content.map((p) => p.type === "text" ? { text: p.text } : { text: "" }) : [{ text: "" }]
|
|
2750
|
+
}));
|
|
2751
|
+
const generationConfig = {};
|
|
2752
|
+
if (req.temperature !== void 0) generationConfig.temperature = req.temperature;
|
|
2753
|
+
generationConfig.maxOutputTokens = req.max_tokens !== void 0 ? req.max_tokens : resolveMaxTokens(model, req.messages);
|
|
2754
|
+
if (req.top_p !== void 0) generationConfig.topP = req.top_p;
|
|
2755
|
+
if (req.top_k !== void 0) generationConfig.topK = req.top_k;
|
|
2756
|
+
if (req.stop !== void 0) {
|
|
2757
|
+
generationConfig.stopSequences = Array.isArray(req.stop) ? req.stop : [req.stop];
|
|
2758
|
+
}
|
|
2759
|
+
if (req.response_format) {
|
|
2760
|
+
if (req.response_format.type === "json_object") {
|
|
2761
|
+
generationConfig.responseMimeType = "application/json";
|
|
2762
|
+
} else if (req.response_format.type === "json_schema") {
|
|
2763
|
+
generationConfig.responseMimeType = "application/json";
|
|
2764
|
+
generationConfig.responseSchema = req.response_format.json_schema?.schema;
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
if (Object.keys(generationConfig).length > 0) {
|
|
2768
|
+
body.generationConfig = generationConfig;
|
|
2769
|
+
}
|
|
2770
|
+
if (req.tools && req.tools.length > 0) {
|
|
2771
|
+
body.tools = [{
|
|
2772
|
+
functionDeclarations: req.tools.map((t) => ({
|
|
2773
|
+
name: t.function.name,
|
|
2774
|
+
description: t.function.description || "",
|
|
2775
|
+
parameters: t.function.parameters || {}
|
|
2776
|
+
}))
|
|
2777
|
+
}];
|
|
2778
|
+
if (req.tool_choice) {
|
|
2779
|
+
if (req.tool_choice === "auto") {
|
|
2780
|
+
body.toolConfig = { functionCallingConfig: { mode: "AUTO" } };
|
|
2781
|
+
} else if (req.tool_choice === "required") {
|
|
2782
|
+
body.toolConfig = { functionCallingConfig: { mode: "ANY" } };
|
|
2783
|
+
} else if (req.tool_choice === "none") {
|
|
2784
|
+
body.toolConfig = { functionCallingConfig: { mode: "NONE" } };
|
|
2785
|
+
} else if (typeof req.tool_choice === "object") {
|
|
2786
|
+
body.toolConfig = {
|
|
2787
|
+
functionCallingConfig: {
|
|
2788
|
+
mode: "ANY",
|
|
2789
|
+
allowedFunctionNames: [req.tool_choice.function.name]
|
|
2790
|
+
}
|
|
2791
|
+
};
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
return body;
|
|
2796
|
+
}
|
|
2797
|
+
function mapFinishReason(reason) {
|
|
2798
|
+
switch (reason) {
|
|
2799
|
+
case "STOP":
|
|
2800
|
+
return "stop";
|
|
2801
|
+
case "MAX_TOKENS":
|
|
2802
|
+
return "length";
|
|
2803
|
+
case "SAFETY":
|
|
2804
|
+
return "content_filter";
|
|
2805
|
+
case "RECITATION":
|
|
2806
|
+
return "content_filter";
|
|
2807
|
+
default:
|
|
2808
|
+
return "stop";
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
function translateGeminiResponse(response, model) {
|
|
2812
|
+
const candidate = response.candidates?.[0];
|
|
2813
|
+
let content = "";
|
|
2814
|
+
const toolCalls = [];
|
|
2815
|
+
for (const part of candidate?.content?.parts || []) {
|
|
2816
|
+
if (part.text) {
|
|
2817
|
+
content += part.text;
|
|
2818
|
+
} else if (part.functionCall) {
|
|
2819
|
+
toolCalls.push({
|
|
2820
|
+
id: generateId("call"),
|
|
2821
|
+
type: "function",
|
|
2822
|
+
function: {
|
|
2823
|
+
name: part.functionCall.name,
|
|
2824
|
+
arguments: JSON.stringify(part.functionCall.args || {})
|
|
2825
|
+
}
|
|
2826
|
+
});
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2829
|
+
const message = { role: "assistant", content };
|
|
2830
|
+
if (toolCalls.length > 0) {
|
|
2831
|
+
message.tool_calls = toolCalls;
|
|
2832
|
+
}
|
|
2833
|
+
const finishReason = toolCalls.length > 0 ? "tool_calls" : mapFinishReason(candidate?.finishReason || "STOP");
|
|
2834
|
+
return {
|
|
2835
|
+
id: generateId(),
|
|
2836
|
+
object: "chat.completion",
|
|
2837
|
+
created: Math.floor(Date.now() / 1e3),
|
|
2838
|
+
model: `google/${model}`,
|
|
2839
|
+
choices: [{ index: 0, message, finish_reason: finishReason }],
|
|
2840
|
+
usage: {
|
|
2841
|
+
prompt_tokens: response.usageMetadata?.promptTokenCount || 0,
|
|
2842
|
+
completion_tokens: response.usageMetadata?.candidatesTokenCount || 0,
|
|
2843
|
+
total_tokens: response.usageMetadata?.totalTokenCount || 0
|
|
2844
|
+
}
|
|
2845
|
+
};
|
|
2846
|
+
}
|
|
2847
|
+
function mapBatchState(state) {
|
|
2848
|
+
switch (state) {
|
|
2849
|
+
case "JOB_STATE_PENDING":
|
|
2850
|
+
return "pending";
|
|
2851
|
+
case "JOB_STATE_RUNNING":
|
|
2852
|
+
return "processing";
|
|
2853
|
+
case "JOB_STATE_SUCCEEDED":
|
|
2854
|
+
return "completed";
|
|
2855
|
+
case "JOB_STATE_FAILED":
|
|
2856
|
+
return "failed";
|
|
2857
|
+
case "JOB_STATE_CANCELLED":
|
|
2858
|
+
return "cancelled";
|
|
2859
|
+
case "JOB_STATE_EXPIRED":
|
|
2860
|
+
return "failed";
|
|
2861
|
+
default:
|
|
2862
|
+
return "pending";
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
return {
|
|
2866
|
+
async createBatch(model, requests, _options) {
|
|
2867
|
+
const batchRequests = requests.map((req) => ({
|
|
2868
|
+
request: translateRequestToGemini(model, req),
|
|
2869
|
+
metadata: { key: req.custom_id }
|
|
2870
|
+
}));
|
|
2871
|
+
const res = await apiRequest(`/models/${model}:batchGenerateContent`, {
|
|
2872
|
+
method: "POST",
|
|
2873
|
+
body: {
|
|
2874
|
+
batch: {
|
|
2875
|
+
display_name: `anymodel-batch-${Date.now()}`,
|
|
2876
|
+
input_config: {
|
|
2877
|
+
requests: {
|
|
2878
|
+
requests: batchRequests
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
});
|
|
2884
|
+
const data = await res.json();
|
|
2885
|
+
const batchName = data.name || data.batch?.name;
|
|
2886
|
+
if (!batchName) {
|
|
2887
|
+
throw new AnyModelError(502, "No batch name in Google response", {
|
|
2888
|
+
provider_name: "google",
|
|
2889
|
+
raw: data
|
|
2890
|
+
});
|
|
2891
|
+
}
|
|
2892
|
+
return {
|
|
2893
|
+
providerBatchId: batchName,
|
|
2894
|
+
metadata: {
|
|
2895
|
+
model,
|
|
2896
|
+
total_requests: requests.length
|
|
2897
|
+
}
|
|
2898
|
+
};
|
|
2899
|
+
},
|
|
2900
|
+
async pollBatch(providerBatchId) {
|
|
2901
|
+
const res = await apiRequest(`/${providerBatchId}`);
|
|
2902
|
+
const data = await res.json();
|
|
2903
|
+
const state = data.state || "JOB_STATE_PENDING";
|
|
2904
|
+
const status = mapBatchState(state);
|
|
2905
|
+
const totalCount = data.totalCount || data.metadata?.total_requests || 0;
|
|
2906
|
+
const successCount = data.succeededCount || 0;
|
|
2907
|
+
const failedCount = data.failedCount || 0;
|
|
2908
|
+
return {
|
|
2909
|
+
status,
|
|
2910
|
+
total: totalCount || successCount + failedCount,
|
|
2911
|
+
completed: successCount,
|
|
2912
|
+
failed: failedCount
|
|
2913
|
+
};
|
|
2914
|
+
},
|
|
2915
|
+
async getBatchResults(providerBatchId) {
|
|
2916
|
+
const batchRes = await apiRequest(`/${providerBatchId}`);
|
|
2917
|
+
const batchData = await batchRes.json();
|
|
2918
|
+
const results = [];
|
|
2919
|
+
const model = batchData.metadata?.model || "unknown";
|
|
2920
|
+
if (batchData.response?.inlinedResponses) {
|
|
2921
|
+
for (const item of batchData.response.inlinedResponses) {
|
|
2922
|
+
const customId = item.metadata?.key || `request-${results.length}`;
|
|
2923
|
+
if (item.response) {
|
|
2924
|
+
results.push({
|
|
2925
|
+
custom_id: customId,
|
|
2926
|
+
status: "success",
|
|
2927
|
+
response: translateGeminiResponse(item.response, model),
|
|
2928
|
+
error: null
|
|
2929
|
+
});
|
|
2930
|
+
} else if (item.error) {
|
|
2931
|
+
results.push({
|
|
2932
|
+
custom_id: customId,
|
|
2933
|
+
status: "error",
|
|
2934
|
+
response: null,
|
|
2935
|
+
error: {
|
|
2936
|
+
code: item.error.code || 500,
|
|
2937
|
+
message: item.error.message || "Batch item failed"
|
|
2938
|
+
}
|
|
2939
|
+
});
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
return results;
|
|
2943
|
+
}
|
|
2944
|
+
const responsesFile = batchData.response?.responsesFileName || batchData.outputConfig?.file_name;
|
|
2945
|
+
if (responsesFile) {
|
|
2946
|
+
const downloadUrl = `${GEMINI_API_BASE2}/${responsesFile}:download?alt=media`;
|
|
2947
|
+
const fileRes = await fetchWithTimeout(downloadUrl, {
|
|
2948
|
+
headers: { "x-goog-api-key": apiKey }
|
|
2949
|
+
});
|
|
2950
|
+
if (!fileRes.ok) {
|
|
2951
|
+
throw new AnyModelError(502, "Failed to download batch results file", {
|
|
2952
|
+
provider_name: "google"
|
|
2953
|
+
});
|
|
2954
|
+
}
|
|
2955
|
+
const text = await fileRes.text();
|
|
2956
|
+
for (const line of text.trim().split("\n")) {
|
|
2957
|
+
if (!line) continue;
|
|
2958
|
+
const item = JSON.parse(line);
|
|
2959
|
+
const customId = item.key || item.metadata?.key || `request-${results.length}`;
|
|
2960
|
+
if (item.response) {
|
|
2961
|
+
results.push({
|
|
2962
|
+
custom_id: customId,
|
|
2963
|
+
status: "success",
|
|
2964
|
+
response: translateGeminiResponse(item.response, model),
|
|
2965
|
+
error: null
|
|
2966
|
+
});
|
|
2967
|
+
} else if (item.error) {
|
|
2968
|
+
results.push({
|
|
2969
|
+
custom_id: customId,
|
|
2970
|
+
status: "error",
|
|
2971
|
+
response: null,
|
|
2972
|
+
error: {
|
|
2973
|
+
code: item.error.code || 500,
|
|
2974
|
+
message: item.error.message || "Batch item failed"
|
|
2975
|
+
}
|
|
2976
|
+
});
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
return results;
|
|
2981
|
+
},
|
|
2982
|
+
async cancelBatch(providerBatchId) {
|
|
2983
|
+
await apiRequest(`/${providerBatchId}:cancel`, { method: "POST" });
|
|
2984
|
+
}
|
|
2985
|
+
};
|
|
2986
|
+
}
|
|
2987
|
+
|
|
2642
2988
|
// src/client.ts
|
|
2643
2989
|
var AnyModel = class {
|
|
2644
2990
|
registry;
|
|
@@ -2654,6 +3000,7 @@ var AnyModel = class {
|
|
|
2654
3000
|
constructor(config = {}) {
|
|
2655
3001
|
this.config = resolveConfig(config);
|
|
2656
3002
|
this.registry = new ProviderRegistry();
|
|
3003
|
+
setDefaultTimeout((this.config.defaults?.timeout ?? 120) * 1e3);
|
|
2657
3004
|
if (this.config.io) {
|
|
2658
3005
|
configureFsIO(this.config.io);
|
|
2659
3006
|
}
|
|
@@ -2774,6 +3121,10 @@ var AnyModel = class {
|
|
|
2774
3121
|
if (anthropicKey) {
|
|
2775
3122
|
this.batchManager.registerBatchAdapter("anthropic", createAnthropicBatchAdapter(anthropicKey));
|
|
2776
3123
|
}
|
|
3124
|
+
const googleKey = config.google?.apiKey || process.env.GOOGLE_API_KEY;
|
|
3125
|
+
if (googleKey) {
|
|
3126
|
+
this.batchManager.registerBatchAdapter("google", createGoogleBatchAdapter(googleKey));
|
|
3127
|
+
}
|
|
2777
3128
|
}
|
|
2778
3129
|
applyDefaults(request) {
|
|
2779
3130
|
const defaults = this.config.defaults;
|