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