@umituz/web-ai 1.0.0 → 1.0.2
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/{ABTesting-DDqNhHtP.d.ts → AIErrors-B2ogd1PB.d.ts} +14 -1
- package/dist/{ABTesting-DWBtKTMQ.d.cts → AIErrors-C5EasV_c.d.cts} +14 -1
- package/dist/{ProviderConfig-a55tLhWT.d.cts → ProviderConfig-DIFa9nmG.d.cts} +10 -1
- package/dist/{ProviderConfig-a55tLhWT.d.ts → ProviderConfig-DIFa9nmG.d.ts} +10 -1
- package/dist/chat/index.cjs +114 -23
- package/dist/chat/index.cjs.map +1 -1
- package/dist/chat/index.d.cts +4 -4
- package/dist/chat/index.d.ts +4 -4
- package/dist/chat/index.js +114 -23
- package/dist/chat/index.js.map +1 -1
- package/dist/{chat.service-DBKq9I2c.d.cts → chat.service-CL1qtYxe.d.cts} +7 -7
- package/dist/{chat.service-RQn8UTXD.d.ts → chat.service-q05GnhEm.d.ts} +7 -7
- package/dist/content/index.cjs +506 -193
- package/dist/content/index.cjs.map +1 -1
- package/dist/content/index.d.cts +7 -8
- package/dist/content/index.d.ts +7 -8
- package/dist/content/index.js +506 -193
- package/dist/content/index.js.map +1 -1
- package/dist/core/index.cjs +122 -15
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +13 -31
- package/dist/core/index.d.ts +13 -31
- package/dist/core/index.js +119 -16
- package/dist/core/index.js.map +1 -1
- package/dist/{create-ai-BhNaz86i.d.ts → create-ai-9PW752z8.d.ts} +14 -21
- package/dist/{create-ai-DGZFBOA1.d.cts → create-ai-CXYKPK6G.d.cts} +14 -21
- package/dist/hooks/index.cjs +631 -179
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +33 -7
- package/dist/hooks/index.d.ts +33 -7
- package/dist/hooks/index.js +631 -180
- package/dist/hooks/index.js.map +1 -1
- package/dist/index-DIHz8_OJ.d.ts +48 -0
- package/dist/index-DKHNcMbl.d.cts +48 -0
- package/dist/index.cjs +666 -104
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +645 -105
- package/dist/index.js.map +1 -1
- package/dist/{provider.factory-COsnprLH.d.cts → provider.factory-BxsfK4WW.d.cts} +1 -1
- package/dist/{provider.factory-CpWFyjbw.d.ts → provider.factory-DfDfk0dK.d.ts} +1 -1
- package/dist/providers/index.cjs +973 -130
- package/dist/providers/index.cjs.map +1 -1
- package/dist/providers/index.d.cts +84 -18
- package/dist/providers/index.d.ts +84 -18
- package/dist/providers/index.js +956 -131
- package/dist/providers/index.js.map +1 -1
- package/dist/text-generation.service-BQO3Tvz2.d.cts +66 -0
- package/dist/text-generation.service-CcYQM6Ch.d.ts +66 -0
- package/dist/wizard/index.d.cts +1 -1
- package/dist/wizard/index.d.ts +1 -1
- package/package.json +9 -1
- package/dist/index-DjX9ZKuM.d.cts +0 -14
- package/dist/index-DxLvE588.d.ts +0 -14
package/dist/index.cjs
CHANGED
|
@@ -43,17 +43,80 @@ var USER_FRIENDLY_ERROR_MESSAGES = {
|
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
// src/core/errors/ai-error.ts
|
|
46
|
-
var
|
|
46
|
+
var KNOWN_ERROR_TYPES = new Set(Object.values(AIErrorType));
|
|
47
|
+
function mapCodeToType(code) {
|
|
48
|
+
switch (code) {
|
|
49
|
+
case "VALIDATION_ERROR":
|
|
50
|
+
case "CLIENT_ERROR":
|
|
51
|
+
return "CLIENT_ERROR" /* CLIENT_ERROR */;
|
|
52
|
+
case "INVALID_API_KEY":
|
|
53
|
+
return "INVALID_API_KEY" /* INVALID_API_KEY */;
|
|
54
|
+
case "MISSING_CONFIG":
|
|
55
|
+
case "PROVIDER_UNAVAILABLE":
|
|
56
|
+
return "MISSING_CONFIG" /* MISSING_CONFIG */;
|
|
57
|
+
case "PROVIDER_QUOTA_EXHAUSTED":
|
|
58
|
+
case "RATE_LIMIT_ERROR":
|
|
59
|
+
return "RATE_LIMIT_ERROR" /* RATE_LIMIT_ERROR */;
|
|
60
|
+
case "NETWORK_ERROR":
|
|
61
|
+
case "TIMEOUT":
|
|
62
|
+
return "NETWORK_ERROR" /* NETWORK_ERROR */;
|
|
63
|
+
case "ABORT_ERROR":
|
|
64
|
+
case "ABORTED":
|
|
65
|
+
return "ABORT_ERROR" /* ABORT_ERROR */;
|
|
66
|
+
case "SERVER_ERROR":
|
|
67
|
+
case "PROVIDER_ERROR":
|
|
68
|
+
case "NO_RESULT":
|
|
69
|
+
return "SERVER_ERROR" /* SERVER_ERROR */;
|
|
70
|
+
default:
|
|
71
|
+
return "UNKNOWN_ERROR" /* UNKNOWN_ERROR */;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function mapMessageToCode(message, fallback = "UNKNOWN") {
|
|
75
|
+
const lower = message.toLowerCase();
|
|
76
|
+
if (lower.includes("validation")) return "VALIDATION_ERROR";
|
|
77
|
+
if (lower.includes("quota")) return "PROVIDER_QUOTA_EXHAUSTED";
|
|
78
|
+
if (lower.includes("unavailable")) return "PROVIDER_UNAVAILABLE";
|
|
79
|
+
if (lower.includes("timeout") || lower.includes("aborted")) {
|
|
80
|
+
return lower.includes("aborted") ? "ABORTED" : "TIMEOUT";
|
|
81
|
+
}
|
|
82
|
+
if (lower.includes("parse") || lower.includes("json")) return "PARSE_ERROR";
|
|
83
|
+
if (lower.includes("no result")) return "NO_RESULT";
|
|
84
|
+
if (lower.includes("network") || lower.includes("fetch")) return "NETWORK_ERROR";
|
|
85
|
+
return fallback;
|
|
86
|
+
}
|
|
87
|
+
var AIError = class _AIError extends Error {
|
|
47
88
|
type;
|
|
89
|
+
code;
|
|
48
90
|
cause;
|
|
49
91
|
metadata;
|
|
50
|
-
constructor(
|
|
51
|
-
|
|
92
|
+
constructor(typeOrMessage, messageOrCode, cause, metadata = {}) {
|
|
93
|
+
let effectiveType;
|
|
94
|
+
let effectiveMessage;
|
|
95
|
+
let effectiveCode;
|
|
96
|
+
if (KNOWN_ERROR_TYPES.has(typeOrMessage)) {
|
|
97
|
+
effectiveType = typeOrMessage;
|
|
98
|
+
effectiveMessage = messageOrCode ?? "";
|
|
99
|
+
effectiveCode = effectiveType;
|
|
100
|
+
} else {
|
|
101
|
+
effectiveMessage = typeOrMessage;
|
|
102
|
+
effectiveCode = messageOrCode ?? "UNKNOWN";
|
|
103
|
+
effectiveType = mapCodeToType(effectiveCode);
|
|
104
|
+
}
|
|
105
|
+
super(effectiveMessage);
|
|
52
106
|
this.name = "AIError";
|
|
53
|
-
this.type =
|
|
107
|
+
this.type = effectiveType;
|
|
108
|
+
this.code = effectiveCode;
|
|
54
109
|
this.cause = cause;
|
|
55
110
|
this.metadata = metadata;
|
|
56
111
|
}
|
|
112
|
+
static from(error, fallbackCode = "UNKNOWN") {
|
|
113
|
+
if (error instanceof _AIError) return error;
|
|
114
|
+
if (error instanceof Error) {
|
|
115
|
+
const code = mapMessageToCode(error.message, fallbackCode);
|
|
116
|
+
return new _AIError(error.message, code, error);
|
|
117
|
+
}
|
|
118
|
+
return new _AIError(String(error), fallbackCode, error);
|
|
119
|
+
}
|
|
57
120
|
toString() {
|
|
58
121
|
const statusPart = typeof this.metadata.status === "number" ? ` (HTTP ${this.metadata.status})` : "";
|
|
59
122
|
return `${this.name} [${this.type}]: ${this.message}${statusPart}`;
|
|
@@ -62,12 +125,21 @@ var AIError = class extends Error {
|
|
|
62
125
|
return {
|
|
63
126
|
name: this.name,
|
|
64
127
|
type: this.type,
|
|
128
|
+
code: this.code,
|
|
65
129
|
message: this.message,
|
|
66
130
|
metadata: this.metadata
|
|
67
131
|
};
|
|
68
132
|
}
|
|
69
133
|
};
|
|
70
134
|
|
|
135
|
+
// src/core/errors/groq-error.ts
|
|
136
|
+
var GroqError = class extends AIError {
|
|
137
|
+
constructor(type, message, cause, metadata = {}) {
|
|
138
|
+
super(type, message, cause, metadata);
|
|
139
|
+
this.name = "GroqError";
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
71
143
|
// src/core/errors/error-classifier.ts
|
|
72
144
|
var DEFAULT_RETRYABLE_TYPES = /* @__PURE__ */ new Set([
|
|
73
145
|
"NETWORK_ERROR" /* NETWORK_ERROR */,
|
|
@@ -346,6 +418,8 @@ function calculateExponentialBackoff(params) {
|
|
|
346
418
|
// src/core/constants/identifier.constants.ts
|
|
347
419
|
var MESSAGE_ID_PREFIX = "msg-";
|
|
348
420
|
var CHAT_MESSAGE_ID_SUFFIX_LENGTH = 9;
|
|
421
|
+
var CACHE_KEY_TYPE_COMPLETION = "completion";
|
|
422
|
+
var CACHE_KEY_TYPE_CHAT = "chat";
|
|
349
423
|
var USER_ROLE = "user";
|
|
350
424
|
var ASSISTANT_ROLE = "assistant";
|
|
351
425
|
var QUEUE_PRIORITY_USER_REQUEST = 10;
|
|
@@ -750,15 +824,22 @@ function oneOfCatalog(catalog, value) {
|
|
|
750
824
|
// src/core/constants/protocol.constants.ts
|
|
751
825
|
var SSE_PREFIX = "data: ";
|
|
752
826
|
var SSE_DONE_MARKER = "[DONE]";
|
|
753
|
-
var JSON_CODE_BLOCK_PATTERN = /```json
|
|
827
|
+
var JSON_CODE_BLOCK_PATTERN = /```(?:json)?\s*\n?([\s\S]*?)\n?```/;
|
|
754
828
|
var JSON_OBJECT_PATTERN = /\{[\s\S]*\}/;
|
|
829
|
+
var JSON_ARRAY_PATTERN = /\[[\s\S]*\]/;
|
|
755
830
|
|
|
756
831
|
// src/core/parsers/sse-lines.ts
|
|
757
832
|
function isSseDataLine(line) {
|
|
758
|
-
return line.startsWith(SSE_PREFIX);
|
|
833
|
+
return line.startsWith(SSE_PREFIX) || line.startsWith("data:");
|
|
759
834
|
}
|
|
760
835
|
function extractSseDataPayload(line) {
|
|
761
|
-
|
|
836
|
+
if (line.startsWith(SSE_PREFIX)) {
|
|
837
|
+
return line.slice(SSE_PREFIX.length);
|
|
838
|
+
}
|
|
839
|
+
if (line.startsWith("data:")) {
|
|
840
|
+
return line.slice(5);
|
|
841
|
+
}
|
|
842
|
+
return line;
|
|
762
843
|
}
|
|
763
844
|
function isSseDoneMarker(payload) {
|
|
764
845
|
return payload === SSE_DONE_MARKER;
|
|
@@ -830,7 +911,7 @@ var StreamingResponseParser = class {
|
|
|
830
911
|
// src/core/parsers/json-content-extractor.ts
|
|
831
912
|
function extractJsonFromCodeFence(content) {
|
|
832
913
|
const match = content.match(JSON_CODE_BLOCK_PATTERN);
|
|
833
|
-
if (match && match[1]) return match[1];
|
|
914
|
+
if (match && match[1]) return match[1].trim();
|
|
834
915
|
return null;
|
|
835
916
|
}
|
|
836
917
|
function extractJsonObject(content) {
|
|
@@ -838,8 +919,27 @@ function extractJsonObject(content) {
|
|
|
838
919
|
if (match && match[0]) return match[0];
|
|
839
920
|
return null;
|
|
840
921
|
}
|
|
922
|
+
function extractJsonArray(content) {
|
|
923
|
+
const match = content.match(JSON_ARRAY_PATTERN);
|
|
924
|
+
if (match && match[0]) return match[0];
|
|
925
|
+
return null;
|
|
926
|
+
}
|
|
927
|
+
function repairCommonJsonDefects(text) {
|
|
928
|
+
return text.replace(/(:\s*-?\d+(?:\.\d+)?)\s*"/g, "$1").replace(/(:\s*"[^"]*")"/g, "$1");
|
|
929
|
+
}
|
|
841
930
|
function extractJsonCandidate(content) {
|
|
842
|
-
|
|
931
|
+
const fromFence = extractJsonFromCodeFence(content);
|
|
932
|
+
if (fromFence) return fromFence;
|
|
933
|
+
const objectIndex = content.indexOf("{");
|
|
934
|
+
const arrayIndex = content.indexOf("[");
|
|
935
|
+
if (objectIndex !== -1 && (arrayIndex === -1 || objectIndex < arrayIndex)) {
|
|
936
|
+
const obj = extractJsonObject(content);
|
|
937
|
+
if (obj) return obj;
|
|
938
|
+
} else if (arrayIndex !== -1) {
|
|
939
|
+
const arr = extractJsonArray(content);
|
|
940
|
+
if (arr) return arr;
|
|
941
|
+
}
|
|
942
|
+
return content.trim();
|
|
843
943
|
}
|
|
844
944
|
|
|
845
945
|
// src/core/parsers/json-response.parser.ts
|
|
@@ -848,12 +948,17 @@ var JsonResponseParser = class {
|
|
|
848
948
|
const candidate = extractJsonCandidate(rawContent);
|
|
849
949
|
try {
|
|
850
950
|
return JSON.parse(candidate);
|
|
851
|
-
} catch
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
951
|
+
} catch {
|
|
952
|
+
try {
|
|
953
|
+
return JSON.parse(repairCommonJsonDefects(candidate));
|
|
954
|
+
} catch (error) {
|
|
955
|
+
throw new AIError(
|
|
956
|
+
"UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
|
|
957
|
+
"Failed to parse structured response as JSON",
|
|
958
|
+
error instanceof Error ? error : void 0,
|
|
959
|
+
{ rawContent }
|
|
960
|
+
);
|
|
961
|
+
}
|
|
857
962
|
}
|
|
858
963
|
}
|
|
859
964
|
};
|
|
@@ -979,38 +1084,6 @@ function isMediaProvider(provider) {
|
|
|
979
1084
|
return provider.capabilities.includes("image") || provider.capabilities.includes("video");
|
|
980
1085
|
}
|
|
981
1086
|
|
|
982
|
-
// src/content/domain/errors/AIErrors.ts
|
|
983
|
-
var AIError2 = class _AIError extends Error {
|
|
984
|
-
code;
|
|
985
|
-
cause;
|
|
986
|
-
constructor(message, code, cause) {
|
|
987
|
-
super(message);
|
|
988
|
-
this.name = "AIError";
|
|
989
|
-
this.code = code;
|
|
990
|
-
this.cause = cause;
|
|
991
|
-
}
|
|
992
|
-
static from(error, fallbackCode = "UNKNOWN") {
|
|
993
|
-
if (error instanceof _AIError) return error;
|
|
994
|
-
if (error instanceof Error) {
|
|
995
|
-
return new _AIError(error.message, mapMessageToCode(error.message, fallbackCode), error);
|
|
996
|
-
}
|
|
997
|
-
return new _AIError(String(error), fallbackCode, error);
|
|
998
|
-
}
|
|
999
|
-
};
|
|
1000
|
-
function mapMessageToCode(message, fallback) {
|
|
1001
|
-
const lower = message.toLowerCase();
|
|
1002
|
-
if (lower.includes("validation")) return "VALIDATION_ERROR";
|
|
1003
|
-
if (lower.includes("quota")) return "PROVIDER_QUOTA_EXHAUSTED";
|
|
1004
|
-
if (lower.includes("unavailable")) return "PROVIDER_UNAVAILABLE";
|
|
1005
|
-
if (lower.includes("timeout") || lower.includes("aborted")) {
|
|
1006
|
-
return lower.includes("aborted") ? "ABORTED" : "TIMEOUT";
|
|
1007
|
-
}
|
|
1008
|
-
if (lower.includes("parse") || lower.includes("json")) return "PARSE_ERROR";
|
|
1009
|
-
if (lower.includes("no result")) return "NO_RESULT";
|
|
1010
|
-
if (lower.includes("network") || lower.includes("fetch")) return "NETWORK_ERROR";
|
|
1011
|
-
return fallback;
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
1087
|
// src/content/domain/limits/ProviderTimingConfig.ts
|
|
1015
1088
|
var ProviderTimingConfig = {
|
|
1016
1089
|
DEFAULT_TIMEOUT_MS: 3e4,
|
|
@@ -1075,7 +1148,7 @@ var BaseProvider = class {
|
|
|
1075
1148
|
throw lastError || new Error("Retry attempts exhausted");
|
|
1076
1149
|
}
|
|
1077
1150
|
};
|
|
1078
|
-
var ProviderError = class extends
|
|
1151
|
+
var ProviderError = class extends AIError {
|
|
1079
1152
|
constructor(message, providerId, originalError) {
|
|
1080
1153
|
super(message, "PROVIDER_ERROR", originalError);
|
|
1081
1154
|
this.providerId = providerId;
|
|
@@ -1169,12 +1242,16 @@ var ProviderFactory = class {
|
|
|
1169
1242
|
let wake = null;
|
|
1170
1243
|
let finished = false;
|
|
1171
1244
|
let failure;
|
|
1245
|
+
const controller = new AbortController();
|
|
1246
|
+
const onAbort = () => controller.abort();
|
|
1247
|
+
request.signal?.addEventListener("abort", onAbort);
|
|
1248
|
+
const effectiveRequest = { ...request, signal: controller.signal };
|
|
1172
1249
|
const notify = () => {
|
|
1173
1250
|
const resolve = wake;
|
|
1174
1251
|
wake = null;
|
|
1175
1252
|
resolve?.();
|
|
1176
1253
|
};
|
|
1177
|
-
const completion = this.chatStream(
|
|
1254
|
+
const completion = this.chatStream(effectiveRequest, {
|
|
1178
1255
|
onChunk: (chunk) => {
|
|
1179
1256
|
queue.push(chunk);
|
|
1180
1257
|
notify();
|
|
@@ -1190,18 +1267,23 @@ var ProviderFactory = class {
|
|
|
1190
1267
|
notify();
|
|
1191
1268
|
}
|
|
1192
1269
|
);
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1270
|
+
try {
|
|
1271
|
+
while (!finished || queue.length > 0) {
|
|
1272
|
+
if (queue.length === 0 && !finished) {
|
|
1273
|
+
await new Promise((resolve) => {
|
|
1274
|
+
wake = resolve;
|
|
1275
|
+
});
|
|
1276
|
+
}
|
|
1277
|
+
while (queue.length > 0) {
|
|
1278
|
+
yield queue.shift();
|
|
1279
|
+
}
|
|
1280
|
+
if (failure) throw failure;
|
|
1201
1281
|
}
|
|
1202
|
-
|
|
1282
|
+
await completion;
|
|
1283
|
+
} finally {
|
|
1284
|
+
controller.abort();
|
|
1285
|
+
request.signal?.removeEventListener("abort", onAbort);
|
|
1203
1286
|
}
|
|
1204
|
-
await completion;
|
|
1205
1287
|
}
|
|
1206
1288
|
async generateJson(request) {
|
|
1207
1289
|
const effective = request.model || request.tier ? request : { ...request, tier: this.defaultTier };
|
|
@@ -1610,11 +1692,14 @@ async function consumeAnthropicStream(stream, callbacks) {
|
|
|
1610
1692
|
break;
|
|
1611
1693
|
case "message_stop":
|
|
1612
1694
|
break;
|
|
1613
|
-
case "error":
|
|
1695
|
+
case "error": {
|
|
1696
|
+
const errType = event.error.type;
|
|
1697
|
+
const mappedType = errType === "rate_limit_error" ? "RATE_LIMIT_ERROR" /* RATE_LIMIT_ERROR */ : errType === "authentication_error" ? "INVALID_API_KEY" /* INVALID_API_KEY */ : errType === "invalid_request_error" ? "CLIENT_ERROR" /* CLIENT_ERROR */ : "SERVER_ERROR" /* SERVER_ERROR */;
|
|
1614
1698
|
throw new AIError(
|
|
1615
|
-
|
|
1699
|
+
mappedType,
|
|
1616
1700
|
event.error.message || "Anthropic stream failed mid-flight"
|
|
1617
1701
|
);
|
|
1702
|
+
}
|
|
1618
1703
|
}
|
|
1619
1704
|
};
|
|
1620
1705
|
try {
|
|
@@ -1806,12 +1891,22 @@ var DEFAULT_GENERATION_CONFIG = {
|
|
|
1806
1891
|
maxTokens: 1024,
|
|
1807
1892
|
topP: 1
|
|
1808
1893
|
};
|
|
1894
|
+
var DEFAULT_MODELS = {
|
|
1895
|
+
TEXT: GROQ_MODELS.LLAMA_3_1_8B_INSTANT,
|
|
1896
|
+
FAST: GROQ_MODELS.LLAMA_3_1_8B_INSTANT,
|
|
1897
|
+
EXPERIMENTAL: GROQ_MODELS.GPT_OSS_20B
|
|
1898
|
+
};
|
|
1809
1899
|
var GROQ_BASE_URL = "https://api.groq.com/openai/v1";
|
|
1900
|
+
var DEFAULT_BASE_URL = GROQ_BASE_URL;
|
|
1810
1901
|
var CHAT_COMPLETIONS_PATH = "/chat/completions";
|
|
1902
|
+
var API_ENDPOINTS = {
|
|
1903
|
+
CHAT: CHAT_COMPLETIONS_PATH
|
|
1904
|
+
};
|
|
1811
1905
|
var GROQ_TIMEOUTS = {
|
|
1812
1906
|
DEFAULT: 3e4,
|
|
1813
1907
|
STREAMING: 6e4
|
|
1814
1908
|
};
|
|
1909
|
+
var TIMEOUTS = GROQ_TIMEOUTS;
|
|
1815
1910
|
var HTTP_HEADERS = {
|
|
1816
1911
|
CONTENT_TYPE: "Content-Type",
|
|
1817
1912
|
APPLICATION_JSON: "application/json",
|
|
@@ -1870,13 +1965,65 @@ var GroqChatRequestBuilder = class _GroqChatRequestBuilder {
|
|
|
1870
1965
|
}
|
|
1871
1966
|
};
|
|
1872
1967
|
|
|
1968
|
+
// src/providers/groq/groq-config-store.ts
|
|
1969
|
+
var GroqConfigStore = class {
|
|
1970
|
+
config = null;
|
|
1971
|
+
initialize(config) {
|
|
1972
|
+
const validation = validateApiKey(config.apiKey, { minLength: 1 });
|
|
1973
|
+
if (!validation.valid) {
|
|
1974
|
+
throw new GroqError("INVALID_API_KEY" /* INVALID_API_KEY */, validation.reason ?? "Invalid API key");
|
|
1975
|
+
}
|
|
1976
|
+
const normalized = {
|
|
1977
|
+
apiKey: config.apiKey.trim(),
|
|
1978
|
+
baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,
|
|
1979
|
+
timeoutMs: config.timeoutMs ?? TIMEOUTS.DEFAULT,
|
|
1980
|
+
...config.models !== void 0 ? { models: config.models } : {},
|
|
1981
|
+
...config.textModel !== void 0 ? { textModel: config.textModel } : {}
|
|
1982
|
+
};
|
|
1983
|
+
this.config = normalized;
|
|
1984
|
+
return normalized;
|
|
1985
|
+
}
|
|
1986
|
+
get() {
|
|
1987
|
+
if (!this.config) {
|
|
1988
|
+
throw new GroqError(
|
|
1989
|
+
"MISSING_CONFIG" /* MISSING_CONFIG */,
|
|
1990
|
+
"Client not initialized. Call configureProvider first."
|
|
1991
|
+
);
|
|
1992
|
+
}
|
|
1993
|
+
return this.config;
|
|
1994
|
+
}
|
|
1995
|
+
getOrNull() {
|
|
1996
|
+
return this.config;
|
|
1997
|
+
}
|
|
1998
|
+
isInitialized() {
|
|
1999
|
+
return this.config !== null;
|
|
2000
|
+
}
|
|
2001
|
+
setApiKey(apiKey) {
|
|
2002
|
+
const current = this.get();
|
|
2003
|
+
const validation = validateApiKey(apiKey, { minLength: 1 });
|
|
2004
|
+
if (!validation.valid) {
|
|
2005
|
+
throw new GroqError("INVALID_API_KEY" /* INVALID_API_KEY */, validation.reason ?? "Invalid API key");
|
|
2006
|
+
}
|
|
2007
|
+
this.config = { ...current, apiKey: apiKey.trim() };
|
|
2008
|
+
}
|
|
2009
|
+
reset() {
|
|
2010
|
+
this.config = null;
|
|
2011
|
+
}
|
|
2012
|
+
};
|
|
2013
|
+
|
|
1873
2014
|
// src/providers/groq/groq-http-transport.ts
|
|
1874
2015
|
var GroqHttpTransport = class {
|
|
1875
|
-
constructor(
|
|
1876
|
-
this.
|
|
2016
|
+
constructor(configSource) {
|
|
2017
|
+
this.configSource = configSource;
|
|
1877
2018
|
}
|
|
1878
|
-
|
|
2019
|
+
configSource;
|
|
1879
2020
|
pendingAbortControllers = /* @__PURE__ */ new Set();
|
|
2021
|
+
getConfig() {
|
|
2022
|
+
if ("get" in this.configSource && typeof this.configSource.get === "function") {
|
|
2023
|
+
return this.configSource.get();
|
|
2024
|
+
}
|
|
2025
|
+
return this.configSource;
|
|
2026
|
+
}
|
|
1880
2027
|
cancelPendingRequests() {
|
|
1881
2028
|
for (const controller of this.pendingAbortControllers) {
|
|
1882
2029
|
controller.abort();
|
|
@@ -1891,7 +2038,7 @@ var GroqHttpTransport = class {
|
|
|
1891
2038
|
}
|
|
1892
2039
|
async streamChatCompletion(request, options = {}) {
|
|
1893
2040
|
const url = `${this.baseUrl()}${CHAT_COMPLETIONS_PATH}`;
|
|
1894
|
-
const timeout = this.
|
|
2041
|
+
const timeout = this.getConfig().timeoutMs ?? GROQ_TIMEOUTS.STREAMING;
|
|
1895
2042
|
const controller = new AbortController();
|
|
1896
2043
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
1897
2044
|
const onExternalAbort = () => controller.abort();
|
|
@@ -1918,11 +2065,11 @@ var GroqHttpTransport = class {
|
|
|
1918
2065
|
}
|
|
1919
2066
|
}
|
|
1920
2067
|
baseUrl() {
|
|
1921
|
-
return this.
|
|
2068
|
+
return this.getConfig().baseUrl ?? GROQ_BASE_URL;
|
|
1922
2069
|
}
|
|
1923
2070
|
async request(endpoint, body) {
|
|
1924
2071
|
const url = `${this.baseUrl()}${endpoint}`;
|
|
1925
|
-
const timeout = this.
|
|
2072
|
+
const timeout = this.getConfig().timeoutMs ?? GROQ_TIMEOUTS.DEFAULT;
|
|
1926
2073
|
const controller = new AbortController();
|
|
1927
2074
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
1928
2075
|
this.pendingAbortControllers.add(controller);
|
|
@@ -1945,7 +2092,7 @@ var GroqHttpTransport = class {
|
|
|
1945
2092
|
buildHeaders() {
|
|
1946
2093
|
return {
|
|
1947
2094
|
[HTTP_HEADERS.CONTENT_TYPE]: HTTP_HEADERS.APPLICATION_JSON,
|
|
1948
|
-
[HTTP_HEADERS.AUTHORIZATION]: `${HTTP_HEADERS.BEARER_PREFIX}${this.
|
|
2095
|
+
[HTTP_HEADERS.AUTHORIZATION]: `${HTTP_HEADERS.BEARER_PREFIX}${this.getConfig().apiKey}`
|
|
1949
2096
|
};
|
|
1950
2097
|
}
|
|
1951
2098
|
async throwFromErrorResponse(response) {
|
|
@@ -1989,21 +2136,40 @@ var GroqHttpTransport = class {
|
|
|
1989
2136
|
|
|
1990
2137
|
// src/providers/groq/groq-http-client.ts
|
|
1991
2138
|
var GroqHttpClient = class {
|
|
2139
|
+
configStore;
|
|
1992
2140
|
transport;
|
|
1993
2141
|
executor;
|
|
1994
|
-
constructor(
|
|
1995
|
-
|
|
2142
|
+
constructor(configOrDeps, maybeDeps = {}) {
|
|
2143
|
+
const isConfig = typeof configOrDeps === "object" && configOrDeps !== null && "apiKey" in configOrDeps && typeof configOrDeps.apiKey === "string";
|
|
2144
|
+
const deps = isConfig ? maybeDeps : configOrDeps ?? {};
|
|
2145
|
+
this.configStore = deps.configStore ?? new GroqConfigStore();
|
|
2146
|
+
if (isConfig) {
|
|
2147
|
+
this.configStore.initialize(configOrDeps);
|
|
2148
|
+
}
|
|
2149
|
+
this.transport = deps.transport ?? new GroqHttpTransport(this.configStore);
|
|
1996
2150
|
const retryManager2 = deps.retryManager ?? new RetryManager();
|
|
1997
2151
|
const queue = deps.queue ?? new RequestQueue();
|
|
1998
2152
|
const deduplicator = deps.deduplicator ?? new RequestDeduplicator();
|
|
1999
2153
|
this.executor = new CompositeExecutor([
|
|
2000
2154
|
new DedupeExecutor(deduplicator, {
|
|
2001
|
-
generateKey: (request) => deduplicatorKey(request,
|
|
2155
|
+
generateKey: (request) => deduplicatorKey(request, this.configStore.isInitialized() ? this.configStore.get().apiKey : "")
|
|
2002
2156
|
}),
|
|
2003
2157
|
new RetryExecutor(retryManager2),
|
|
2004
2158
|
new QueueExecutor(queue, QUEUE_PRIORITY_USER_REQUEST)
|
|
2005
2159
|
]);
|
|
2006
2160
|
}
|
|
2161
|
+
initialize(config) {
|
|
2162
|
+
this.configStore.initialize(config);
|
|
2163
|
+
}
|
|
2164
|
+
isInitialized() {
|
|
2165
|
+
return this.configStore.isInitialized();
|
|
2166
|
+
}
|
|
2167
|
+
getApiKey() {
|
|
2168
|
+
return this.configStore.get().apiKey;
|
|
2169
|
+
}
|
|
2170
|
+
setApiKey(apiKey) {
|
|
2171
|
+
this.configStore.setApiKey(apiKey);
|
|
2172
|
+
}
|
|
2007
2173
|
cancelPendingRequests() {
|
|
2008
2174
|
this.transport.cancelPendingRequests();
|
|
2009
2175
|
}
|
|
@@ -2016,6 +2182,10 @@ var GroqHttpClient = class {
|
|
|
2016
2182
|
streamChatCompletion(request, options) {
|
|
2017
2183
|
return this.transport.streamChatCompletion(request, options);
|
|
2018
2184
|
}
|
|
2185
|
+
reset() {
|
|
2186
|
+
this.transport.cancelPendingRequests();
|
|
2187
|
+
this.configStore.reset();
|
|
2188
|
+
}
|
|
2019
2189
|
};
|
|
2020
2190
|
function deduplicatorKey(request, apiKey) {
|
|
2021
2191
|
const { model, messages, stream: _stream, ...rest } = request;
|
|
@@ -2072,6 +2242,13 @@ async function consumeGroqStream(stream, callbacks) {
|
|
|
2072
2242
|
} catch {
|
|
2073
2243
|
return;
|
|
2074
2244
|
}
|
|
2245
|
+
const errorBody = chunk.error;
|
|
2246
|
+
if (errorBody) {
|
|
2247
|
+
throw new AIError(
|
|
2248
|
+
errorBody.message?.toLowerCase().includes("rate limit") ? "RATE_LIMIT_ERROR" /* RATE_LIMIT_ERROR */ : "SERVER_ERROR" /* SERVER_ERROR */,
|
|
2249
|
+
errorBody.message || "Groq stream failed mid-flight"
|
|
2250
|
+
);
|
|
2251
|
+
}
|
|
2075
2252
|
if (chunk.model) model = chunk.model;
|
|
2076
2253
|
const choice = chunk.choices?.[0];
|
|
2077
2254
|
const delta = choice?.delta?.content;
|
|
@@ -2086,13 +2263,6 @@ async function consumeGroqStream(stream, callbacks) {
|
|
|
2086
2263
|
if (tailUsage) {
|
|
2087
2264
|
usage = mapGroqUsage(tailUsage);
|
|
2088
2265
|
}
|
|
2089
|
-
const errorBody = chunk.error;
|
|
2090
|
-
if (errorBody) {
|
|
2091
|
-
throw new AIError(
|
|
2092
|
-
"SERVER_ERROR" /* SERVER_ERROR */,
|
|
2093
|
-
errorBody.message || "Groq stream failed mid-flight"
|
|
2094
|
-
);
|
|
2095
|
-
}
|
|
2096
2266
|
};
|
|
2097
2267
|
try {
|
|
2098
2268
|
while (true) {
|
|
@@ -2359,7 +2529,9 @@ var GeminiProvider = class extends BaseProvider {
|
|
|
2359
2529
|
headers: this.authHeaders()
|
|
2360
2530
|
}
|
|
2361
2531
|
);
|
|
2362
|
-
|
|
2532
|
+
if (response.ok) return "healthy";
|
|
2533
|
+
if (response.status === 401 || response.status === 403) return "unavailable";
|
|
2534
|
+
return "degraded";
|
|
2363
2535
|
} catch {
|
|
2364
2536
|
return "unavailable";
|
|
2365
2537
|
}
|
|
@@ -2370,6 +2542,8 @@ var GeminiProvider = class extends BaseProvider {
|
|
|
2370
2542
|
async generate(request) {
|
|
2371
2543
|
try {
|
|
2372
2544
|
const model = request.model ?? this.resolveModel(request.tier ?? "balanced");
|
|
2545
|
+
const systemMessages = request.messages.filter((m) => m.role === "system");
|
|
2546
|
+
const systemPrompt = request.systemPrompt && request.systemPrompt.length > 0 ? request.systemPrompt : systemMessages.length > 0 ? systemMessages.map((m) => m.content).join("\n") : void 0;
|
|
2373
2547
|
const response = await this.withRetry(async () => {
|
|
2374
2548
|
return await this.fetchWithTimeout(
|
|
2375
2549
|
`${this.config.baseUrl}/models/${model}:generateContent`,
|
|
@@ -2377,22 +2551,28 @@ var GeminiProvider = class extends BaseProvider {
|
|
|
2377
2551
|
method: "POST",
|
|
2378
2552
|
headers: this.authHeaders(),
|
|
2379
2553
|
body: JSON.stringify({
|
|
2380
|
-
systemInstruction:
|
|
2554
|
+
systemInstruction: systemPrompt && systemPrompt.length > 0 ? { parts: [{ text: systemPrompt }] } : void 0,
|
|
2381
2555
|
contents: toGeminiContents(request.messages),
|
|
2382
2556
|
generationConfig: {
|
|
2383
|
-
temperature: request.temperature
|
|
2384
|
-
maxOutputTokens: request.maxTokens
|
|
2385
|
-
topP: request.topP
|
|
2557
|
+
temperature: request.temperature ?? 0.7,
|
|
2558
|
+
maxOutputTokens: request.maxTokens ?? 2048,
|
|
2559
|
+
topP: request.topP ?? 0.9
|
|
2386
2560
|
}
|
|
2387
2561
|
})
|
|
2388
2562
|
}
|
|
2389
2563
|
);
|
|
2390
2564
|
});
|
|
2391
2565
|
if (!response.ok) {
|
|
2392
|
-
|
|
2566
|
+
const message = await extractErrorMessageFromResponse(response);
|
|
2567
|
+
throw new AIError(
|
|
2568
|
+
classifyHttpStatus(response.status),
|
|
2569
|
+
`Gemini API error (${response.status}): ${message}`,
|
|
2570
|
+
void 0,
|
|
2571
|
+
{ status: response.status, model }
|
|
2572
|
+
);
|
|
2393
2573
|
}
|
|
2394
2574
|
const data = await response.json();
|
|
2395
|
-
const text = data.candidates[0]?.content?.parts?.map((part) => part.text ?? "").join("") ?? "";
|
|
2575
|
+
const text = data.candidates?.[0]?.content?.parts?.map((part) => part.text ?? "").join("") ?? "";
|
|
2396
2576
|
if (text.length === 0) {
|
|
2397
2577
|
throw new AIError("SERVER_ERROR" /* SERVER_ERROR */, "No content generated from Gemini API", void 0, { model });
|
|
2398
2578
|
}
|
|
@@ -2405,7 +2585,7 @@ var GeminiProvider = class extends BaseProvider {
|
|
|
2405
2585
|
} : void 0,
|
|
2406
2586
|
model,
|
|
2407
2587
|
providerId: this.id,
|
|
2408
|
-
finishReason: mapGeminiFinishReason(data.candidates[0]?.finishReason)
|
|
2588
|
+
finishReason: mapGeminiFinishReason(data.candidates?.[0]?.finishReason)
|
|
2409
2589
|
};
|
|
2410
2590
|
} catch (error) {
|
|
2411
2591
|
if (error instanceof AIError) throw error;
|
|
@@ -2457,12 +2637,18 @@ var GeminiProvider = class extends BaseProvider {
|
|
|
2457
2637
|
);
|
|
2458
2638
|
});
|
|
2459
2639
|
if (!response.ok) {
|
|
2460
|
-
|
|
2640
|
+
const message = await extractErrorMessageFromResponse(response);
|
|
2641
|
+
throw new AIError(
|
|
2642
|
+
classifyHttpStatus(response.status),
|
|
2643
|
+
`Gemini image generation error (${response.status}): ${message}`,
|
|
2644
|
+
void 0,
|
|
2645
|
+
{ status: response.status }
|
|
2646
|
+
);
|
|
2461
2647
|
}
|
|
2462
2648
|
const data = await response.json();
|
|
2463
|
-
const imageData = data.candidates[0]?.content?.parts[0]?.inlineData;
|
|
2649
|
+
const imageData = data.candidates?.[0]?.content?.parts?.[0]?.inlineData;
|
|
2464
2650
|
if (!imageData) {
|
|
2465
|
-
throw new
|
|
2651
|
+
throw new AIError("SERVER_ERROR" /* SERVER_ERROR */, "No image data in Gemini response");
|
|
2466
2652
|
}
|
|
2467
2653
|
const url = `data:${imageData.mimeType};base64,${imageData.data}`;
|
|
2468
2654
|
return {
|
|
@@ -2781,17 +2967,70 @@ var PrunaProvider = class {
|
|
|
2781
2967
|
async estimateCost(_request) {
|
|
2782
2968
|
return 1;
|
|
2783
2969
|
}
|
|
2784
|
-
async generateImage(
|
|
2785
|
-
|
|
2970
|
+
async generateImage(request) {
|
|
2971
|
+
let finalUrl;
|
|
2972
|
+
const model = this.config.models?.textToImage;
|
|
2973
|
+
for await (const stage of generateWithPruna(
|
|
2974
|
+
{ prompt: request.prompt, model, quality: request.quality },
|
|
2975
|
+
this.config.apiKey
|
|
2976
|
+
)) {
|
|
2977
|
+
if (stage.error) throw stage.error;
|
|
2978
|
+
if (stage.result?.url) finalUrl = stage.result.url;
|
|
2979
|
+
}
|
|
2980
|
+
if (!finalUrl) {
|
|
2981
|
+
throw new AIError("SERVER_ERROR" /* SERVER_ERROR */, "No image generated by Pruna AI");
|
|
2982
|
+
}
|
|
2983
|
+
return {
|
|
2984
|
+
id: Date.now().toString(),
|
|
2985
|
+
type: "image",
|
|
2986
|
+
url: finalUrl,
|
|
2987
|
+
metadata: { provider: this.id, model: model ?? "p-image" },
|
|
2988
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2989
|
+
};
|
|
2786
2990
|
}
|
|
2787
|
-
async generateVideo(
|
|
2788
|
-
|
|
2991
|
+
async generateVideo(request) {
|
|
2992
|
+
let finalUrl;
|
|
2993
|
+
const model = this.config.models?.textToVideo;
|
|
2994
|
+
for await (const stage of generateWithPruna(
|
|
2995
|
+
{ prompt: request.prompt, model, duration: request.duration, aspectRatio: request.aspectRatio },
|
|
2996
|
+
this.config.apiKey
|
|
2997
|
+
)) {
|
|
2998
|
+
if (stage.error) throw stage.error;
|
|
2999
|
+
if (stage.result?.url) finalUrl = stage.result.url;
|
|
3000
|
+
}
|
|
3001
|
+
if (!finalUrl) {
|
|
3002
|
+
throw new AIError("SERVER_ERROR" /* SERVER_ERROR */, "No video generated by Pruna AI");
|
|
3003
|
+
}
|
|
3004
|
+
return {
|
|
3005
|
+
id: Date.now().toString(),
|
|
3006
|
+
type: "video",
|
|
3007
|
+
url: finalUrl,
|
|
3008
|
+
metadata: { provider: this.id, model: model ?? "p-video" },
|
|
3009
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3010
|
+
};
|
|
2789
3011
|
}
|
|
2790
|
-
async imageToVideo(
|
|
2791
|
-
|
|
3012
|
+
async imageToVideo(request) {
|
|
3013
|
+
let finalUrl;
|
|
3014
|
+
for await (const stage of generateWithPruna(
|
|
3015
|
+
{ image: request.imageUrl, prompt: request.prompt, duration: request.duration, motion: request.motion },
|
|
3016
|
+
this.config.apiKey
|
|
3017
|
+
)) {
|
|
3018
|
+
if (stage.error) throw stage.error;
|
|
3019
|
+
if (stage.result?.url) finalUrl = stage.result.url;
|
|
3020
|
+
}
|
|
3021
|
+
if (!finalUrl) {
|
|
3022
|
+
throw new AIError("SERVER_ERROR" /* SERVER_ERROR */, "No video generated from image by Pruna AI");
|
|
3023
|
+
}
|
|
3024
|
+
return {
|
|
3025
|
+
id: Date.now().toString(),
|
|
3026
|
+
type: "video",
|
|
3027
|
+
url: finalUrl,
|
|
3028
|
+
metadata: { provider: this.id, model: "p-image-to-video" },
|
|
3029
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3030
|
+
};
|
|
2792
3031
|
}
|
|
2793
3032
|
async videoToVideo(_request) {
|
|
2794
|
-
throw new AIError("
|
|
3033
|
+
throw new AIError("CLIENT_ERROR" /* CLIENT_ERROR */, "Pruna AI provider does not support video-to-video conversion");
|
|
2795
3034
|
}
|
|
2796
3035
|
};
|
|
2797
3036
|
function createPrunaProvider(config) {
|
|
@@ -2823,6 +3062,278 @@ function createAI(config = {}) {
|
|
|
2823
3062
|
return factory;
|
|
2824
3063
|
}
|
|
2825
3064
|
|
|
3065
|
+
// src/providers/groq/groq-messages.ts
|
|
3066
|
+
var createUserMessage = (content) => ({
|
|
3067
|
+
role: "user",
|
|
3068
|
+
content
|
|
3069
|
+
});
|
|
3070
|
+
var createAssistantMessage = (content) => ({
|
|
3071
|
+
role: "assistant",
|
|
3072
|
+
content
|
|
3073
|
+
});
|
|
3074
|
+
var createSystemMessage = (content) => ({
|
|
3075
|
+
role: "system",
|
|
3076
|
+
content
|
|
3077
|
+
});
|
|
3078
|
+
var createMessage = (role, content) => ({
|
|
3079
|
+
role,
|
|
3080
|
+
content
|
|
3081
|
+
});
|
|
3082
|
+
var promptToMessages = (prompt) => [
|
|
3083
|
+
createUserMessage(prompt)
|
|
3084
|
+
];
|
|
3085
|
+
var extractTextFromMessages = (messages) => messages.map((m) => m.content).join("\n\n");
|
|
3086
|
+
var formatMessagesForDisplay = (messages) => messages.map((m) => `[${m.role.toUpperCase()}]: ${m.content}`).join("\n\n---\n\n");
|
|
3087
|
+
|
|
3088
|
+
// src/providers/groq/groq-structured-json.ts
|
|
3089
|
+
async function requestStructuredJson(client, request) {
|
|
3090
|
+
const chatRequest = {
|
|
3091
|
+
model: request.model,
|
|
3092
|
+
messages: [createUserMessage(request.instructions)],
|
|
3093
|
+
temperature: request.temperature,
|
|
3094
|
+
max_tokens: request.maxTokens,
|
|
3095
|
+
response_format: { type: "json_object" },
|
|
3096
|
+
...request.reasoningEffort !== void 0 ? { reasoning_effort: request.reasoningEffort } : {}
|
|
3097
|
+
};
|
|
3098
|
+
const response = await client.postChatCompletion(chatRequest);
|
|
3099
|
+
const content = response.choices[0]?.message?.content ?? "";
|
|
3100
|
+
const candidate = extractJsonCandidate(content);
|
|
3101
|
+
try {
|
|
3102
|
+
return JSON.parse(candidate);
|
|
3103
|
+
} catch (err) {
|
|
3104
|
+
throw new GroqError(
|
|
3105
|
+
"UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
|
|
3106
|
+
"model response contained no parsable json object",
|
|
3107
|
+
err instanceof Error ? err : void 0
|
|
3108
|
+
);
|
|
3109
|
+
}
|
|
3110
|
+
}
|
|
3111
|
+
|
|
3112
|
+
// src/providers/groq/text-generation.service.ts
|
|
3113
|
+
var STRUCTURED_OUTPUT_TEMPERATURE = 0.1;
|
|
3114
|
+
var TextGenerationService = class {
|
|
3115
|
+
constructor(httpClient, cache = new CacheManager(), defaultModel = DEFAULT_MODELS.TEXT) {
|
|
3116
|
+
this.httpClient = httpClient;
|
|
3117
|
+
this.cache = cache;
|
|
3118
|
+
this.defaultModel = defaultModel;
|
|
3119
|
+
}
|
|
3120
|
+
httpClient;
|
|
3121
|
+
cache;
|
|
3122
|
+
defaultModel;
|
|
3123
|
+
id = "groq-text-generation";
|
|
3124
|
+
name = "Groq Text Generation";
|
|
3125
|
+
capabilities = ["text"];
|
|
3126
|
+
jsonParser = new JsonResponseParser();
|
|
3127
|
+
generateCompletion(prompt, options = {}) {
|
|
3128
|
+
const model = options.model ?? this.defaultModel;
|
|
3129
|
+
return this.executeWithCache(
|
|
3130
|
+
{
|
|
3131
|
+
type: CACHE_KEY_TYPE_COMPLETION,
|
|
3132
|
+
model,
|
|
3133
|
+
prompt,
|
|
3134
|
+
config: options.generationConfig
|
|
3135
|
+
},
|
|
3136
|
+
async () => {
|
|
3137
|
+
const request = GroqChatRequestBuilder.for(model).withMessages([createUserMessage(prompt)]).withConfig(options.generationConfig).build();
|
|
3138
|
+
const response = await this.httpClient.postChatCompletion(request);
|
|
3139
|
+
return this.extractContent(response.choices[0]?.message?.content);
|
|
3140
|
+
}
|
|
3141
|
+
);
|
|
3142
|
+
}
|
|
3143
|
+
generateChatCompletion(messages, options = {}) {
|
|
3144
|
+
const model = options.model ?? this.defaultModel;
|
|
3145
|
+
return this.executeWithCache(
|
|
3146
|
+
{
|
|
3147
|
+
type: CACHE_KEY_TYPE_CHAT,
|
|
3148
|
+
model,
|
|
3149
|
+
messages: [...messages],
|
|
3150
|
+
config: options.generationConfig
|
|
3151
|
+
},
|
|
3152
|
+
async () => {
|
|
3153
|
+
const request = GroqChatRequestBuilder.for(model).withMessages(messages).withConfig(options.generationConfig).build();
|
|
3154
|
+
const response = await this.httpClient.postChatCompletion(request);
|
|
3155
|
+
return this.extractContent(response.choices[0]?.message?.content);
|
|
3156
|
+
}
|
|
3157
|
+
);
|
|
3158
|
+
}
|
|
3159
|
+
generateStructured(promptOrRequest, options) {
|
|
3160
|
+
if (typeof promptOrRequest === "string") {
|
|
3161
|
+
const model2 = options?.model ?? this.defaultModel;
|
|
3162
|
+
const jsonPrompt = StructuredPromptBuilder.for(promptOrRequest).withSchema(options?.schema).build();
|
|
3163
|
+
const request = GroqChatRequestBuilder.for(model2).withMessages([createUserMessage(jsonPrompt)]).withConfig({
|
|
3164
|
+
...options?.generationConfig,
|
|
3165
|
+
temperature: STRUCTURED_OUTPUT_TEMPERATURE
|
|
3166
|
+
}).build();
|
|
3167
|
+
return this.httpClient.postChatCompletion(request).then((response) => {
|
|
3168
|
+
const content = this.extractContent(response.choices[0]?.message?.content);
|
|
3169
|
+
return this.jsonParser.parse(content);
|
|
3170
|
+
});
|
|
3171
|
+
}
|
|
3172
|
+
const req = promptOrRequest;
|
|
3173
|
+
const model = req.model ?? (req.tier ? this.resolveModel(req.tier) : this.defaultModel);
|
|
3174
|
+
const schemaObj = req.schema;
|
|
3175
|
+
const messages = [];
|
|
3176
|
+
if (req.systemPrompt) {
|
|
3177
|
+
messages.push({ role: "system", content: req.systemPrompt });
|
|
3178
|
+
}
|
|
3179
|
+
for (const m of req.messages) {
|
|
3180
|
+
messages.push({ role: m.role, content: m.content });
|
|
3181
|
+
}
|
|
3182
|
+
const lastMsg = messages[messages.length - 1];
|
|
3183
|
+
if (lastMsg) {
|
|
3184
|
+
const structuredPrompt = StructuredPromptBuilder.for(lastMsg.content).withSchema(schemaObj).build();
|
|
3185
|
+
messages[messages.length - 1] = { ...lastMsg, content: structuredPrompt };
|
|
3186
|
+
}
|
|
3187
|
+
const groqReq = GroqChatRequestBuilder.for(model).withMessages(messages).withConfig({
|
|
3188
|
+
temperature: req.temperature ?? STRUCTURED_OUTPUT_TEMPERATURE,
|
|
3189
|
+
maxTokens: req.maxTokens
|
|
3190
|
+
}).build();
|
|
3191
|
+
return this.httpClient.postChatCompletion(groqReq).then((response) => {
|
|
3192
|
+
const content = this.extractContent(response.choices[0]?.message?.content);
|
|
3193
|
+
const parsed = this.jsonParser.parse(content);
|
|
3194
|
+
const genResult = {
|
|
3195
|
+
text: content,
|
|
3196
|
+
model: response.model,
|
|
3197
|
+
providerId: this.id,
|
|
3198
|
+
finishReason: response.choices[0]?.finish_reason ?? "stop",
|
|
3199
|
+
usage: response.usage ? {
|
|
3200
|
+
inputTokens: response.usage.prompt_tokens,
|
|
3201
|
+
outputTokens: response.usage.completion_tokens,
|
|
3202
|
+
totalTokens: response.usage.total_tokens
|
|
3203
|
+
} : void 0
|
|
3204
|
+
};
|
|
3205
|
+
return { value: parsed, result: genResult };
|
|
3206
|
+
});
|
|
3207
|
+
}
|
|
3208
|
+
streamCompletion(prompt, callbacks, options = {}) {
|
|
3209
|
+
return this.streamChatCompletion([createUserMessage(prompt)], callbacks, options);
|
|
3210
|
+
}
|
|
3211
|
+
async streamChatCompletion(messages, callbacks, options = {}) {
|
|
3212
|
+
const model = options.model ?? this.defaultModel;
|
|
3213
|
+
const request = GroqChatRequestBuilder.for(model).withMessages(messages).withConfig(options.generationConfig).withStream(true).build();
|
|
3214
|
+
const parser = new StreamingResponseParser(
|
|
3215
|
+
{
|
|
3216
|
+
onChunk: (chunk) => callbacks.onChunk?.(chunk)
|
|
3217
|
+
},
|
|
3218
|
+
extractContentFromSsePayload
|
|
3219
|
+
);
|
|
3220
|
+
try {
|
|
3221
|
+
const stream = await this.httpClient.streamChatCompletion(request, {
|
|
3222
|
+
signal: options.signal
|
|
3223
|
+
});
|
|
3224
|
+
const fullText = await parser.parse(stream);
|
|
3225
|
+
callbacks.onComplete?.(fullText);
|
|
3226
|
+
return fullText;
|
|
3227
|
+
} catch (error) {
|
|
3228
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
3229
|
+
callbacks.onError?.(err);
|
|
3230
|
+
throw err;
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
clearCache() {
|
|
3234
|
+
this.cache.clear();
|
|
3235
|
+
}
|
|
3236
|
+
// --- ITextProvider implementation ---
|
|
3237
|
+
resolveModel(tier) {
|
|
3238
|
+
return GROQ_TIERS[tier] ?? this.defaultModel;
|
|
3239
|
+
}
|
|
3240
|
+
async generate(request) {
|
|
3241
|
+
const messages = [];
|
|
3242
|
+
if (request.systemPrompt) {
|
|
3243
|
+
messages.push({ role: "system", content: request.systemPrompt });
|
|
3244
|
+
}
|
|
3245
|
+
for (const m of request.messages) {
|
|
3246
|
+
messages.push({ role: m.role, content: m.content });
|
|
3247
|
+
}
|
|
3248
|
+
const model = request.model ?? (request.tier ? this.resolveModel(request.tier) : this.defaultModel);
|
|
3249
|
+
const groqReq = GroqChatRequestBuilder.for(model).withMessages(messages).withConfig({
|
|
3250
|
+
temperature: request.temperature,
|
|
3251
|
+
maxTokens: request.maxTokens
|
|
3252
|
+
}).build();
|
|
3253
|
+
const resp = await this.httpClient.postChatCompletion(groqReq);
|
|
3254
|
+
const content = resp.choices[0]?.message?.content ?? "";
|
|
3255
|
+
return {
|
|
3256
|
+
text: content,
|
|
3257
|
+
finishReason: resp.choices[0]?.finish_reason ?? "stop",
|
|
3258
|
+
model: resp.model,
|
|
3259
|
+
providerId: this.id,
|
|
3260
|
+
usage: resp.usage ? {
|
|
3261
|
+
inputTokens: resp.usage.prompt_tokens,
|
|
3262
|
+
outputTokens: resp.usage.completion_tokens,
|
|
3263
|
+
totalTokens: resp.usage.total_tokens
|
|
3264
|
+
} : void 0
|
|
3265
|
+
};
|
|
3266
|
+
}
|
|
3267
|
+
async stream(request, callbacks) {
|
|
3268
|
+
const messages = [];
|
|
3269
|
+
if (request.systemPrompt) {
|
|
3270
|
+
messages.push({ role: "system", content: request.systemPrompt });
|
|
3271
|
+
}
|
|
3272
|
+
for (const m of request.messages) {
|
|
3273
|
+
messages.push({ role: m.role, content: m.content });
|
|
3274
|
+
}
|
|
3275
|
+
const model = request.model ?? (request.tier ? this.resolveModel(request.tier) : this.defaultModel);
|
|
3276
|
+
const text = await this.streamChatCompletion(
|
|
3277
|
+
messages,
|
|
3278
|
+
{
|
|
3279
|
+
onChunk: callbacks.onChunk,
|
|
3280
|
+
onError: callbacks.onError
|
|
3281
|
+
},
|
|
3282
|
+
{
|
|
3283
|
+
model,
|
|
3284
|
+
signal: request.signal,
|
|
3285
|
+
generationConfig: {
|
|
3286
|
+
temperature: request.temperature,
|
|
3287
|
+
maxTokens: request.maxTokens
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
);
|
|
3291
|
+
const result = {
|
|
3292
|
+
text,
|
|
3293
|
+
finishReason: "stop",
|
|
3294
|
+
model,
|
|
3295
|
+
providerId: this.id
|
|
3296
|
+
};
|
|
3297
|
+
callbacks.onComplete?.(result);
|
|
3298
|
+
return result;
|
|
3299
|
+
}
|
|
3300
|
+
async countTokens(text) {
|
|
3301
|
+
return Math.max(1, Math.ceil(text.length / 4));
|
|
3302
|
+
}
|
|
3303
|
+
async estimateCost(_request) {
|
|
3304
|
+
return 0;
|
|
3305
|
+
}
|
|
3306
|
+
async healthCheck() {
|
|
3307
|
+
try {
|
|
3308
|
+
await this.generateCompletion("ping", {
|
|
3309
|
+
generationConfig: { maxTokens: 1 }
|
|
3310
|
+
});
|
|
3311
|
+
return "healthy";
|
|
3312
|
+
} catch {
|
|
3313
|
+
return "unavailable";
|
|
3314
|
+
}
|
|
3315
|
+
}
|
|
3316
|
+
async executeWithCache(params, factory) {
|
|
3317
|
+
const key = this.cache.generateKey(params);
|
|
3318
|
+
const cached = this.cache.get(key);
|
|
3319
|
+
if (cached !== null) {
|
|
3320
|
+
return cached;
|
|
3321
|
+
}
|
|
3322
|
+
const result = await factory();
|
|
3323
|
+
this.cache.set(key, result);
|
|
3324
|
+
return result;
|
|
3325
|
+
}
|
|
3326
|
+
extractContent(content) {
|
|
3327
|
+
if (!content) {
|
|
3328
|
+
throw new GroqError(
|
|
3329
|
+
"UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
|
|
3330
|
+
"No content generated from Groq API"
|
|
3331
|
+
);
|
|
3332
|
+
}
|
|
3333
|
+
return content;
|
|
3334
|
+
}
|
|
3335
|
+
};
|
|
3336
|
+
|
|
2826
3337
|
// src/core/calculations/random-base36-suffix.ts
|
|
2827
3338
|
var BASE_36_RADIX = 36;
|
|
2828
3339
|
var DECIMAL_OFFSET = 2;
|
|
@@ -2943,9 +3454,12 @@ var ChatService = class {
|
|
|
2943
3454
|
};
|
|
2944
3455
|
}
|
|
2945
3456
|
async getConversations() {
|
|
3457
|
+
if (this.storage && "getConversations" in this.storage && typeof this.storage.getConversations === "function") {
|
|
3458
|
+
return this.storage.getConversations();
|
|
3459
|
+
}
|
|
2946
3460
|
return [];
|
|
2947
3461
|
}
|
|
2948
|
-
async sendMessage(input) {
|
|
3462
|
+
async sendMessage(input, signal) {
|
|
2949
3463
|
const userMessage = {
|
|
2950
3464
|
...messageFormatter.toChatMessage(input.text, "user"),
|
|
2951
3465
|
type: input.type ?? "text",
|
|
@@ -2954,13 +3468,14 @@ var ChatService = class {
|
|
|
2954
3468
|
const aiResponse = await this.generateAIResponse(
|
|
2955
3469
|
input.companionId,
|
|
2956
3470
|
input.text,
|
|
2957
|
-
[]
|
|
3471
|
+
[],
|
|
3472
|
+
signal
|
|
2958
3473
|
);
|
|
2959
3474
|
return { userMessage, aiResponse };
|
|
2960
3475
|
}
|
|
2961
|
-
async generateAIResponse(companionId, userMessage, context = []) {
|
|
3476
|
+
async generateAIResponse(companionId, userMessage, context = [], signal) {
|
|
2962
3477
|
const result = await this.run({
|
|
2963
|
-
...this.buildRequest(userMessage, context)
|
|
3478
|
+
...this.buildRequest(userMessage, context, signal)
|
|
2964
3479
|
});
|
|
2965
3480
|
return {
|
|
2966
3481
|
...messageFormatter.toChatMessage(result.text, "assistant"),
|
|
@@ -2976,12 +3491,12 @@ var ChatService = class {
|
|
|
2976
3491
|
}
|
|
2977
3492
|
};
|
|
2978
3493
|
}
|
|
2979
|
-
async generateStreamingResponse(userMessage, context, onChunk) {
|
|
2980
|
-
const request = this.buildRequest(userMessage, context);
|
|
3494
|
+
async generateStreamingResponse(userMessage, context, onChunk, signal) {
|
|
3495
|
+
const request = this.buildRequest(userMessage, context, signal);
|
|
2981
3496
|
const result = await this.runStream(request, { onChunk });
|
|
2982
3497
|
return result.text;
|
|
2983
3498
|
}
|
|
2984
|
-
buildRequest(userMessage, context) {
|
|
3499
|
+
buildRequest(userMessage, context, signal) {
|
|
2985
3500
|
const messages = messageFormatter.toCoreMessages(context);
|
|
2986
3501
|
messages.push({ role: "user", content: userMessage });
|
|
2987
3502
|
return {
|
|
@@ -2990,7 +3505,8 @@ var ChatService = class {
|
|
|
2990
3505
|
model: this.config.model,
|
|
2991
3506
|
tier: this.config.tier,
|
|
2992
3507
|
temperature: this.config.temperature,
|
|
2993
|
-
maxTokens: this.config.maxTokens
|
|
3508
|
+
maxTokens: this.config.maxTokens,
|
|
3509
|
+
...signal !== void 0 ? { signal } : {}
|
|
2994
3510
|
};
|
|
2995
3511
|
}
|
|
2996
3512
|
resolveSystemPrompt() {
|
|
@@ -3045,12 +3561,37 @@ function readNumber(source, keys) {
|
|
|
3045
3561
|
return null;
|
|
3046
3562
|
}
|
|
3047
3563
|
|
|
3564
|
+
// src/providers/groq/groq-container.ts
|
|
3565
|
+
var container = null;
|
|
3566
|
+
function configureProvider(config) {
|
|
3567
|
+
const configStore = new GroqConfigStore();
|
|
3568
|
+
const transport = new GroqHttpTransport(configStore);
|
|
3569
|
+
const httpClient = new GroqHttpClient({ configStore, transport });
|
|
3570
|
+
httpClient.initialize(config);
|
|
3571
|
+
const textGeneration = new TextGenerationService(
|
|
3572
|
+
httpClient,
|
|
3573
|
+
new CacheManager(),
|
|
3574
|
+
config.textModel
|
|
3575
|
+
);
|
|
3576
|
+
const chat = new ChatService(textGeneration);
|
|
3577
|
+
container = { groqHttpClient: httpClient, textGeneration, chat };
|
|
3578
|
+
return container;
|
|
3579
|
+
}
|
|
3580
|
+
function getProvider() {
|
|
3581
|
+
return container;
|
|
3582
|
+
}
|
|
3583
|
+
function resetProvider() {
|
|
3584
|
+
container?.groqHttpClient.reset();
|
|
3585
|
+
container = null;
|
|
3586
|
+
}
|
|
3587
|
+
|
|
3048
3588
|
exports.AIError = AIError;
|
|
3049
3589
|
exports.AIErrorType = AIErrorType;
|
|
3050
3590
|
exports.ANTHROPIC_API_VERSION = ANTHROPIC_API_VERSION;
|
|
3051
3591
|
exports.ANTHROPIC_DEFAULT_MAX_TOKENS = ANTHROPIC_DEFAULT_MAX_TOKENS;
|
|
3052
3592
|
exports.ANTHROPIC_MODELS = ANTHROPIC_MODELS;
|
|
3053
3593
|
exports.ANTHROPIC_TIERS = ANTHROPIC_TIERS;
|
|
3594
|
+
exports.API_ENDPOINTS = API_ENDPOINTS;
|
|
3054
3595
|
exports.AnthropicHttpTransport = AnthropicHttpTransport;
|
|
3055
3596
|
exports.AnthropicProvider = AnthropicProvider;
|
|
3056
3597
|
exports.AnthropicRequestBuilder = AnthropicRequestBuilder;
|
|
@@ -3060,8 +3601,11 @@ exports.ChatIdGenerator = ChatIdGenerator;
|
|
|
3060
3601
|
exports.ChatService = ChatService;
|
|
3061
3602
|
exports.CompositeExecutor = CompositeExecutor;
|
|
3062
3603
|
exports.DEFAULT_API_KEY_RULE = DEFAULT_API_KEY_RULE;
|
|
3604
|
+
exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
|
|
3063
3605
|
exports.DEFAULT_ERROR_CLASSIFICATION_RULE = DEFAULT_ERROR_CLASSIFICATION_RULE;
|
|
3606
|
+
exports.DEFAULT_GENERATION_CONFIG = DEFAULT_GENERATION_CONFIG;
|
|
3064
3607
|
exports.DEFAULT_HTTP_STATUS_RULE = DEFAULT_HTTP_STATUS_RULE;
|
|
3608
|
+
exports.DEFAULT_MODELS = DEFAULT_MODELS;
|
|
3065
3609
|
exports.DEFAULT_PROMPT_STRATEGY = DEFAULT_PROMPT_STRATEGY;
|
|
3066
3610
|
exports.DEFAULT_RETRY_BACKOFF_MULTIPLIER = DEFAULT_RETRY_BACKOFF_MULTIPLIER;
|
|
3067
3611
|
exports.DEFAULT_RETRY_INITIAL_DELAY_MS = DEFAULT_RETRY_INITIAL_DELAY_MS;
|
|
@@ -3076,6 +3620,9 @@ exports.GROQ_MODELS = GROQ_MODELS;
|
|
|
3076
3620
|
exports.GROQ_TIERS = GROQ_TIERS;
|
|
3077
3621
|
exports.GeminiProvider = GeminiProvider;
|
|
3078
3622
|
exports.GroqChatRequestBuilder = GroqChatRequestBuilder;
|
|
3623
|
+
exports.GroqConfigStore = GroqConfigStore;
|
|
3624
|
+
exports.GroqError = GroqError;
|
|
3625
|
+
exports.GroqErrorType = AIErrorType;
|
|
3079
3626
|
exports.GroqHttpClient = GroqHttpClient;
|
|
3080
3627
|
exports.GroqHttpTransport = GroqHttpTransport;
|
|
3081
3628
|
exports.GroqProvider = GroqProvider;
|
|
@@ -3096,6 +3643,8 @@ exports.SSE_PREFIX = SSE_PREFIX;
|
|
|
3096
3643
|
exports.StreamingResponseParser = StreamingResponseParser;
|
|
3097
3644
|
exports.StructuredPromptBuilder = StructuredPromptBuilder;
|
|
3098
3645
|
exports.TEXT_TIERS = TEXT_TIERS;
|
|
3646
|
+
exports.TIMEOUTS = TIMEOUTS;
|
|
3647
|
+
exports.TextGenerationService = TextGenerationService;
|
|
3099
3648
|
exports.ThrottleManager = ThrottleManager;
|
|
3100
3649
|
exports.USER_FRIENDLY_ERROR_MESSAGES = USER_FRIENDLY_ERROR_MESSAGES;
|
|
3101
3650
|
exports.asObjectArray = asObjectArray;
|
|
@@ -3108,13 +3657,18 @@ exports.cacheManager = cacheManager;
|
|
|
3108
3657
|
exports.chatIdGenerator = chatIdGenerator;
|
|
3109
3658
|
exports.clampScore = clampScore;
|
|
3110
3659
|
exports.classifyHttpStatus = classifyHttpStatus;
|
|
3660
|
+
exports.configureProvider = configureProvider;
|
|
3111
3661
|
exports.consumeAnthropicStream = consumeAnthropicStream;
|
|
3112
3662
|
exports.consumeGroqStream = consumeGroqStream;
|
|
3113
3663
|
exports.createAI = createAI;
|
|
3664
|
+
exports.createAssistantMessage = createAssistantMessage;
|
|
3114
3665
|
exports.createFalProvider = createFalProvider;
|
|
3115
3666
|
exports.createGeminiProvider = createGeminiProvider;
|
|
3667
|
+
exports.createMessage = createMessage;
|
|
3116
3668
|
exports.createPrunaProvider = createPrunaProvider;
|
|
3117
3669
|
exports.createSseResponse = createSseResponse;
|
|
3670
|
+
exports.createSystemMessage = createSystemMessage;
|
|
3671
|
+
exports.createUserMessage = createUserMessage;
|
|
3118
3672
|
exports.debounce = debounce;
|
|
3119
3673
|
exports.debounceManager = debounceManager;
|
|
3120
3674
|
exports.defaultEffortForModel = defaultEffortForModel;
|
|
@@ -3122,13 +3676,17 @@ exports.describeAIErrorType = describeAIErrorType;
|
|
|
3122
3676
|
exports.extractContentFromSsePayload = extractContentFromSsePayload;
|
|
3123
3677
|
exports.extractErrorMessageFromJsonBody = extractErrorMessageFromJsonBody;
|
|
3124
3678
|
exports.extractErrorMessageFromResponse = extractErrorMessageFromResponse;
|
|
3679
|
+
exports.extractJsonArray = extractJsonArray;
|
|
3125
3680
|
exports.extractJsonCandidate = extractJsonCandidate;
|
|
3126
3681
|
exports.extractJsonFromCodeFence = extractJsonFromCodeFence;
|
|
3127
3682
|
exports.extractJsonObject = extractJsonObject;
|
|
3128
3683
|
exports.extractSseDataPayload = extractSseDataPayload;
|
|
3684
|
+
exports.extractTextFromMessages = extractTextFromMessages;
|
|
3129
3685
|
exports.extractTokenUsage = extractTokenUsage;
|
|
3130
3686
|
exports.formatErrorForLogging = formatErrorForLogging;
|
|
3687
|
+
exports.formatMessagesForDisplay = formatMessagesForDisplay;
|
|
3131
3688
|
exports.generateWithPruna = generateWithPruna;
|
|
3689
|
+
exports.getProvider = getProvider;
|
|
3132
3690
|
exports.isAuthErrorType = isAuthErrorType;
|
|
3133
3691
|
exports.isMediaProvider = isMediaProvider;
|
|
3134
3692
|
exports.isRetryableErrorType = isRetryableErrorType;
|
|
@@ -3142,8 +3700,12 @@ exports.mergeTierOverrides = mergeTierOverrides;
|
|
|
3142
3700
|
exports.messageFormatter = messageFormatter;
|
|
3143
3701
|
exports.normalizeSseChunk = normalizeSseChunk;
|
|
3144
3702
|
exports.oneOfCatalog = oneOfCatalog;
|
|
3703
|
+
exports.promptToMessages = promptToMessages;
|
|
3704
|
+
exports.repairCommonJsonDefects = repairCommonJsonDefects;
|
|
3145
3705
|
exports.requestDeduplicator = requestDeduplicator;
|
|
3146
3706
|
exports.requestQueue = requestQueue;
|
|
3707
|
+
exports.requestStructuredJson = requestStructuredJson;
|
|
3708
|
+
exports.resetProvider = resetProvider;
|
|
3147
3709
|
exports.resolveModel = resolveModel;
|
|
3148
3710
|
exports.resolveUserFriendlyErrorMessage = resolveUserFriendlyErrorMessage;
|
|
3149
3711
|
exports.resolveUserFriendlyMessage = resolveUserFriendlyMessage;
|