@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
@@ -8,25 +8,49 @@ function isMediaProvider(provider) {
8
8
  return provider.capabilities.includes("image") || provider.capabilities.includes("video");
9
9
  }
10
10
 
11
- // src/content/domain/errors/AIErrors.ts
12
- var AIError = class _AIError extends Error {
13
- code;
14
- cause;
15
- constructor(message, code, cause) {
16
- super(message);
17
- this.name = "AIError";
18
- this.code = code;
19
- this.cause = cause;
20
- }
21
- static from(error, fallbackCode = "UNKNOWN") {
22
- if (error instanceof _AIError) return error;
23
- if (error instanceof Error) {
24
- return new _AIError(error.message, mapMessageToCode(error.message, fallbackCode), error);
25
- }
26
- return new _AIError(String(error), fallbackCode, error);
11
+ // src/core/errors/ai-error-types.ts
12
+ var AIErrorType = /* @__PURE__ */ ((AIErrorType2) => {
13
+ AIErrorType2["INVALID_API_KEY"] = "INVALID_API_KEY";
14
+ AIErrorType2["MISSING_CONFIG"] = "MISSING_CONFIG";
15
+ AIErrorType2["NETWORK_ERROR"] = "NETWORK_ERROR";
16
+ AIErrorType2["ABORT_ERROR"] = "ABORT_ERROR";
17
+ AIErrorType2["RATE_LIMIT_ERROR"] = "RATE_LIMIT_ERROR";
18
+ AIErrorType2["SERVER_ERROR"] = "SERVER_ERROR";
19
+ AIErrorType2["CLIENT_ERROR"] = "CLIENT_ERROR";
20
+ AIErrorType2["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
21
+ return AIErrorType2;
22
+ })(AIErrorType || {});
23
+
24
+ // src/core/errors/ai-error.ts
25
+ var KNOWN_ERROR_TYPES = new Set(Object.values(AIErrorType));
26
+ function mapCodeToType(code) {
27
+ switch (code) {
28
+ case "VALIDATION_ERROR":
29
+ case "CLIENT_ERROR":
30
+ return "CLIENT_ERROR" /* CLIENT_ERROR */;
31
+ case "INVALID_API_KEY":
32
+ return "INVALID_API_KEY" /* INVALID_API_KEY */;
33
+ case "MISSING_CONFIG":
34
+ case "PROVIDER_UNAVAILABLE":
35
+ return "MISSING_CONFIG" /* MISSING_CONFIG */;
36
+ case "PROVIDER_QUOTA_EXHAUSTED":
37
+ case "RATE_LIMIT_ERROR":
38
+ return "RATE_LIMIT_ERROR" /* RATE_LIMIT_ERROR */;
39
+ case "NETWORK_ERROR":
40
+ case "TIMEOUT":
41
+ return "NETWORK_ERROR" /* NETWORK_ERROR */;
42
+ case "ABORT_ERROR":
43
+ case "ABORTED":
44
+ return "ABORT_ERROR" /* ABORT_ERROR */;
45
+ case "SERVER_ERROR":
46
+ case "PROVIDER_ERROR":
47
+ case "NO_RESULT":
48
+ return "SERVER_ERROR" /* SERVER_ERROR */;
49
+ default:
50
+ return "UNKNOWN_ERROR" /* UNKNOWN_ERROR */;
27
51
  }
28
- };
29
- function mapMessageToCode(message, fallback) {
52
+ }
53
+ function mapMessageToCode(message, fallback = "UNKNOWN") {
30
54
  const lower = message.toLowerCase();
31
55
  if (lower.includes("validation")) return "VALIDATION_ERROR";
32
56
  if (lower.includes("quota")) return "PROVIDER_QUOTA_EXHAUSTED";
@@ -39,6 +63,53 @@ function mapMessageToCode(message, fallback) {
39
63
  if (lower.includes("network") || lower.includes("fetch")) return "NETWORK_ERROR";
40
64
  return fallback;
41
65
  }
66
+ var AIError = class _AIError extends Error {
67
+ type;
68
+ code;
69
+ cause;
70
+ metadata;
71
+ constructor(typeOrMessage, messageOrCode, cause, metadata = {}) {
72
+ let effectiveType;
73
+ let effectiveMessage;
74
+ let effectiveCode;
75
+ if (KNOWN_ERROR_TYPES.has(typeOrMessage)) {
76
+ effectiveType = typeOrMessage;
77
+ effectiveMessage = messageOrCode ?? "";
78
+ effectiveCode = effectiveType;
79
+ } else {
80
+ effectiveMessage = typeOrMessage;
81
+ effectiveCode = messageOrCode ?? "UNKNOWN";
82
+ effectiveType = mapCodeToType(effectiveCode);
83
+ }
84
+ super(effectiveMessage);
85
+ this.name = "AIError";
86
+ this.type = effectiveType;
87
+ this.code = effectiveCode;
88
+ this.cause = cause;
89
+ this.metadata = metadata;
90
+ }
91
+ static from(error, fallbackCode = "UNKNOWN") {
92
+ if (error instanceof _AIError) return error;
93
+ if (error instanceof Error) {
94
+ const code = mapMessageToCode(error.message, fallbackCode);
95
+ return new _AIError(error.message, code, error);
96
+ }
97
+ return new _AIError(String(error), fallbackCode, error);
98
+ }
99
+ toString() {
100
+ const statusPart = typeof this.metadata.status === "number" ? ` (HTTP ${this.metadata.status})` : "";
101
+ return `${this.name} [${this.type}]: ${this.message}${statusPart}`;
102
+ }
103
+ toJSON() {
104
+ return {
105
+ name: this.name,
106
+ type: this.type,
107
+ code: this.code,
108
+ message: this.message,
109
+ metadata: this.metadata
110
+ };
111
+ }
112
+ };
42
113
 
43
114
  // src/content/domain/limits/ProviderTimingConfig.ts
44
115
  var ProviderTimingConfig = {
@@ -113,29 +184,11 @@ var ProviderError = class extends AIError {
113
184
  providerId;
114
185
  };
115
186
 
116
- // src/core/errors/ai-error.ts
117
- var AIError2 = class extends Error {
118
- type;
119
- cause;
120
- metadata;
187
+ // src/core/errors/groq-error.ts
188
+ var GroqError = class extends AIError {
121
189
  constructor(type, message, cause, metadata = {}) {
122
- super(message);
123
- this.name = "AIError";
124
- this.type = type;
125
- this.cause = cause;
126
- this.metadata = metadata;
127
- }
128
- toString() {
129
- const statusPart = typeof this.metadata.status === "number" ? ` (HTTP ${this.metadata.status})` : "";
130
- return `${this.name} [${this.type}]: ${this.message}${statusPart}`;
131
- }
132
- toJSON() {
133
- return {
134
- name: this.name,
135
- type: this.type,
136
- message: this.message,
137
- metadata: this.metadata
138
- };
190
+ super(type, message, cause, metadata);
191
+ this.name = "GroqError";
139
192
  }
140
193
  };
141
194
 
@@ -264,7 +317,7 @@ var ProviderFactory = class {
264
317
  }
265
318
  }
266
319
  }
267
- const failure = new AIError2(
320
+ const failure = new AIError(
268
321
  "SERVER_ERROR" /* SERVER_ERROR */,
269
322
  `All providers failed for capability 'text'`,
270
323
  lastError instanceof Error ? lastError : void 0
@@ -278,12 +331,16 @@ var ProviderFactory = class {
278
331
  let wake = null;
279
332
  let finished = false;
280
333
  let failure;
334
+ const controller = new AbortController();
335
+ const onAbort = () => controller.abort();
336
+ request.signal?.addEventListener("abort", onAbort);
337
+ const effectiveRequest = { ...request, signal: controller.signal };
281
338
  const notify = () => {
282
339
  const resolve = wake;
283
340
  wake = null;
284
341
  resolve?.();
285
342
  };
286
- const completion = this.chatStream(request, {
343
+ const completion = this.chatStream(effectiveRequest, {
287
344
  onChunk: (chunk) => {
288
345
  queue.push(chunk);
289
346
  notify();
@@ -299,18 +356,23 @@ var ProviderFactory = class {
299
356
  notify();
300
357
  }
301
358
  );
302
- while (!finished || queue.length > 0) {
303
- if (queue.length === 0 && !finished) {
304
- await new Promise((resolve) => {
305
- wake = resolve;
306
- });
307
- }
308
- while (queue.length > 0) {
309
- yield queue.shift();
359
+ try {
360
+ while (!finished || queue.length > 0) {
361
+ if (queue.length === 0 && !finished) {
362
+ await new Promise((resolve) => {
363
+ wake = resolve;
364
+ });
365
+ }
366
+ while (queue.length > 0) {
367
+ yield queue.shift();
368
+ }
369
+ if (failure) throw failure;
310
370
  }
311
- if (failure) throw failure;
371
+ await completion;
372
+ } finally {
373
+ controller.abort();
374
+ request.signal?.removeEventListener("abort", onAbort);
312
375
  }
313
- await completion;
314
376
  }
315
377
  async generateJson(request) {
316
378
  const effective = request.model || request.tier ? request : { ...request, tier: this.defaultTier };
@@ -418,7 +480,7 @@ var ProviderFactory = class {
418
480
  }
419
481
  }
420
482
  }
421
- throw new AIError2(
483
+ throw new AIError(
422
484
  "SERVER_ERROR" /* SERVER_ERROR */,
423
485
  `All providers failed for capability '${capability}'`,
424
486
  lastError instanceof Error ? lastError : void 0
@@ -447,7 +509,7 @@ var ProviderFactory = class {
447
509
  }
448
510
  }
449
511
  noProviderError(capability) {
450
- return new AIError2(
512
+ return new AIError(
451
513
  "MISSING_CONFIG" /* MISSING_CONFIG */,
452
514
  `No provider registered for capability '${capability}' \u2014 create one with createAI() and include its config block`
453
515
  );
@@ -457,24 +519,81 @@ var ProviderFactory = class {
457
519
  // src/core/constants/protocol.constants.ts
458
520
  var SSE_PREFIX = "data: ";
459
521
  var SSE_DONE_MARKER = "[DONE]";
460
- var JSON_CODE_BLOCK_PATTERN = /```json\n([\s\S]*?)\n```/;
522
+ var JSON_CODE_BLOCK_PATTERN = /```(?:json)?\s*\n?([\s\S]*?)\n?```/;
461
523
  var JSON_OBJECT_PATTERN = /\{[\s\S]*\}/;
524
+ var JSON_ARRAY_PATTERN = /\[[\s\S]*\]/;
462
525
 
463
526
  // src/core/parsers/sse-lines.ts
464
527
  function isSseDataLine(line) {
465
- return line.startsWith(SSE_PREFIX);
528
+ return line.startsWith(SSE_PREFIX) || line.startsWith("data:");
466
529
  }
467
530
  function extractSseDataPayload(line) {
468
- return line.slice(SSE_PREFIX.length);
531
+ if (line.startsWith(SSE_PREFIX)) {
532
+ return line.slice(SSE_PREFIX.length);
533
+ }
534
+ if (line.startsWith("data:")) {
535
+ return line.slice(5);
536
+ }
537
+ return line;
469
538
  }
470
539
  function isSseDoneMarker(payload) {
471
540
  return payload === SSE_DONE_MARKER;
472
541
  }
473
542
 
543
+ // src/core/parsers/streaming-response.parser.ts
544
+ var StreamingResponseParser = class {
545
+ constructor(callbacks, extractDelta) {
546
+ this.callbacks = callbacks;
547
+ this.extractDelta = extractDelta;
548
+ }
549
+ callbacks;
550
+ extractDelta;
551
+ decoder = new TextDecoder();
552
+ async parse(stream) {
553
+ const reader = stream.getReader();
554
+ const contentChunks = [];
555
+ let buffer = "";
556
+ const consumeLine = (rawLine) => {
557
+ const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
558
+ const trimmed = line.trim();
559
+ if (trimmed.length === 0 || !isSseDataLine(trimmed)) return;
560
+ const payload = extractSseDataPayload(trimmed);
561
+ if (isSseDoneMarker(payload)) return;
562
+ const content = this.extractDelta(payload);
563
+ if (content !== null) {
564
+ contentChunks.push(content);
565
+ this.callbacks.onChunk(content);
566
+ }
567
+ };
568
+ try {
569
+ while (true) {
570
+ const { done, value } = await reader.read();
571
+ if (done) break;
572
+ buffer += this.decoder.decode(value, { stream: true });
573
+ const lines = buffer.split("\n");
574
+ buffer = lines.pop() ?? "";
575
+ for (const line of lines) consumeLine(line);
576
+ }
577
+ buffer += this.decoder.decode();
578
+ if (buffer.length > 0) consumeLine(buffer);
579
+ } catch (error) {
580
+ if (error instanceof AIError) throw error;
581
+ throw new AIError(
582
+ "NETWORK_ERROR" /* NETWORK_ERROR */,
583
+ "Stream was interrupted",
584
+ error instanceof Error ? error : void 0
585
+ );
586
+ } finally {
587
+ reader.releaseLock();
588
+ }
589
+ return contentChunks.join("");
590
+ }
591
+ };
592
+
474
593
  // src/core/parsers/json-content-extractor.ts
475
594
  function extractJsonFromCodeFence(content) {
476
595
  const match = content.match(JSON_CODE_BLOCK_PATTERN);
477
- if (match && match[1]) return match[1];
596
+ if (match && match[1]) return match[1].trim();
478
597
  return null;
479
598
  }
480
599
  function extractJsonObject(content) {
@@ -482,8 +601,27 @@ function extractJsonObject(content) {
482
601
  if (match && match[0]) return match[0];
483
602
  return null;
484
603
  }
604
+ function extractJsonArray(content) {
605
+ const match = content.match(JSON_ARRAY_PATTERN);
606
+ if (match && match[0]) return match[0];
607
+ return null;
608
+ }
609
+ function repairCommonJsonDefects(text) {
610
+ return text.replace(/(:\s*-?\d+(?:\.\d+)?)\s*"/g, "$1").replace(/(:\s*"[^"]*")"/g, "$1");
611
+ }
485
612
  function extractJsonCandidate(content) {
486
- return extractJsonFromCodeFence(content) ?? extractJsonObject(content) ?? content;
613
+ const fromFence = extractJsonFromCodeFence(content);
614
+ if (fromFence) return fromFence;
615
+ const objectIndex = content.indexOf("{");
616
+ const arrayIndex = content.indexOf("[");
617
+ if (objectIndex !== -1 && (arrayIndex === -1 || objectIndex < arrayIndex)) {
618
+ const obj = extractJsonObject(content);
619
+ if (obj) return obj;
620
+ } else if (arrayIndex !== -1) {
621
+ const arr = extractJsonArray(content);
622
+ if (arr) return arr;
623
+ }
624
+ return content.trim();
487
625
  }
488
626
 
489
627
  // src/core/parsers/json-response.parser.ts
@@ -492,12 +630,17 @@ var JsonResponseParser = class {
492
630
  const candidate = extractJsonCandidate(rawContent);
493
631
  try {
494
632
  return JSON.parse(candidate);
495
- } catch (error) {
496
- throw new AIError2(
497
- "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
498
- "Failed to parse structured response as JSON",
499
- error instanceof Error ? error : void 0
500
- );
633
+ } catch {
634
+ try {
635
+ return JSON.parse(repairCommonJsonDefects(candidate));
636
+ } catch (error) {
637
+ throw new AIError(
638
+ "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
639
+ "Failed to parse structured response as JSON",
640
+ error instanceof Error ? error : void 0,
641
+ { rawContent }
642
+ );
643
+ }
501
644
  }
502
645
  }
503
646
  };
@@ -623,7 +766,7 @@ var AnthropicHttpTransport = class {
623
766
  });
624
767
  if (!response.ok) await this.throwFromErrorResponse(response);
625
768
  if (!response.body) {
626
- throw new AIError2("NETWORK_ERROR" /* NETWORK_ERROR */, "Response body is null");
769
+ throw new AIError("NETWORK_ERROR" /* NETWORK_ERROR */, "Response body is null");
627
770
  }
628
771
  return response.body;
629
772
  } catch (error) {
@@ -656,7 +799,7 @@ var AnthropicHttpTransport = class {
656
799
  status: response.status,
657
800
  url: response.url
658
801
  };
659
- throw new AIError2(
802
+ throw new AIError(
660
803
  classifyHttpStatus(response.status),
661
804
  errorMessage,
662
805
  void 0,
@@ -664,24 +807,24 @@ var AnthropicHttpTransport = class {
664
807
  );
665
808
  }
666
809
  normalizeError(error) {
667
- if (error instanceof AIError2) return error;
810
+ if (error instanceof AIError) return error;
668
811
  if (error instanceof Error) {
669
812
  if (error.name === "AbortError") {
670
- return new AIError2(
813
+ return new AIError(
671
814
  "ABORT_ERROR" /* ABORT_ERROR */,
672
815
  "Request was aborted by the client",
673
816
  error
674
817
  );
675
818
  }
676
819
  if (error.name === "TypeError" && error.message.toLowerCase().includes("network")) {
677
- return new AIError2(
820
+ return new AIError(
678
821
  "NETWORK_ERROR" /* NETWORK_ERROR */,
679
822
  "Network error: Unable to connect to the AI service",
680
823
  error
681
824
  );
682
825
  }
683
826
  }
684
- return new AIError2(
827
+ return new AIError(
685
828
  "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
686
829
  error instanceof Error ? error.message : "Unknown error occurred",
687
830
  error instanceof Error ? error : void 0
@@ -811,11 +954,14 @@ async function consumeAnthropicStream(stream, callbacks) {
811
954
  break;
812
955
  case "message_stop":
813
956
  break;
814
- case "error":
815
- throw new AIError2(
816
- event.error.type === "rate_limit_error" ? "RATE_LIMIT_ERROR" /* RATE_LIMIT_ERROR */ : "SERVER_ERROR" /* SERVER_ERROR */,
957
+ case "error": {
958
+ const errType = event.error.type;
959
+ 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 */;
960
+ throw new AIError(
961
+ mappedType,
817
962
  event.error.message || "Anthropic stream failed mid-flight"
818
963
  );
964
+ }
819
965
  }
820
966
  };
821
967
  try {
@@ -830,8 +976,8 @@ async function consumeAnthropicStream(stream, callbacks) {
830
976
  buffer += decoder.decode();
831
977
  if (buffer.length > 0) consumeLine(buffer);
832
978
  } catch (error) {
833
- if (error instanceof AIError2) throw error;
834
- throw new AIError2(
979
+ if (error instanceof AIError) throw error;
980
+ throw new AIError(
835
981
  "NETWORK_ERROR" /* NETWORK_ERROR */,
836
982
  "Stream was interrupted",
837
983
  error instanceof Error ? error : void 0
@@ -893,7 +1039,7 @@ var AnthropicProvider = class {
893
1039
  const messages = [...request.messages];
894
1040
  const lastUserIndex = findLastIndex(messages, (m) => m.role === "user");
895
1041
  if (lastUserIndex === -1) {
896
- throw new AIError2(
1042
+ throw new AIError(
897
1043
  "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
898
1044
  "generateStructured requires at least one user message"
899
1045
  );
@@ -948,7 +1094,7 @@ var AnthropicProvider = class {
948
1094
  finishReason
949
1095
  };
950
1096
  }
951
- throw new AIError2(
1097
+ throw new AIError(
952
1098
  "SERVER_ERROR" /* SERVER_ERROR */,
953
1099
  "No content generated from Anthropic API",
954
1100
  void 0,
@@ -1102,6 +1248,12 @@ function calculateExponentialBackoff(params) {
1102
1248
  }
1103
1249
 
1104
1250
  // src/core/constants/identifier.constants.ts
1251
+ var MESSAGE_ID_PREFIX = "msg-";
1252
+ var CHAT_MESSAGE_ID_SUFFIX_LENGTH = 9;
1253
+ var CACHE_KEY_TYPE_COMPLETION = "completion";
1254
+ var CACHE_KEY_TYPE_CHAT = "chat";
1255
+ var USER_ROLE = "user";
1256
+ var ASSISTANT_ROLE = "assistant";
1105
1257
  var QUEUE_PRIORITY_USER_REQUEST = 10;
1106
1258
  var DEFAULT_RETRY_MAX_ATTEMPTS = 3;
1107
1259
  var DEFAULT_RETRY_INITIAL_DELAY_MS = 1e3;
@@ -1153,7 +1305,7 @@ var RetryManager = class {
1153
1305
  }
1154
1306
  shouldRetry(error, options) {
1155
1307
  if (options.shouldRetry) return options.shouldRetry(error);
1156
- if (error instanceof AIError2) {
1308
+ if (error instanceof AIError) {
1157
1309
  return isRetryableErrorType(error.type, DEFAULT_ERROR_CLASSIFICATION_RULE);
1158
1310
  }
1159
1311
  const lower = error.message.toLowerCase();
@@ -1275,6 +1427,27 @@ var RequestDeduplicator = class {
1275
1427
  }
1276
1428
  };
1277
1429
 
1430
+ // src/core/utils/api-key-validator.ts
1431
+ var DEFAULT_API_KEY_RULE = {
1432
+ minLength: 10
1433
+ };
1434
+ function validateApiKey(apiKey, rule = DEFAULT_API_KEY_RULE) {
1435
+ if (!apiKey) {
1436
+ return { valid: false, reason: "API key is required" };
1437
+ }
1438
+ const trimmed = apiKey.trim();
1439
+ if (trimmed.length === 0) {
1440
+ return { valid: false, reason: "API key cannot be empty" };
1441
+ }
1442
+ if (trimmed.length < rule.minLength) {
1443
+ return {
1444
+ valid: false,
1445
+ reason: `API key must be at least ${rule.minLength} characters`
1446
+ };
1447
+ }
1448
+ return { valid: true };
1449
+ }
1450
+
1278
1451
  // src/providers/groq/groq.constants.ts
1279
1452
  var GROQ_MODELS = {
1280
1453
  LLAMA_3_1_8B_INSTANT: "llama-3.1-8b-instant",
@@ -1298,12 +1471,22 @@ var DEFAULT_GENERATION_CONFIG = {
1298
1471
  maxTokens: 1024,
1299
1472
  topP: 1
1300
1473
  };
1474
+ var DEFAULT_MODELS = {
1475
+ TEXT: GROQ_MODELS.LLAMA_3_1_8B_INSTANT,
1476
+ FAST: GROQ_MODELS.LLAMA_3_1_8B_INSTANT,
1477
+ EXPERIMENTAL: GROQ_MODELS.GPT_OSS_20B
1478
+ };
1301
1479
  var GROQ_BASE_URL = "https://api.groq.com/openai/v1";
1480
+ var DEFAULT_BASE_URL = GROQ_BASE_URL;
1302
1481
  var CHAT_COMPLETIONS_PATH = "/chat/completions";
1482
+ var API_ENDPOINTS = {
1483
+ CHAT: CHAT_COMPLETIONS_PATH
1484
+ };
1303
1485
  var GROQ_TIMEOUTS = {
1304
1486
  DEFAULT: 3e4,
1305
1487
  STREAMING: 6e4
1306
1488
  };
1489
+ var TIMEOUTS = GROQ_TIMEOUTS;
1307
1490
  var HTTP_HEADERS = {
1308
1491
  CONTENT_TYPE: "Content-Type",
1309
1492
  APPLICATION_JSON: "application/json",
@@ -1362,13 +1545,65 @@ var GroqChatRequestBuilder = class _GroqChatRequestBuilder {
1362
1545
  }
1363
1546
  };
1364
1547
 
1548
+ // src/providers/groq/groq-config-store.ts
1549
+ var GroqConfigStore = class {
1550
+ config = null;
1551
+ initialize(config) {
1552
+ const validation = validateApiKey(config.apiKey, { minLength: 1 });
1553
+ if (!validation.valid) {
1554
+ throw new GroqError("INVALID_API_KEY" /* INVALID_API_KEY */, validation.reason ?? "Invalid API key");
1555
+ }
1556
+ const normalized = {
1557
+ apiKey: config.apiKey.trim(),
1558
+ baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,
1559
+ timeoutMs: config.timeoutMs ?? TIMEOUTS.DEFAULT,
1560
+ ...config.models !== void 0 ? { models: config.models } : {},
1561
+ ...config.textModel !== void 0 ? { textModel: config.textModel } : {}
1562
+ };
1563
+ this.config = normalized;
1564
+ return normalized;
1565
+ }
1566
+ get() {
1567
+ if (!this.config) {
1568
+ throw new GroqError(
1569
+ "MISSING_CONFIG" /* MISSING_CONFIG */,
1570
+ "Client not initialized. Call configureProvider first."
1571
+ );
1572
+ }
1573
+ return this.config;
1574
+ }
1575
+ getOrNull() {
1576
+ return this.config;
1577
+ }
1578
+ isInitialized() {
1579
+ return this.config !== null;
1580
+ }
1581
+ setApiKey(apiKey) {
1582
+ const current = this.get();
1583
+ const validation = validateApiKey(apiKey, { minLength: 1 });
1584
+ if (!validation.valid) {
1585
+ throw new GroqError("INVALID_API_KEY" /* INVALID_API_KEY */, validation.reason ?? "Invalid API key");
1586
+ }
1587
+ this.config = { ...current, apiKey: apiKey.trim() };
1588
+ }
1589
+ reset() {
1590
+ this.config = null;
1591
+ }
1592
+ };
1593
+
1365
1594
  // src/providers/groq/groq-http-transport.ts
1366
1595
  var GroqHttpTransport = class {
1367
- constructor(config) {
1368
- this.config = config;
1596
+ constructor(configSource) {
1597
+ this.configSource = configSource;
1369
1598
  }
1370
- config;
1599
+ configSource;
1371
1600
  pendingAbortControllers = /* @__PURE__ */ new Set();
1601
+ getConfig() {
1602
+ if ("get" in this.configSource && typeof this.configSource.get === "function") {
1603
+ return this.configSource.get();
1604
+ }
1605
+ return this.configSource;
1606
+ }
1372
1607
  cancelPendingRequests() {
1373
1608
  for (const controller of this.pendingAbortControllers) {
1374
1609
  controller.abort();
@@ -1383,7 +1618,7 @@ var GroqHttpTransport = class {
1383
1618
  }
1384
1619
  async streamChatCompletion(request, options = {}) {
1385
1620
  const url = `${this.baseUrl()}${CHAT_COMPLETIONS_PATH}`;
1386
- const timeout = this.config.timeoutMs ?? GROQ_TIMEOUTS.STREAMING;
1621
+ const timeout = this.getConfig().timeoutMs ?? GROQ_TIMEOUTS.STREAMING;
1387
1622
  const controller = new AbortController();
1388
1623
  const timeoutId = setTimeout(() => controller.abort(), timeout);
1389
1624
  const onExternalAbort = () => controller.abort();
@@ -1398,7 +1633,7 @@ var GroqHttpTransport = class {
1398
1633
  });
1399
1634
  if (!response.ok) await this.throwFromErrorResponse(response);
1400
1635
  if (!response.body) {
1401
- throw new AIError2("NETWORK_ERROR" /* NETWORK_ERROR */, "Response body is null");
1636
+ throw new AIError("NETWORK_ERROR" /* NETWORK_ERROR */, "Response body is null");
1402
1637
  }
1403
1638
  return response.body;
1404
1639
  } catch (error) {
@@ -1410,11 +1645,11 @@ var GroqHttpTransport = class {
1410
1645
  }
1411
1646
  }
1412
1647
  baseUrl() {
1413
- return this.config.baseUrl ?? GROQ_BASE_URL;
1648
+ return this.getConfig().baseUrl ?? GROQ_BASE_URL;
1414
1649
  }
1415
1650
  async request(endpoint, body) {
1416
1651
  const url = `${this.baseUrl()}${endpoint}`;
1417
- const timeout = this.config.timeoutMs ?? GROQ_TIMEOUTS.DEFAULT;
1652
+ const timeout = this.getConfig().timeoutMs ?? GROQ_TIMEOUTS.DEFAULT;
1418
1653
  const controller = new AbortController();
1419
1654
  const timeoutId = setTimeout(() => controller.abort(), timeout);
1420
1655
  this.pendingAbortControllers.add(controller);
@@ -1437,7 +1672,7 @@ var GroqHttpTransport = class {
1437
1672
  buildHeaders() {
1438
1673
  return {
1439
1674
  [HTTP_HEADERS.CONTENT_TYPE]: HTTP_HEADERS.APPLICATION_JSON,
1440
- [HTTP_HEADERS.AUTHORIZATION]: `${HTTP_HEADERS.BEARER_PREFIX}${this.config.apiKey}`
1675
+ [HTTP_HEADERS.AUTHORIZATION]: `${HTTP_HEADERS.BEARER_PREFIX}${this.getConfig().apiKey}`
1441
1676
  };
1442
1677
  }
1443
1678
  async throwFromErrorResponse(response) {
@@ -1446,7 +1681,7 @@ var GroqHttpTransport = class {
1446
1681
  status: response.status,
1447
1682
  url: response.url
1448
1683
  };
1449
- throw new AIError2(
1684
+ throw new AIError(
1450
1685
  classifyHttpStatus(response.status),
1451
1686
  errorMessage,
1452
1687
  void 0,
@@ -1454,24 +1689,24 @@ var GroqHttpTransport = class {
1454
1689
  );
1455
1690
  }
1456
1691
  normalizeError(error) {
1457
- if (error instanceof AIError2) return error;
1692
+ if (error instanceof AIError) return error;
1458
1693
  if (error instanceof Error) {
1459
1694
  if (error.name === "AbortError") {
1460
- return new AIError2(
1695
+ return new AIError(
1461
1696
  "ABORT_ERROR" /* ABORT_ERROR */,
1462
1697
  "Request was aborted by the client",
1463
1698
  error
1464
1699
  );
1465
1700
  }
1466
1701
  if (error.name === "TypeError" && error.message.toLowerCase().includes("network")) {
1467
- return new AIError2(
1702
+ return new AIError(
1468
1703
  "NETWORK_ERROR" /* NETWORK_ERROR */,
1469
1704
  "Network error: Unable to connect to the AI service",
1470
1705
  error
1471
1706
  );
1472
1707
  }
1473
1708
  }
1474
- return new AIError2(
1709
+ return new AIError(
1475
1710
  "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
1476
1711
  error instanceof Error ? error.message : "Unknown error occurred",
1477
1712
  error instanceof Error ? error : void 0
@@ -1539,21 +1774,40 @@ var CompositeExecutor = class {
1539
1774
 
1540
1775
  // src/providers/groq/groq-http-client.ts
1541
1776
  var GroqHttpClient = class {
1777
+ configStore;
1542
1778
  transport;
1543
1779
  executor;
1544
- constructor(config, deps = {}) {
1545
- this.transport = deps.transport ?? new GroqHttpTransport(config);
1780
+ constructor(configOrDeps, maybeDeps = {}) {
1781
+ const isConfig = typeof configOrDeps === "object" && configOrDeps !== null && "apiKey" in configOrDeps && typeof configOrDeps.apiKey === "string";
1782
+ const deps = isConfig ? maybeDeps : configOrDeps ?? {};
1783
+ this.configStore = deps.configStore ?? new GroqConfigStore();
1784
+ if (isConfig) {
1785
+ this.configStore.initialize(configOrDeps);
1786
+ }
1787
+ this.transport = deps.transport ?? new GroqHttpTransport(this.configStore);
1546
1788
  const retryManager2 = deps.retryManager ?? new RetryManager();
1547
1789
  const queue = deps.queue ?? new RequestQueue();
1548
1790
  const deduplicator = deps.deduplicator ?? new RequestDeduplicator();
1549
1791
  this.executor = new CompositeExecutor([
1550
1792
  new DedupeExecutor(deduplicator, {
1551
- generateKey: (request) => deduplicatorKey(request, config.apiKey)
1793
+ generateKey: (request) => deduplicatorKey(request, this.configStore.isInitialized() ? this.configStore.get().apiKey : "")
1552
1794
  }),
1553
1795
  new RetryExecutor(retryManager2),
1554
1796
  new QueueExecutor(queue, QUEUE_PRIORITY_USER_REQUEST)
1555
1797
  ]);
1556
1798
  }
1799
+ initialize(config) {
1800
+ this.configStore.initialize(config);
1801
+ }
1802
+ isInitialized() {
1803
+ return this.configStore.isInitialized();
1804
+ }
1805
+ getApiKey() {
1806
+ return this.configStore.get().apiKey;
1807
+ }
1808
+ setApiKey(apiKey) {
1809
+ this.configStore.setApiKey(apiKey);
1810
+ }
1557
1811
  cancelPendingRequests() {
1558
1812
  this.transport.cancelPendingRequests();
1559
1813
  }
@@ -1566,6 +1820,10 @@ var GroqHttpClient = class {
1566
1820
  streamChatCompletion(request, options) {
1567
1821
  return this.transport.streamChatCompletion(request, options);
1568
1822
  }
1823
+ reset() {
1824
+ this.transport.cancelPendingRequests();
1825
+ this.configStore.reset();
1826
+ }
1569
1827
  };
1570
1828
  function deduplicatorKey(request, apiKey) {
1571
1829
  const { model, messages, stream: _stream, ...rest } = request;
@@ -1622,6 +1880,13 @@ async function consumeGroqStream(stream, callbacks) {
1622
1880
  } catch {
1623
1881
  return;
1624
1882
  }
1883
+ const errorBody = chunk.error;
1884
+ if (errorBody) {
1885
+ throw new AIError(
1886
+ errorBody.message?.toLowerCase().includes("rate limit") ? "RATE_LIMIT_ERROR" /* RATE_LIMIT_ERROR */ : "SERVER_ERROR" /* SERVER_ERROR */,
1887
+ errorBody.message || "Groq stream failed mid-flight"
1888
+ );
1889
+ }
1625
1890
  if (chunk.model) model = chunk.model;
1626
1891
  const choice = chunk.choices?.[0];
1627
1892
  const delta = choice?.delta?.content;
@@ -1636,13 +1901,6 @@ async function consumeGroqStream(stream, callbacks) {
1636
1901
  if (tailUsage) {
1637
1902
  usage = mapGroqUsage(tailUsage);
1638
1903
  }
1639
- const errorBody = chunk.error;
1640
- if (errorBody) {
1641
- throw new AIError2(
1642
- "SERVER_ERROR" /* SERVER_ERROR */,
1643
- errorBody.message || "Groq stream failed mid-flight"
1644
- );
1645
- }
1646
1904
  };
1647
1905
  try {
1648
1906
  while (true) {
@@ -1656,8 +1914,8 @@ async function consumeGroqStream(stream, callbacks) {
1656
1914
  buffer += decoder.decode();
1657
1915
  if (buffer.length > 0) consumeLine(buffer);
1658
1916
  } catch (error) {
1659
- if (error instanceof AIError2) throw error;
1660
- throw new AIError2(
1917
+ if (error instanceof AIError) throw error;
1918
+ throw new AIError(
1661
1919
  "NETWORK_ERROR" /* NETWORK_ERROR */,
1662
1920
  "Stream was interrupted",
1663
1921
  error instanceof Error ? error : void 0
@@ -1715,7 +1973,7 @@ var GroqProvider = class {
1715
1973
  const choice = response.choices?.[0];
1716
1974
  const text = choice?.message?.content ?? "";
1717
1975
  if (text.length === 0) {
1718
- throw new AIError2(
1976
+ throw new AIError(
1719
1977
  "SERVER_ERROR" /* SERVER_ERROR */,
1720
1978
  "No content generated from Groq API",
1721
1979
  void 0,
@@ -1737,7 +1995,7 @@ var GroqProvider = class {
1737
1995
  const messages = toGroqMessages(request.messages, request.systemPrompt);
1738
1996
  const lastUserIndex = findLastIndex2(messages, (m) => m.role === "user");
1739
1997
  if (lastUserIndex === -1) {
1740
- throw new AIError2(
1998
+ throw new AIError(
1741
1999
  "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
1742
2000
  "generateStructured requires at least one user message"
1743
2001
  );
@@ -1751,7 +2009,7 @@ var GroqProvider = class {
1751
2009
  const choice = response.choices?.[0];
1752
2010
  const text = choice?.message?.content ?? "";
1753
2011
  if (text.length === 0) {
1754
- throw new AIError2(
2012
+ throw new AIError(
1755
2013
  "SERVER_ERROR" /* SERVER_ERROR */,
1756
2014
  "No content generated from Groq API",
1757
2015
  void 0,
@@ -1778,7 +2036,7 @@ var GroqProvider = class {
1778
2036
  try {
1779
2037
  const outcome = await consumeGroqStream(streamBody, callbacks);
1780
2038
  if (outcome.text.length === 0) {
1781
- throw new AIError2(
2039
+ throw new AIError(
1782
2040
  "SERVER_ERROR" /* SERVER_ERROR */,
1783
2041
  "No content generated from Groq API",
1784
2042
  void 0,
@@ -1909,7 +2167,9 @@ var GeminiProvider = class extends BaseProvider {
1909
2167
  headers: this.authHeaders()
1910
2168
  }
1911
2169
  );
1912
- return response.ok ? "healthy" : "unavailable";
2170
+ if (response.ok) return "healthy";
2171
+ if (response.status === 401 || response.status === 403) return "unavailable";
2172
+ return "degraded";
1913
2173
  } catch {
1914
2174
  return "unavailable";
1915
2175
  }
@@ -1920,6 +2180,8 @@ var GeminiProvider = class extends BaseProvider {
1920
2180
  async generate(request) {
1921
2181
  try {
1922
2182
  const model = request.model ?? this.resolveModel(request.tier ?? "balanced");
2183
+ const systemMessages = request.messages.filter((m) => m.role === "system");
2184
+ const systemPrompt = request.systemPrompt && request.systemPrompt.length > 0 ? request.systemPrompt : systemMessages.length > 0 ? systemMessages.map((m) => m.content).join("\n") : void 0;
1923
2185
  const response = await this.withRetry(async () => {
1924
2186
  return await this.fetchWithTimeout(
1925
2187
  `${this.config.baseUrl}/models/${model}:generateContent`,
@@ -1927,24 +2189,30 @@ var GeminiProvider = class extends BaseProvider {
1927
2189
  method: "POST",
1928
2190
  headers: this.authHeaders(),
1929
2191
  body: JSON.stringify({
1930
- systemInstruction: request.systemPrompt && request.systemPrompt.length > 0 ? { parts: [{ text: request.systemPrompt }] } : void 0,
2192
+ systemInstruction: systemPrompt && systemPrompt.length > 0 ? { parts: [{ text: systemPrompt }] } : void 0,
1931
2193
  contents: toGeminiContents(request.messages),
1932
2194
  generationConfig: {
1933
- temperature: request.temperature || 0.7,
1934
- maxOutputTokens: request.maxTokens || 2048,
1935
- topP: request.topP || 0.9
2195
+ temperature: request.temperature ?? 0.7,
2196
+ maxOutputTokens: request.maxTokens ?? 2048,
2197
+ topP: request.topP ?? 0.9
1936
2198
  }
1937
2199
  })
1938
2200
  }
1939
2201
  );
1940
2202
  });
1941
2203
  if (!response.ok) {
1942
- throw new Error(`Gemini API error: ${response.statusText}`);
2204
+ const message = await extractErrorMessageFromResponse(response);
2205
+ throw new AIError(
2206
+ classifyHttpStatus(response.status),
2207
+ `Gemini API error (${response.status}): ${message}`,
2208
+ void 0,
2209
+ { status: response.status, model }
2210
+ );
1943
2211
  }
1944
2212
  const data = await response.json();
1945
- const text = data.candidates[0]?.content?.parts?.map((part) => part.text ?? "").join("") ?? "";
2213
+ const text = data.candidates?.[0]?.content?.parts?.map((part) => part.text ?? "").join("") ?? "";
1946
2214
  if (text.length === 0) {
1947
- throw new AIError2("SERVER_ERROR" /* SERVER_ERROR */, "No content generated from Gemini API", void 0, { model });
2215
+ throw new AIError("SERVER_ERROR" /* SERVER_ERROR */, "No content generated from Gemini API", void 0, { model });
1948
2216
  }
1949
2217
  return {
1950
2218
  text,
@@ -1955,11 +2223,11 @@ var GeminiProvider = class extends BaseProvider {
1955
2223
  } : void 0,
1956
2224
  model,
1957
2225
  providerId: this.id,
1958
- finishReason: mapGeminiFinishReason(data.candidates[0]?.finishReason)
2226
+ finishReason: mapGeminiFinishReason(data.candidates?.[0]?.finishReason)
1959
2227
  };
1960
2228
  } catch (error) {
1961
- if (error instanceof AIError2) throw error;
1962
- throw new AIError2(
2229
+ if (error instanceof AIError) throw error;
2230
+ throw new AIError(
1963
2231
  "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
1964
2232
  `Gemini text generation failed: ${error instanceof Error ? error.message : "Unknown error"}`,
1965
2233
  error instanceof Error ? error : void 0
@@ -1970,7 +2238,7 @@ var GeminiProvider = class extends BaseProvider {
1970
2238
  const messages = [...request.messages];
1971
2239
  const lastUserIndex = findLastIndex3(messages, (m) => m.role === "user");
1972
2240
  if (lastUserIndex === -1) {
1973
- throw new AIError2(
2241
+ throw new AIError(
1974
2242
  "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
1975
2243
  "generateStructured requires at least one user message"
1976
2244
  );
@@ -2007,12 +2275,18 @@ var GeminiProvider = class extends BaseProvider {
2007
2275
  );
2008
2276
  });
2009
2277
  if (!response.ok) {
2010
- throw new Error(`Gemini API error: ${response.statusText}`);
2278
+ const message = await extractErrorMessageFromResponse(response);
2279
+ throw new AIError(
2280
+ classifyHttpStatus(response.status),
2281
+ `Gemini image generation error (${response.status}): ${message}`,
2282
+ void 0,
2283
+ { status: response.status }
2284
+ );
2011
2285
  }
2012
2286
  const data = await response.json();
2013
- const imageData = data.candidates[0]?.content?.parts[0]?.inlineData;
2287
+ const imageData = data.candidates?.[0]?.content?.parts?.[0]?.inlineData;
2014
2288
  if (!imageData) {
2015
- throw new Error("No image data in response");
2289
+ throw new AIError("SERVER_ERROR" /* SERVER_ERROR */, "No image data in Gemini response");
2016
2290
  }
2017
2291
  const url = `data:${imageData.mimeType};base64,${imageData.data}`;
2018
2292
  return {
@@ -2331,17 +2605,70 @@ var PrunaProvider = class {
2331
2605
  async estimateCost(_request) {
2332
2606
  return 1;
2333
2607
  }
2334
- async generateImage(_request) {
2335
- throw new AIError2("UNKNOWN_ERROR" /* UNKNOWN_ERROR */, "Use generateWithPruna instead");
2608
+ async generateImage(request) {
2609
+ let finalUrl;
2610
+ const model = this.config.models?.textToImage;
2611
+ for await (const stage of generateWithPruna(
2612
+ { prompt: request.prompt, model, quality: request.quality },
2613
+ this.config.apiKey
2614
+ )) {
2615
+ if (stage.error) throw stage.error;
2616
+ if (stage.result?.url) finalUrl = stage.result.url;
2617
+ }
2618
+ if (!finalUrl) {
2619
+ throw new AIError("SERVER_ERROR" /* SERVER_ERROR */, "No image generated by Pruna AI");
2620
+ }
2621
+ return {
2622
+ id: Date.now().toString(),
2623
+ type: "image",
2624
+ url: finalUrl,
2625
+ metadata: { provider: this.id, model: model ?? "p-image" },
2626
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
2627
+ };
2336
2628
  }
2337
- async generateVideo(_request) {
2338
- throw new AIError2("UNKNOWN_ERROR" /* UNKNOWN_ERROR */, "Use generateWithPruna instead");
2629
+ async generateVideo(request) {
2630
+ let finalUrl;
2631
+ const model = this.config.models?.textToVideo;
2632
+ for await (const stage of generateWithPruna(
2633
+ { prompt: request.prompt, model, duration: request.duration, aspectRatio: request.aspectRatio },
2634
+ this.config.apiKey
2635
+ )) {
2636
+ if (stage.error) throw stage.error;
2637
+ if (stage.result?.url) finalUrl = stage.result.url;
2638
+ }
2639
+ if (!finalUrl) {
2640
+ throw new AIError("SERVER_ERROR" /* SERVER_ERROR */, "No video generated by Pruna AI");
2641
+ }
2642
+ return {
2643
+ id: Date.now().toString(),
2644
+ type: "video",
2645
+ url: finalUrl,
2646
+ metadata: { provider: this.id, model: model ?? "p-video" },
2647
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
2648
+ };
2339
2649
  }
2340
- async imageToVideo(_request) {
2341
- throw new AIError2("UNKNOWN_ERROR" /* UNKNOWN_ERROR */, "Use generateWithPruna instead");
2650
+ async imageToVideo(request) {
2651
+ let finalUrl;
2652
+ for await (const stage of generateWithPruna(
2653
+ { image: request.imageUrl, prompt: request.prompt, duration: request.duration, motion: request.motion },
2654
+ this.config.apiKey
2655
+ )) {
2656
+ if (stage.error) throw stage.error;
2657
+ if (stage.result?.url) finalUrl = stage.result.url;
2658
+ }
2659
+ if (!finalUrl) {
2660
+ throw new AIError("SERVER_ERROR" /* SERVER_ERROR */, "No video generated from image by Pruna AI");
2661
+ }
2662
+ return {
2663
+ id: Date.now().toString(),
2664
+ type: "video",
2665
+ url: finalUrl,
2666
+ metadata: { provider: this.id, model: "p-image-to-video" },
2667
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
2668
+ };
2342
2669
  }
2343
2670
  async videoToVideo(_request) {
2344
- throw new AIError2("UNKNOWN_ERROR" /* UNKNOWN_ERROR */, "Use generateWithPruna instead");
2671
+ throw new AIError("CLIENT_ERROR" /* CLIENT_ERROR */, "Pruna AI provider does not support video-to-video conversion");
2345
2672
  }
2346
2673
  };
2347
2674
  function createPrunaProvider(config) {
@@ -2373,38 +2700,554 @@ function createAI(config = {}) {
2373
2700
  return factory;
2374
2701
  }
2375
2702
 
2703
+ // src/providers/groq/groq-messages.ts
2704
+ var createUserMessage = (content) => ({
2705
+ role: "user",
2706
+ content
2707
+ });
2708
+ var createAssistantMessage = (content) => ({
2709
+ role: "assistant",
2710
+ content
2711
+ });
2712
+ var createSystemMessage = (content) => ({
2713
+ role: "system",
2714
+ content
2715
+ });
2716
+ var createMessage = (role, content) => ({
2717
+ role,
2718
+ content
2719
+ });
2720
+ var promptToMessages = (prompt) => [
2721
+ createUserMessage(prompt)
2722
+ ];
2723
+ var extractTextFromMessages = (messages) => messages.map((m) => m.content).join("\n\n");
2724
+ var formatMessagesForDisplay = (messages) => messages.map((m) => `[${m.role.toUpperCase()}]: ${m.content}`).join("\n\n---\n\n");
2725
+
2726
+ // src/providers/groq/groq-structured-json.ts
2727
+ async function requestStructuredJson(client, request) {
2728
+ const chatRequest = {
2729
+ model: request.model,
2730
+ messages: [createUserMessage(request.instructions)],
2731
+ temperature: request.temperature,
2732
+ max_tokens: request.maxTokens,
2733
+ response_format: { type: "json_object" },
2734
+ ...request.reasoningEffort !== void 0 ? { reasoning_effort: request.reasoningEffort } : {}
2735
+ };
2736
+ const response = await client.postChatCompletion(chatRequest);
2737
+ const content = response.choices[0]?.message?.content ?? "";
2738
+ const candidate = extractJsonCandidate(content);
2739
+ try {
2740
+ return JSON.parse(candidate);
2741
+ } catch (err) {
2742
+ throw new GroqError(
2743
+ "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
2744
+ "model response contained no parsable json object",
2745
+ err instanceof Error ? err : void 0
2746
+ );
2747
+ }
2748
+ }
2749
+
2750
+ // src/providers/groq/text-generation.service.ts
2751
+ var STRUCTURED_OUTPUT_TEMPERATURE = 0.1;
2752
+ var TextGenerationService = class {
2753
+ constructor(httpClient, cache = new CacheManager(), defaultModel = DEFAULT_MODELS.TEXT) {
2754
+ this.httpClient = httpClient;
2755
+ this.cache = cache;
2756
+ this.defaultModel = defaultModel;
2757
+ }
2758
+ httpClient;
2759
+ cache;
2760
+ defaultModel;
2761
+ id = "groq-text-generation";
2762
+ name = "Groq Text Generation";
2763
+ capabilities = ["text"];
2764
+ jsonParser = new JsonResponseParser();
2765
+ generateCompletion(prompt, options = {}) {
2766
+ const model = options.model ?? this.defaultModel;
2767
+ return this.executeWithCache(
2768
+ {
2769
+ type: CACHE_KEY_TYPE_COMPLETION,
2770
+ model,
2771
+ prompt,
2772
+ config: options.generationConfig
2773
+ },
2774
+ async () => {
2775
+ const request = GroqChatRequestBuilder.for(model).withMessages([createUserMessage(prompt)]).withConfig(options.generationConfig).build();
2776
+ const response = await this.httpClient.postChatCompletion(request);
2777
+ return this.extractContent(response.choices[0]?.message?.content);
2778
+ }
2779
+ );
2780
+ }
2781
+ generateChatCompletion(messages, options = {}) {
2782
+ const model = options.model ?? this.defaultModel;
2783
+ return this.executeWithCache(
2784
+ {
2785
+ type: CACHE_KEY_TYPE_CHAT,
2786
+ model,
2787
+ messages: [...messages],
2788
+ config: options.generationConfig
2789
+ },
2790
+ async () => {
2791
+ const request = GroqChatRequestBuilder.for(model).withMessages(messages).withConfig(options.generationConfig).build();
2792
+ const response = await this.httpClient.postChatCompletion(request);
2793
+ return this.extractContent(response.choices[0]?.message?.content);
2794
+ }
2795
+ );
2796
+ }
2797
+ generateStructured(promptOrRequest, options) {
2798
+ if (typeof promptOrRequest === "string") {
2799
+ const model2 = options?.model ?? this.defaultModel;
2800
+ const jsonPrompt = StructuredPromptBuilder.for(promptOrRequest).withSchema(options?.schema).build();
2801
+ const request = GroqChatRequestBuilder.for(model2).withMessages([createUserMessage(jsonPrompt)]).withConfig({
2802
+ ...options?.generationConfig,
2803
+ temperature: STRUCTURED_OUTPUT_TEMPERATURE
2804
+ }).build();
2805
+ return this.httpClient.postChatCompletion(request).then((response) => {
2806
+ const content = this.extractContent(response.choices[0]?.message?.content);
2807
+ return this.jsonParser.parse(content);
2808
+ });
2809
+ }
2810
+ const req = promptOrRequest;
2811
+ const model = req.model ?? (req.tier ? this.resolveModel(req.tier) : this.defaultModel);
2812
+ const schemaObj = req.schema;
2813
+ const messages = [];
2814
+ if (req.systemPrompt) {
2815
+ messages.push({ role: "system", content: req.systemPrompt });
2816
+ }
2817
+ for (const m of req.messages) {
2818
+ messages.push({ role: m.role, content: m.content });
2819
+ }
2820
+ const lastMsg = messages[messages.length - 1];
2821
+ if (lastMsg) {
2822
+ const structuredPrompt = StructuredPromptBuilder.for(lastMsg.content).withSchema(schemaObj).build();
2823
+ messages[messages.length - 1] = { ...lastMsg, content: structuredPrompt };
2824
+ }
2825
+ const groqReq = GroqChatRequestBuilder.for(model).withMessages(messages).withConfig({
2826
+ temperature: req.temperature ?? STRUCTURED_OUTPUT_TEMPERATURE,
2827
+ maxTokens: req.maxTokens
2828
+ }).build();
2829
+ return this.httpClient.postChatCompletion(groqReq).then((response) => {
2830
+ const content = this.extractContent(response.choices[0]?.message?.content);
2831
+ const parsed = this.jsonParser.parse(content);
2832
+ const genResult = {
2833
+ text: content,
2834
+ model: response.model,
2835
+ providerId: this.id,
2836
+ finishReason: response.choices[0]?.finish_reason ?? "stop",
2837
+ usage: response.usage ? {
2838
+ inputTokens: response.usage.prompt_tokens,
2839
+ outputTokens: response.usage.completion_tokens,
2840
+ totalTokens: response.usage.total_tokens
2841
+ } : void 0
2842
+ };
2843
+ return { value: parsed, result: genResult };
2844
+ });
2845
+ }
2846
+ streamCompletion(prompt, callbacks, options = {}) {
2847
+ return this.streamChatCompletion([createUserMessage(prompt)], callbacks, options);
2848
+ }
2849
+ async streamChatCompletion(messages, callbacks, options = {}) {
2850
+ const model = options.model ?? this.defaultModel;
2851
+ const request = GroqChatRequestBuilder.for(model).withMessages(messages).withConfig(options.generationConfig).withStream(true).build();
2852
+ const parser = new StreamingResponseParser(
2853
+ {
2854
+ onChunk: (chunk) => callbacks.onChunk?.(chunk)
2855
+ },
2856
+ extractContentFromSsePayload
2857
+ );
2858
+ try {
2859
+ const stream = await this.httpClient.streamChatCompletion(request, {
2860
+ signal: options.signal
2861
+ });
2862
+ const fullText = await parser.parse(stream);
2863
+ callbacks.onComplete?.(fullText);
2864
+ return fullText;
2865
+ } catch (error) {
2866
+ const err = error instanceof Error ? error : new Error(String(error));
2867
+ callbacks.onError?.(err);
2868
+ throw err;
2869
+ }
2870
+ }
2871
+ clearCache() {
2872
+ this.cache.clear();
2873
+ }
2874
+ // --- ITextProvider implementation ---
2875
+ resolveModel(tier) {
2876
+ return GROQ_TIERS[tier] ?? this.defaultModel;
2877
+ }
2878
+ async generate(request) {
2879
+ const messages = [];
2880
+ if (request.systemPrompt) {
2881
+ messages.push({ role: "system", content: request.systemPrompt });
2882
+ }
2883
+ for (const m of request.messages) {
2884
+ messages.push({ role: m.role, content: m.content });
2885
+ }
2886
+ const model = request.model ?? (request.tier ? this.resolveModel(request.tier) : this.defaultModel);
2887
+ const groqReq = GroqChatRequestBuilder.for(model).withMessages(messages).withConfig({
2888
+ temperature: request.temperature,
2889
+ maxTokens: request.maxTokens
2890
+ }).build();
2891
+ const resp = await this.httpClient.postChatCompletion(groqReq);
2892
+ const content = resp.choices[0]?.message?.content ?? "";
2893
+ return {
2894
+ text: content,
2895
+ finishReason: resp.choices[0]?.finish_reason ?? "stop",
2896
+ model: resp.model,
2897
+ providerId: this.id,
2898
+ usage: resp.usage ? {
2899
+ inputTokens: resp.usage.prompt_tokens,
2900
+ outputTokens: resp.usage.completion_tokens,
2901
+ totalTokens: resp.usage.total_tokens
2902
+ } : void 0
2903
+ };
2904
+ }
2905
+ async stream(request, callbacks) {
2906
+ const messages = [];
2907
+ if (request.systemPrompt) {
2908
+ messages.push({ role: "system", content: request.systemPrompt });
2909
+ }
2910
+ for (const m of request.messages) {
2911
+ messages.push({ role: m.role, content: m.content });
2912
+ }
2913
+ const model = request.model ?? (request.tier ? this.resolveModel(request.tier) : this.defaultModel);
2914
+ const text = await this.streamChatCompletion(
2915
+ messages,
2916
+ {
2917
+ onChunk: callbacks.onChunk,
2918
+ onError: callbacks.onError
2919
+ },
2920
+ {
2921
+ model,
2922
+ signal: request.signal,
2923
+ generationConfig: {
2924
+ temperature: request.temperature,
2925
+ maxTokens: request.maxTokens
2926
+ }
2927
+ }
2928
+ );
2929
+ const result = {
2930
+ text,
2931
+ finishReason: "stop",
2932
+ model,
2933
+ providerId: this.id
2934
+ };
2935
+ callbacks.onComplete?.(result);
2936
+ return result;
2937
+ }
2938
+ async countTokens(text) {
2939
+ return Math.max(1, Math.ceil(text.length / 4));
2940
+ }
2941
+ async estimateCost(_request) {
2942
+ return 0;
2943
+ }
2944
+ async healthCheck() {
2945
+ try {
2946
+ await this.generateCompletion("ping", {
2947
+ generationConfig: { maxTokens: 1 }
2948
+ });
2949
+ return "healthy";
2950
+ } catch {
2951
+ return "unavailable";
2952
+ }
2953
+ }
2954
+ async executeWithCache(params, factory) {
2955
+ const key = this.cache.generateKey(params);
2956
+ const cached = this.cache.get(key);
2957
+ if (cached !== null) {
2958
+ return cached;
2959
+ }
2960
+ const result = await factory();
2961
+ this.cache.set(key, result);
2962
+ return result;
2963
+ }
2964
+ extractContent(content) {
2965
+ if (!content) {
2966
+ throw new GroqError(
2967
+ "UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
2968
+ "No content generated from Groq API"
2969
+ );
2970
+ }
2971
+ return content;
2972
+ }
2973
+ };
2974
+
2975
+ // src/core/calculations/random-base36-suffix.ts
2976
+ var BASE_36_RADIX = 36;
2977
+ var DECIMAL_OFFSET = 2;
2978
+ function generateRandomBase36Suffix(length, random = Math.random) {
2979
+ if (length <= 0) return "";
2980
+ const raw = random().toString(BASE_36_RADIX).slice(DECIMAL_OFFSET);
2981
+ if (raw.length >= length) return raw.slice(0, length);
2982
+ let result = raw;
2983
+ while (result.length < length) {
2984
+ result += random().toString(BASE_36_RADIX).slice(DECIMAL_OFFSET);
2985
+ }
2986
+ return result.slice(0, length);
2987
+ }
2988
+
2989
+ // src/chat/utils/chat-id-generator.ts
2990
+ var ID_PART_DELIMITER = "-";
2991
+ var ChatIdGenerator = class {
2992
+ counter = 0;
2993
+ randomLength;
2994
+ constructor(randomLength = CHAT_MESSAGE_ID_SUFFIX_LENGTH) {
2995
+ this.randomLength = randomLength;
2996
+ }
2997
+ next(sender) {
2998
+ this.counter += 1;
2999
+ const random = generateRandomBase36Suffix(this.randomLength);
3000
+ return [
3001
+ MESSAGE_ID_PREFIX,
3002
+ Date.now(),
3003
+ sender,
3004
+ this.counter,
3005
+ random
3006
+ ].join(ID_PART_DELIMITER);
3007
+ }
3008
+ };
3009
+ var chatIdGenerator = new ChatIdGenerator();
3010
+
3011
+ // src/chat/utils/message-formatter.ts
3012
+ var MessageFormatter = class {
3013
+ constructor(idGenerator = chatIdGenerator) {
3014
+ this.idGenerator = idGenerator;
3015
+ }
3016
+ idGenerator;
3017
+ /** Maps chat-domain history to neutral core messages; system senders are
3018
+ * dropped — the system prompt travels on the request's own slot. */
3019
+ toCoreMessages(messages) {
3020
+ const coreMessages = [];
3021
+ for (const message of messages) {
3022
+ if (message.sender === "system") continue;
3023
+ coreMessages.push({
3024
+ role: message.sender === "user" ? USER_ROLE : ASSISTANT_ROLE,
3025
+ content: message.content
3026
+ });
3027
+ }
3028
+ return coreMessages;
3029
+ }
3030
+ toChatMessage(content, sender) {
3031
+ return {
3032
+ id: this.idGenerator.next(sender),
3033
+ sender,
3034
+ content: content.trim(),
3035
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3036
+ type: "text"
3037
+ };
3038
+ }
3039
+ };
3040
+ var messageFormatter = new MessageFormatter();
3041
+
3042
+ // src/chat/utils/prompt-strategy.ts
3043
+ var DEFAULT_PROMPT_STRATEGY = {
3044
+ resolve: (config) => {
3045
+ if (config.systemPrompt && config.systemPrompt.length > 0) {
3046
+ return config.systemPrompt;
3047
+ }
3048
+ return void 0;
3049
+ }
3050
+ };
3051
+
3052
+ // src/chat/services/chat.service.ts
3053
+ var DEFAULT_CONFIG = {
3054
+ temperature: 0.8,
3055
+ maxTokens: 500
3056
+ };
3057
+ var ChatService = class {
3058
+ constructor(engine) {
3059
+ this.engine = engine;
3060
+ }
3061
+ engine;
3062
+ config = DEFAULT_CONFIG;
3063
+ promptStrategy = DEFAULT_PROMPT_STRATEGY;
3064
+ storage = null;
3065
+ initialize(config) {
3066
+ this.config = { ...DEFAULT_CONFIG, ...config };
3067
+ }
3068
+ updateConfig(config) {
3069
+ this.config = { ...this.config, ...config };
3070
+ }
3071
+ setPromptStrategy(strategy) {
3072
+ this.promptStrategy = strategy;
3073
+ }
3074
+ setStorage(storage) {
3075
+ this.storage = storage;
3076
+ }
3077
+ async getConversation(conversationId) {
3078
+ const storage = this.requireStorage();
3079
+ const messages = await storage.getMessages(conversationId);
3080
+ if (messages.length === 0) return null;
3081
+ const last = messages[messages.length - 1];
3082
+ const first = messages[0];
3083
+ const companionId = String(first.metadata?.["companionId"] ?? "unknown");
3084
+ const companionName = String(first.metadata?.["companionName"] ?? "Unknown");
3085
+ return {
3086
+ id: conversationId,
3087
+ companionId,
3088
+ companionName,
3089
+ lastMessage: last,
3090
+ messageCount: messages.length,
3091
+ updatedAt: last.timestamp
3092
+ };
3093
+ }
3094
+ async getConversations() {
3095
+ if (this.storage && "getConversations" in this.storage && typeof this.storage.getConversations === "function") {
3096
+ return this.storage.getConversations();
3097
+ }
3098
+ return [];
3099
+ }
3100
+ async sendMessage(input, signal) {
3101
+ const userMessage = {
3102
+ ...messageFormatter.toChatMessage(input.text, "user"),
3103
+ type: input.type ?? "text",
3104
+ ...input.imageUrl !== void 0 ? { imageUrl: input.imageUrl } : {}
3105
+ };
3106
+ const aiResponse = await this.generateAIResponse(
3107
+ input.companionId,
3108
+ input.text,
3109
+ [],
3110
+ signal
3111
+ );
3112
+ return { userMessage, aiResponse };
3113
+ }
3114
+ async generateAIResponse(companionId, userMessage, context = [], signal) {
3115
+ const result = await this.run({
3116
+ ...this.buildRequest(userMessage, context, signal)
3117
+ });
3118
+ return {
3119
+ ...messageFormatter.toChatMessage(result.text, "assistant"),
3120
+ metadata: {
3121
+ companionId,
3122
+ model: result.model,
3123
+ usage: {
3124
+ input_tokens: result.usage?.inputTokens,
3125
+ output_tokens: result.usage?.outputTokens,
3126
+ total_tokens: result.usage?.totalTokens
3127
+ },
3128
+ finishReason: result.finishReason
3129
+ }
3130
+ };
3131
+ }
3132
+ async generateStreamingResponse(userMessage, context, onChunk, signal) {
3133
+ const request = this.buildRequest(userMessage, context, signal);
3134
+ const result = await this.runStream(request, { onChunk });
3135
+ return result.text;
3136
+ }
3137
+ buildRequest(userMessage, context, signal) {
3138
+ const messages = messageFormatter.toCoreMessages(context);
3139
+ messages.push({ role: "user", content: userMessage });
3140
+ return {
3141
+ messages,
3142
+ systemPrompt: this.resolveSystemPrompt(),
3143
+ model: this.config.model,
3144
+ tier: this.config.tier,
3145
+ temperature: this.config.temperature,
3146
+ maxTokens: this.config.maxTokens,
3147
+ ...signal !== void 0 ? { signal } : {}
3148
+ };
3149
+ }
3150
+ resolveSystemPrompt() {
3151
+ const prompt = this.promptStrategy.resolve(this.config);
3152
+ return prompt && prompt.length > 0 ? prompt : void 0;
3153
+ }
3154
+ async run(request) {
3155
+ if (this.engine instanceof ProviderFactory) {
3156
+ return this.engine.chat(request);
3157
+ }
3158
+ return this.engine.generate(request);
3159
+ }
3160
+ async runStream(request, callbacks) {
3161
+ if (this.engine instanceof ProviderFactory) {
3162
+ return this.engine.chatStream(request, callbacks);
3163
+ }
3164
+ return this.engine.stream(request, callbacks);
3165
+ }
3166
+ requireStorage() {
3167
+ if (!this.storage) {
3168
+ throw new AIError(
3169
+ "MISSING_CONFIG" /* MISSING_CONFIG */,
3170
+ "ChatService.getConversation requires setStorage() to be called first."
3171
+ );
3172
+ }
3173
+ return this.storage;
3174
+ }
3175
+ };
3176
+
3177
+ // src/providers/groq/groq-container.ts
3178
+ var container = null;
3179
+ function configureProvider(config) {
3180
+ const configStore = new GroqConfigStore();
3181
+ const transport = new GroqHttpTransport(configStore);
3182
+ const httpClient = new GroqHttpClient({ configStore, transport });
3183
+ httpClient.initialize(config);
3184
+ const textGeneration = new TextGenerationService(
3185
+ httpClient,
3186
+ new CacheManager(),
3187
+ config.textModel
3188
+ );
3189
+ const chat = new ChatService(textGeneration);
3190
+ container = { groqHttpClient: httpClient, textGeneration, chat };
3191
+ return container;
3192
+ }
3193
+ function getProvider() {
3194
+ return container;
3195
+ }
3196
+ function resetProvider() {
3197
+ container?.groqHttpClient.reset();
3198
+ container = null;
3199
+ }
3200
+
2376
3201
  exports.ANTHROPIC_API_VERSION = ANTHROPIC_API_VERSION;
2377
3202
  exports.ANTHROPIC_DEFAULT_MAX_TOKENS = ANTHROPIC_DEFAULT_MAX_TOKENS;
2378
3203
  exports.ANTHROPIC_MODELS = ANTHROPIC_MODELS;
2379
3204
  exports.ANTHROPIC_TIERS = ANTHROPIC_TIERS;
3205
+ exports.API_ENDPOINTS = API_ENDPOINTS;
2380
3206
  exports.AnthropicHttpTransport = AnthropicHttpTransport;
2381
3207
  exports.AnthropicProvider = AnthropicProvider;
2382
3208
  exports.AnthropicRequestBuilder = AnthropicRequestBuilder;
2383
3209
  exports.BaseProvider = BaseProvider;
3210
+ exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
3211
+ exports.DEFAULT_GENERATION_CONFIG = DEFAULT_GENERATION_CONFIG;
3212
+ exports.DEFAULT_MODELS = DEFAULT_MODELS;
2384
3213
  exports.FalProvider = FalProvider;
2385
3214
  exports.GEMINI_TIERS = GEMINI_TIERS;
2386
3215
  exports.GROQ_MODELS = GROQ_MODELS;
2387
3216
  exports.GROQ_TIERS = GROQ_TIERS;
2388
3217
  exports.GeminiProvider = GeminiProvider;
2389
3218
  exports.GroqChatRequestBuilder = GroqChatRequestBuilder;
3219
+ exports.GroqConfigStore = GroqConfigStore;
2390
3220
  exports.GroqHttpClient = GroqHttpClient;
2391
3221
  exports.GroqHttpTransport = GroqHttpTransport;
2392
3222
  exports.GroqProvider = GroqProvider;
2393
3223
  exports.ProviderError = ProviderError;
2394
3224
  exports.ProviderFactory = ProviderFactory;
2395
3225
  exports.PrunaProvider = PrunaProvider;
3226
+ exports.TIMEOUTS = TIMEOUTS;
3227
+ exports.TextGenerationService = TextGenerationService;
3228
+ exports.configureProvider = configureProvider;
2396
3229
  exports.consumeAnthropicStream = consumeAnthropicStream;
2397
3230
  exports.consumeGroqStream = consumeGroqStream;
2398
3231
  exports.createAI = createAI;
3232
+ exports.createAssistantMessage = createAssistantMessage;
2399
3233
  exports.createFalProvider = createFalProvider;
2400
3234
  exports.createGeminiProvider = createGeminiProvider;
3235
+ exports.createMessage = createMessage;
2401
3236
  exports.createPrunaProvider = createPrunaProvider;
3237
+ exports.createSystemMessage = createSystemMessage;
3238
+ exports.createUserMessage = createUserMessage;
2402
3239
  exports.defaultEffortForModel = defaultEffortForModel;
2403
3240
  exports.extractContentFromSsePayload = extractContentFromSsePayload;
3241
+ exports.extractTextFromMessages = extractTextFromMessages;
3242
+ exports.formatMessagesForDisplay = formatMessagesForDisplay;
2404
3243
  exports.generateWithPruna = generateWithPruna;
3244
+ exports.getProvider = getProvider;
2405
3245
  exports.isMediaProvider = isMediaProvider;
2406
3246
  exports.isTextProvider = isTextProvider;
2407
3247
  exports.mapAnthropicStopReason = mapAnthropicStopReason;
3248
+ exports.promptToMessages = promptToMessages;
3249
+ exports.requestStructuredJson = requestStructuredJson;
3250
+ exports.resetProvider = resetProvider;
2408
3251
  exports.toGroqMessages = toGroqMessages;
2409
3252
  //# sourceMappingURL=index.cjs.map
2410
3253
  //# sourceMappingURL=index.cjs.map