190proof 1.0.105 → 1.0.107
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 +1 -1
- package/dist/index.js +116 -107
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +114 -106
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 190proof
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
An opinionated unified interface for interacting with multiple AI providers including **OpenAI**, **Anthropic**, **Google**, **Groq**, **OpenRouter**, and **AWS Bedrock**. This package provides a consistent API for making requests to different LLM providers while handling retries, streaming, and multimodal inputs.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
package/dist/index.js
CHANGED
|
@@ -28,8 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
30
|
// index.ts
|
|
31
|
-
var
|
|
32
|
-
__export(
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
33
|
ClaudeModel: () => ClaudeModel,
|
|
34
34
|
GPTModel: () => GPTModel,
|
|
35
35
|
GeminiModel: () => GeminiModel,
|
|
@@ -38,7 +38,7 @@ __export(proof_exports, {
|
|
|
38
38
|
callWithRetries: () => callWithRetries,
|
|
39
39
|
parseModelString: () => parseModelString
|
|
40
40
|
});
|
|
41
|
-
module.exports = __toCommonJS(
|
|
41
|
+
module.exports = __toCommonJS(index_exports);
|
|
42
42
|
|
|
43
43
|
// interfaces.ts
|
|
44
44
|
var ClaudeModel = /* @__PURE__ */ ((ClaudeModel2) => {
|
|
@@ -146,6 +146,19 @@ function anySignal(signals) {
|
|
|
146
146
|
signals
|
|
147
147
|
);
|
|
148
148
|
}
|
|
149
|
+
async function withRequestDeadline(apiName, requestTimeoutMs, signal, fn) {
|
|
150
|
+
const deadline = AbortSignal.timeout(requestTimeoutMs);
|
|
151
|
+
try {
|
|
152
|
+
return await fn(signal ? anySignal([signal, deadline]) : deadline);
|
|
153
|
+
} catch (error2) {
|
|
154
|
+
if (deadline.aborted && !(signal == null ? void 0 : signal.aborted)) {
|
|
155
|
+
throw new Error(
|
|
156
|
+
`${apiName} request exceeded hard deadline of ${requestTimeoutMs}ms`
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
throw error2;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
149
162
|
async function withRetries(identifier, apiName, fn, options = {}) {
|
|
150
163
|
var _a, _b, _c, _d, _e;
|
|
151
164
|
const { retries = 5, baseDelayMs = 125, onError } = options;
|
|
@@ -156,8 +169,7 @@ async function withRetries(identifier, apiName, fn, options = {}) {
|
|
|
156
169
|
return await fn();
|
|
157
170
|
} catch (error3) {
|
|
158
171
|
lastError = error3;
|
|
159
|
-
if ((_a = options.signal) == null ? void 0 : _a.aborted)
|
|
160
|
-
throw error3;
|
|
172
|
+
if ((_a = options.signal) == null ? void 0 : _a.aborted) throw error3;
|
|
161
173
|
if (onError) {
|
|
162
174
|
onError(error3, attempt);
|
|
163
175
|
} else {
|
|
@@ -181,8 +193,7 @@ function parseStreamedResponse(identifier, paragraph, toolCallAccumulators, allo
|
|
|
181
193
|
const functionCalls = [];
|
|
182
194
|
for (let i = 0; i < toolCallAccumulators.length; i++) {
|
|
183
195
|
const acc = toolCallAccumulators[i];
|
|
184
|
-
if (!acc.name || !acc.arguments)
|
|
185
|
-
continue;
|
|
196
|
+
if (!acc.name || !acc.arguments) continue;
|
|
186
197
|
if (allowedFunctionNames && !allowedFunctionNames.has(acc.name)) {
|
|
187
198
|
throw new Error(
|
|
188
199
|
`Stream error: received function call with unknown name: ${acc.name}`
|
|
@@ -321,8 +332,7 @@ function buildOpenAIRequestConfig(identifier, model, config) {
|
|
|
321
332
|
};
|
|
322
333
|
}
|
|
323
334
|
function filterOpenAICompatReasoningDetails(details) {
|
|
324
|
-
if (!Array.isArray(details))
|
|
325
|
-
return details || void 0;
|
|
335
|
+
if (!Array.isArray(details)) return details || void 0;
|
|
326
336
|
const blocks = details.filter(
|
|
327
337
|
(block) => typeof (block == null ? void 0 : block.type) === "string" && block.type.startsWith("reasoning.")
|
|
328
338
|
);
|
|
@@ -393,13 +403,11 @@ async function prepareOpenAIPayload(identifier, payload) {
|
|
|
393
403
|
};
|
|
394
404
|
});
|
|
395
405
|
}
|
|
396
|
-
if (message.reasoning)
|
|
397
|
-
outMessage.reasoning = message.reasoning;
|
|
406
|
+
if (message.reasoning) outMessage.reasoning = message.reasoning;
|
|
398
407
|
const reasoningDetails = filterOpenAICompatReasoningDetails(
|
|
399
408
|
message.reasoningDetails
|
|
400
409
|
);
|
|
401
|
-
if (reasoningDetails)
|
|
402
|
-
outMessage.reasoning_details = reasoningDetails;
|
|
410
|
+
if (reasoningDetails) outMessage.reasoning_details = reasoningDetails;
|
|
403
411
|
preparedPayload.messages.push(outMessage);
|
|
404
412
|
}
|
|
405
413
|
return preparedPayload;
|
|
@@ -461,8 +469,7 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
|
|
|
461
469
|
}
|
|
462
470
|
const jsonStrings = chunk.split(/^data: /gm);
|
|
463
471
|
for (const jsonString of jsonStrings) {
|
|
464
|
-
if (!jsonString)
|
|
465
|
-
continue;
|
|
472
|
+
if (!jsonString) continue;
|
|
466
473
|
if (jsonString.includes("[DONE]")) {
|
|
467
474
|
clearTimeout(overallTimeout);
|
|
468
475
|
return parseStreamedResponse(
|
|
@@ -500,8 +507,7 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
|
|
|
500
507
|
while (toolCallAccumulators.length <= idx) {
|
|
501
508
|
toolCallAccumulators.push({ name: "", arguments: "" });
|
|
502
509
|
}
|
|
503
|
-
if (toolCall.id)
|
|
504
|
-
toolCallAccumulators[idx].id = toolCall.id;
|
|
510
|
+
if (toolCall.id) toolCallAccumulators[idx].id = toolCall.id;
|
|
505
511
|
if ((_e = toolCall.function) == null ? void 0 : _e.name)
|
|
506
512
|
toolCallAccumulators[idx].name += toolCall.function.name;
|
|
507
513
|
if ((_f = toolCall.function) == null ? void 0 : _f.arguments)
|
|
@@ -509,11 +515,9 @@ async function callOpenAIStream(id, openAiPayload, openAiConfig, chunkTimeoutMs,
|
|
|
509
515
|
}
|
|
510
516
|
}
|
|
511
517
|
const text = (_h = (_g = json.choices[0]) == null ? void 0 : _g.delta) == null ? void 0 : _h.content;
|
|
512
|
-
if (text)
|
|
513
|
-
paragraph += text;
|
|
518
|
+
if (text) paragraph += text;
|
|
514
519
|
const reasoningDelta = (_j = (_i = json.choices[0]) == null ? void 0 : _i.delta) == null ? void 0 : _j.reasoning;
|
|
515
|
-
if (reasoningDelta)
|
|
516
|
-
reasoning += reasoningDelta;
|
|
520
|
+
if (reasoningDelta) reasoning += reasoningDelta;
|
|
517
521
|
}
|
|
518
522
|
}
|
|
519
523
|
}
|
|
@@ -658,8 +662,7 @@ function jigAnthropicMessages(messages) {
|
|
|
658
662
|
];
|
|
659
663
|
}
|
|
660
664
|
jiggedMessages = jiggedMessages.reduce((acc, message) => {
|
|
661
|
-
if (acc.length === 0)
|
|
662
|
-
return [message];
|
|
665
|
+
if (acc.length === 0) return [message];
|
|
663
666
|
const lastMessage = acc[acc.length - 1];
|
|
664
667
|
if (lastMessage.role === message.role) {
|
|
665
668
|
const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
|
|
@@ -796,28 +799,33 @@ async function callAnthropic(id, payload, config, requestTimeoutMs = 12e4, signa
|
|
|
796
799
|
...tools.slice(0, -1),
|
|
797
800
|
{ ...tools[tools.length - 1], cache_control: { type: "ephemeral" } }
|
|
798
801
|
] : tools;
|
|
799
|
-
const response = await
|
|
800
|
-
"
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
"x-api-key": process.env.ANTHROPIC_API_KEY,
|
|
815
|
-
"anthropic-version": "2023-06-01",
|
|
816
|
-
"anthropic-beta": "tools-2024-04-04"
|
|
802
|
+
const response = await withRequestDeadline(
|
|
803
|
+
"Anthropic",
|
|
804
|
+
requestTimeoutMs,
|
|
805
|
+
signal,
|
|
806
|
+
(mergedSignal) => import_axios.default.post(
|
|
807
|
+
"https://api.anthropic.com/v1/messages",
|
|
808
|
+
{
|
|
809
|
+
model: payload.model,
|
|
810
|
+
messages: anthropicMessages,
|
|
811
|
+
tools: cachedTools,
|
|
812
|
+
// tool_choice requires tools in the request; drop it otherwise.
|
|
813
|
+
tool_choice: (cachedTools == null ? void 0 : cachedTools.length) ? payload.tool_choice : void 0,
|
|
814
|
+
temperature: payload.temperature,
|
|
815
|
+
system: payload.system,
|
|
816
|
+
max_tokens: 4096
|
|
817
817
|
},
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
818
|
+
{
|
|
819
|
+
headers: {
|
|
820
|
+
"content-type": "application/json",
|
|
821
|
+
"x-api-key": process.env.ANTHROPIC_API_KEY,
|
|
822
|
+
"anthropic-version": "2023-06-01",
|
|
823
|
+
"anthropic-beta": "tools-2024-04-04"
|
|
824
|
+
},
|
|
825
|
+
timeout: requestTimeoutMs,
|
|
826
|
+
signal: mergedSignal
|
|
827
|
+
}
|
|
828
|
+
)
|
|
821
829
|
);
|
|
822
830
|
data = response.data;
|
|
823
831
|
}
|
|
@@ -908,8 +916,7 @@ function jigGoogleMessages(messages) {
|
|
|
908
916
|
];
|
|
909
917
|
}
|
|
910
918
|
jiggedMessages = jiggedMessages.reduce((acc, message) => {
|
|
911
|
-
if (acc.length === 0)
|
|
912
|
-
return [message];
|
|
919
|
+
if (acc.length === 0) return [message];
|
|
913
920
|
const lastMessage = acc[acc.length - 1];
|
|
914
921
|
if (lastMessage.role === message.role) {
|
|
915
922
|
lastMessage.parts = [...lastMessage.parts, ...message.parts];
|
|
@@ -947,8 +954,7 @@ async function prepareGoogleAIPayload(_identifier, payload) {
|
|
|
947
954
|
const toolNameById = /* @__PURE__ */ new Map();
|
|
948
955
|
for (const m of payload.messages) {
|
|
949
956
|
for (const fc of m.functionCalls || []) {
|
|
950
|
-
if (fc.id)
|
|
951
|
-
toolNameById.set(fc.id, fc.name);
|
|
957
|
+
if (fc.id) toolNameById.set(fc.id, fc.name);
|
|
952
958
|
}
|
|
953
959
|
}
|
|
954
960
|
for (const message of payload.messages) {
|
|
@@ -1025,8 +1031,7 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
|
|
|
1025
1031
|
contents,
|
|
1026
1032
|
generationConfig: { responseModalities: ["TEXT"] }
|
|
1027
1033
|
};
|
|
1028
|
-
if (payload.tools)
|
|
1029
|
-
requestBody.tools = [payload.tools];
|
|
1034
|
+
if (payload.tools) requestBody.tools = [payload.tools];
|
|
1030
1035
|
if (payload.tools && payload.toolConfig) {
|
|
1031
1036
|
requestBody.toolConfig = payload.toolConfig;
|
|
1032
1037
|
}
|
|
@@ -1037,17 +1042,22 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
|
|
|
1037
1042
|
}
|
|
1038
1043
|
let response;
|
|
1039
1044
|
try {
|
|
1040
|
-
const httpResponse = await
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1045
|
+
const httpResponse = await withRequestDeadline(
|
|
1046
|
+
"Google AI",
|
|
1047
|
+
requestTimeoutMs,
|
|
1048
|
+
signal,
|
|
1049
|
+
(mergedSignal) => import_axios.default.post(
|
|
1050
|
+
`https://generativelanguage.googleapis.com/v1beta/models/${payload.model}:generateContent`,
|
|
1051
|
+
requestBody,
|
|
1052
|
+
{
|
|
1053
|
+
headers: {
|
|
1054
|
+
"content-type": "application/json",
|
|
1055
|
+
"x-goog-api-key": process.env.GEMINI_API_KEY
|
|
1056
|
+
},
|
|
1057
|
+
timeout: requestTimeoutMs,
|
|
1058
|
+
signal: mergedSignal
|
|
1059
|
+
}
|
|
1060
|
+
)
|
|
1051
1061
|
);
|
|
1052
1062
|
response = httpResponse.data;
|
|
1053
1063
|
} catch (err) {
|
|
@@ -1079,8 +1089,7 @@ async function callGoogleAI(id, payload, requestTimeoutMs = 12e4, signal) {
|
|
|
1079
1089
|
});
|
|
1080
1090
|
continue;
|
|
1081
1091
|
}
|
|
1082
|
-
if (part.text)
|
|
1083
|
-
text += part.text;
|
|
1092
|
+
if (part.text) text += part.text;
|
|
1084
1093
|
if ((_m = part.inlineData) == null ? void 0 : _m.data) {
|
|
1085
1094
|
files.push({ mimeType: "image/png", data: part.inlineData.data });
|
|
1086
1095
|
}
|
|
@@ -1157,21 +1166,15 @@ async function callGoogleAIWithRetries(id, payload, retries = 5, requestTimeoutM
|
|
|
1157
1166
|
finishReason: error2.finishReason,
|
|
1158
1167
|
modelVersion: error2.modelVersion
|
|
1159
1168
|
};
|
|
1160
|
-
if (error2.safetyRatings)
|
|
1161
|
-
|
|
1162
|
-
if (error2.usageMetadata)
|
|
1163
|
-
errorDetails.usageMetadata = error2.usageMetadata;
|
|
1169
|
+
if (error2.safetyRatings) errorDetails.safetyRatings = error2.safetyRatings;
|
|
1170
|
+
if (error2.usageMetadata) errorDetails.usageMetadata = error2.usageMetadata;
|
|
1164
1171
|
if (error2.promptFeedback)
|
|
1165
1172
|
errorDetails.promptFeedback = error2.promptFeedback;
|
|
1166
|
-
if (error2.status)
|
|
1167
|
-
|
|
1168
|
-
if (error2.
|
|
1169
|
-
errorDetails.errorCode = error2.code;
|
|
1170
|
-
if (error2.details)
|
|
1171
|
-
errorDetails.errorDetails = error2.details;
|
|
1173
|
+
if (error2.status) errorDetails.httpStatus = error2.status;
|
|
1174
|
+
if (error2.code) errorDetails.errorCode = error2.code;
|
|
1175
|
+
if (error2.details) errorDetails.errorDetails = error2.details;
|
|
1172
1176
|
const fileUris = payload.messages.flatMap((m) => m.parts).filter((p) => "fileData" in p).map((p) => p.fileData.fileUri);
|
|
1173
|
-
if (fileUris.length)
|
|
1174
|
-
errorDetails.fileUris = fileUris;
|
|
1177
|
+
if (fileUris.length) errorDetails.fileUris = fileUris;
|
|
1175
1178
|
logger_default.error(
|
|
1176
1179
|
id,
|
|
1177
1180
|
`Retry #${attempt} error: ${error2.message}`,
|
|
@@ -1251,16 +1254,13 @@ function prepareOpenAICompatMessages(messages) {
|
|
|
1251
1254
|
}
|
|
1252
1255
|
};
|
|
1253
1256
|
});
|
|
1254
|
-
if (!message.content)
|
|
1255
|
-
outMessage.content = null;
|
|
1257
|
+
if (!message.content) outMessage.content = null;
|
|
1256
1258
|
}
|
|
1257
|
-
if (message.reasoning)
|
|
1258
|
-
outMessage.reasoning = message.reasoning;
|
|
1259
|
+
if (message.reasoning) outMessage.reasoning = message.reasoning;
|
|
1259
1260
|
const reasoningDetails = filterOpenAICompatReasoningDetails(
|
|
1260
1261
|
message.reasoningDetails
|
|
1261
1262
|
);
|
|
1262
|
-
if (reasoningDetails)
|
|
1263
|
-
outMessage.reasoning_details = reasoningDetails;
|
|
1263
|
+
if (reasoningDetails) outMessage.reasoning_details = reasoningDetails;
|
|
1264
1264
|
out.push(outMessage);
|
|
1265
1265
|
}
|
|
1266
1266
|
return out;
|
|
@@ -1280,17 +1280,22 @@ function prepareGroqPayload(payload) {
|
|
|
1280
1280
|
}
|
|
1281
1281
|
async function callGroq(id, payload, requestTimeoutMs = 12e4, signal) {
|
|
1282
1282
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
1283
|
-
const response = await
|
|
1284
|
-
"
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1283
|
+
const response = await withRequestDeadline(
|
|
1284
|
+
"Groq",
|
|
1285
|
+
requestTimeoutMs,
|
|
1286
|
+
signal,
|
|
1287
|
+
(mergedSignal) => import_axios.default.post(
|
|
1288
|
+
"https://api.groq.com/openai/v1/chat/completions",
|
|
1289
|
+
payload,
|
|
1290
|
+
{
|
|
1291
|
+
headers: {
|
|
1292
|
+
"content-type": "application/json",
|
|
1293
|
+
Authorization: `Bearer ${process.env.GROQ_API_KEY}`
|
|
1294
|
+
},
|
|
1295
|
+
timeout: requestTimeoutMs,
|
|
1296
|
+
signal: mergedSignal
|
|
1297
|
+
}
|
|
1298
|
+
)
|
|
1294
1299
|
);
|
|
1295
1300
|
if (response.data.error) {
|
|
1296
1301
|
logger_default.error(id, "Groq error:", response.data.error);
|
|
@@ -1398,8 +1403,7 @@ function parseDsmlToolCalls(content) {
|
|
|
1398
1403
|
let last = -1;
|
|
1399
1404
|
let tag;
|
|
1400
1405
|
while ((tag = DSML_ANY_TAG_RE.exec(content)) !== null) {
|
|
1401
|
-
if (first === -1)
|
|
1402
|
-
first = tag.index;
|
|
1406
|
+
if (first === -1) first = tag.index;
|
|
1403
1407
|
last = tag.index + tag[0].length;
|
|
1404
1408
|
}
|
|
1405
1409
|
const remaining = first === -1 ? content : (content.slice(0, first) + content.slice(last)).trim();
|
|
@@ -1407,17 +1411,23 @@ function parseDsmlToolCalls(content) {
|
|
|
1407
1411
|
}
|
|
1408
1412
|
async function callOpenRouter(id, payload, requestTimeoutMs = 12e4, signal) {
|
|
1409
1413
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1410
|
-
const response = await
|
|
1411
|
-
"
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1414
|
+
const response = await withRequestDeadline(
|
|
1415
|
+
"OpenRouter",
|
|
1416
|
+
requestTimeoutMs,
|
|
1417
|
+
signal,
|
|
1418
|
+
(mergedSignal) => import_axios.default.post(
|
|
1419
|
+
// Override point for tests (deadline behavior needs a local server).
|
|
1420
|
+
`${process.env.OPENROUTER_BASE_URL || "https://openrouter.ai"}/api/v1/chat/completions`,
|
|
1421
|
+
payload,
|
|
1422
|
+
{
|
|
1423
|
+
headers: {
|
|
1424
|
+
"content-type": "application/json",
|
|
1425
|
+
Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`
|
|
1426
|
+
},
|
|
1427
|
+
timeout: requestTimeoutMs,
|
|
1428
|
+
signal: mergedSignal
|
|
1429
|
+
}
|
|
1430
|
+
)
|
|
1421
1431
|
);
|
|
1422
1432
|
if (response.data.error) {
|
|
1423
1433
|
logger_default.error(id, "OpenRouter error:", response.data.error);
|
|
@@ -1583,8 +1593,7 @@ async function callWithRetries(id, aiPayload, aiConfig, retries = 5, chunkTimeou
|
|
|
1583
1593
|
(_b = result.provider) != null ? _b : result.provider = provider;
|
|
1584
1594
|
return result;
|
|
1585
1595
|
} catch (error2) {
|
|
1586
|
-
if ((_c = aiPayload.signal) == null ? void 0 : _c.aborted)
|
|
1587
|
-
throw error2;
|
|
1596
|
+
if ((_c = aiPayload.signal) == null ? void 0 : _c.aborted) throw error2;
|
|
1588
1597
|
if (aiPayload.fallbackModel) {
|
|
1589
1598
|
logger_default.error(
|
|
1590
1599
|
id,
|