@umituz/web-ai 1.0.1 → 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.
@@ -5,7 +5,7 @@ export { A as AnthropicConfig, B as BaseProviderConfig, F as FalConfig, c as Gem
5
5
  import { j as GenerationType, k as ImageQuality, l as VideoQuality, m as AspectRatio, S as SentimentAnalysisResult, C as ContentAnalysisRequest, a as ContentAnalysisResult, b as SEOOptimizationRequest, c as SEOOptimizationResult, d as SEOScoreBreakdown, K as KeywordAnalysis, e as ABTestRequest, f as ABTestPrediction, g as ABTestComparison } from '../AIErrors-C5EasV_c.cjs';
6
6
  export { n as ABTestVariant, A as AIErrorCode, o as ASPECT_RATIO_OPTIONS, G as ContentGenerationResult, p as CreditCost, q as GenerationMetadata, h as GenerationProgress, i as GenerationStatus, r as IMAGE_QUALITY_OPTIONS, I as ImageGenerationInput, M as MOTION_OPTIONS, P as ProviderQuotaExhaustedError, s as ProviderUnavailableError, t as STYLE_PRESETS, u as VIDEO_DURATION_OPTIONS_SECONDS, v as VIDEO_QUALITY_OPTIONS, w as ValidationError, V as VideoGenerationInput } from '../AIErrors-C5EasV_c.cjs';
7
7
  import { f as ITextGenerator, c as ProviderFactory, T as TextGenerationOptions } from '../provider.factory-BxsfK4WW.cjs';
8
- import { A as AIProviderConfig } from '../create-ai-DOI9jD3v.cjs';
8
+ import { A as AIProviderConfig } from '../create-ai-CXYKPK6G.cjs';
9
9
  import { T as TextRequest, G as GenerationResult } from '../index-fXjxTR5W.cjs';
10
10
  export { A as AIError } from '../index-DKHNcMbl.cjs';
11
11
 
@@ -5,7 +5,7 @@ export { A as AnthropicConfig, B as BaseProviderConfig, F as FalConfig, c as Gem
5
5
  import { j as GenerationType, k as ImageQuality, l as VideoQuality, m as AspectRatio, S as SentimentAnalysisResult, C as ContentAnalysisRequest, a as ContentAnalysisResult, b as SEOOptimizationRequest, c as SEOOptimizationResult, d as SEOScoreBreakdown, K as KeywordAnalysis, e as ABTestRequest, f as ABTestPrediction, g as ABTestComparison } from '../AIErrors-B2ogd1PB.js';
6
6
  export { n as ABTestVariant, A as AIErrorCode, o as ASPECT_RATIO_OPTIONS, G as ContentGenerationResult, p as CreditCost, q as GenerationMetadata, h as GenerationProgress, i as GenerationStatus, r as IMAGE_QUALITY_OPTIONS, I as ImageGenerationInput, M as MOTION_OPTIONS, P as ProviderQuotaExhaustedError, s as ProviderUnavailableError, t as STYLE_PRESETS, u as VIDEO_DURATION_OPTIONS_SECONDS, v as VIDEO_QUALITY_OPTIONS, w as ValidationError, V as VideoGenerationInput } from '../AIErrors-B2ogd1PB.js';
7
7
  import { f as ITextGenerator, c as ProviderFactory, T as TextGenerationOptions } from '../provider.factory-DfDfk0dK.js';
8
- import { A as AIProviderConfig } from '../create-ai-DXEoke8-.js';
8
+ import { A as AIProviderConfig } from '../create-ai-9PW752z8.js';
9
9
  import { T as TextRequest, G as GenerationResult } from '../index-fXjxTR5W.js';
10
10
  export { A as AIError } from '../index-DIHz8_OJ.js';
11
11
 
@@ -196,6 +196,14 @@ var ProviderQuotaExhaustedError = class extends AIError {
196
196
  }
197
197
  };
198
198
 
199
+ // src/core/errors/groq-error.ts
200
+ var GroqError = class extends AIError {
201
+ constructor(type, message, cause, metadata = {}) {
202
+ super(type, message, cause, metadata);
203
+ this.name = "GroqError";
204
+ }
205
+ };
206
+
199
207
  // src/core/errors/error-classifier.ts
200
208
  var DEFAULT_RETRYABLE_TYPES = /* @__PURE__ */ new Set([
201
209
  "NETWORK_ERROR" /* NETWORK_ERROR */,
@@ -1392,6 +1400,27 @@ var RequestDeduplicator = class {
1392
1400
  }
1393
1401
  };
1394
1402
 
1403
+ // src/core/utils/api-key-validator.ts
1404
+ var DEFAULT_API_KEY_RULE = {
1405
+ minLength: 10
1406
+ };
1407
+ function validateApiKey(apiKey, rule = DEFAULT_API_KEY_RULE) {
1408
+ if (!apiKey) {
1409
+ return { valid: false, reason: "API key is required" };
1410
+ }
1411
+ const trimmed = apiKey.trim();
1412
+ if (trimmed.length === 0) {
1413
+ return { valid: false, reason: "API key cannot be empty" };
1414
+ }
1415
+ if (trimmed.length < rule.minLength) {
1416
+ return {
1417
+ valid: false,
1418
+ reason: `API key must be at least ${rule.minLength} characters`
1419
+ };
1420
+ }
1421
+ return { valid: true };
1422
+ }
1423
+
1395
1424
  // src/providers/groq/groq.constants.ts
1396
1425
  var GROQ_MODELS = {
1397
1426
  LLAMA_3_1_8B_INSTANT: "llama-3.1-8b-instant",
@@ -1408,11 +1437,13 @@ var DEFAULT_GENERATION_CONFIG = {
1408
1437
  topP: 1
1409
1438
  };
1410
1439
  var GROQ_BASE_URL = "https://api.groq.com/openai/v1";
1440
+ var DEFAULT_BASE_URL = GROQ_BASE_URL;
1411
1441
  var CHAT_COMPLETIONS_PATH = "/chat/completions";
1412
1442
  var GROQ_TIMEOUTS = {
1413
1443
  DEFAULT: 3e4,
1414
1444
  STREAMING: 6e4
1415
1445
  };
1446
+ var TIMEOUTS = GROQ_TIMEOUTS;
1416
1447
  var HTTP_HEADERS = {
1417
1448
  CONTENT_TYPE: "Content-Type",
1418
1449
  APPLICATION_JSON: "application/json",
@@ -1471,13 +1502,65 @@ var GroqChatRequestBuilder = class _GroqChatRequestBuilder {
1471
1502
  }
1472
1503
  };
1473
1504
 
1505
+ // src/providers/groq/groq-config-store.ts
1506
+ var GroqConfigStore = class {
1507
+ config = null;
1508
+ initialize(config) {
1509
+ const validation = validateApiKey(config.apiKey, { minLength: 1 });
1510
+ if (!validation.valid) {
1511
+ throw new GroqError("INVALID_API_KEY" /* INVALID_API_KEY */, validation.reason ?? "Invalid API key");
1512
+ }
1513
+ const normalized = {
1514
+ apiKey: config.apiKey.trim(),
1515
+ baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,
1516
+ timeoutMs: config.timeoutMs ?? TIMEOUTS.DEFAULT,
1517
+ ...config.models !== void 0 ? { models: config.models } : {},
1518
+ ...config.textModel !== void 0 ? { textModel: config.textModel } : {}
1519
+ };
1520
+ this.config = normalized;
1521
+ return normalized;
1522
+ }
1523
+ get() {
1524
+ if (!this.config) {
1525
+ throw new GroqError(
1526
+ "MISSING_CONFIG" /* MISSING_CONFIG */,
1527
+ "Client not initialized. Call configureProvider first."
1528
+ );
1529
+ }
1530
+ return this.config;
1531
+ }
1532
+ getOrNull() {
1533
+ return this.config;
1534
+ }
1535
+ isInitialized() {
1536
+ return this.config !== null;
1537
+ }
1538
+ setApiKey(apiKey) {
1539
+ const current = this.get();
1540
+ const validation = validateApiKey(apiKey, { minLength: 1 });
1541
+ if (!validation.valid) {
1542
+ throw new GroqError("INVALID_API_KEY" /* INVALID_API_KEY */, validation.reason ?? "Invalid API key");
1543
+ }
1544
+ this.config = { ...current, apiKey: apiKey.trim() };
1545
+ }
1546
+ reset() {
1547
+ this.config = null;
1548
+ }
1549
+ };
1550
+
1474
1551
  // src/providers/groq/groq-http-transport.ts
1475
1552
  var GroqHttpTransport = class {
1476
- constructor(config) {
1477
- this.config = config;
1553
+ constructor(configSource) {
1554
+ this.configSource = configSource;
1478
1555
  }
1479
- config;
1556
+ configSource;
1480
1557
  pendingAbortControllers = /* @__PURE__ */ new Set();
1558
+ getConfig() {
1559
+ if ("get" in this.configSource && typeof this.configSource.get === "function") {
1560
+ return this.configSource.get();
1561
+ }
1562
+ return this.configSource;
1563
+ }
1481
1564
  cancelPendingRequests() {
1482
1565
  for (const controller of this.pendingAbortControllers) {
1483
1566
  controller.abort();
@@ -1492,7 +1575,7 @@ var GroqHttpTransport = class {
1492
1575
  }
1493
1576
  async streamChatCompletion(request, options = {}) {
1494
1577
  const url = `${this.baseUrl()}${CHAT_COMPLETIONS_PATH}`;
1495
- const timeout = this.config.timeoutMs ?? GROQ_TIMEOUTS.STREAMING;
1578
+ const timeout = this.getConfig().timeoutMs ?? GROQ_TIMEOUTS.STREAMING;
1496
1579
  const controller = new AbortController();
1497
1580
  const timeoutId = setTimeout(() => controller.abort(), timeout);
1498
1581
  const onExternalAbort = () => controller.abort();
@@ -1519,11 +1602,11 @@ var GroqHttpTransport = class {
1519
1602
  }
1520
1603
  }
1521
1604
  baseUrl() {
1522
- return this.config.baseUrl ?? GROQ_BASE_URL;
1605
+ return this.getConfig().baseUrl ?? GROQ_BASE_URL;
1523
1606
  }
1524
1607
  async request(endpoint, body) {
1525
1608
  const url = `${this.baseUrl()}${endpoint}`;
1526
- const timeout = this.config.timeoutMs ?? GROQ_TIMEOUTS.DEFAULT;
1609
+ const timeout = this.getConfig().timeoutMs ?? GROQ_TIMEOUTS.DEFAULT;
1527
1610
  const controller = new AbortController();
1528
1611
  const timeoutId = setTimeout(() => controller.abort(), timeout);
1529
1612
  this.pendingAbortControllers.add(controller);
@@ -1546,7 +1629,7 @@ var GroqHttpTransport = class {
1546
1629
  buildHeaders() {
1547
1630
  return {
1548
1631
  [HTTP_HEADERS.CONTENT_TYPE]: HTTP_HEADERS.APPLICATION_JSON,
1549
- [HTTP_HEADERS.AUTHORIZATION]: `${HTTP_HEADERS.BEARER_PREFIX}${this.config.apiKey}`
1632
+ [HTTP_HEADERS.AUTHORIZATION]: `${HTTP_HEADERS.BEARER_PREFIX}${this.getConfig().apiKey}`
1550
1633
  };
1551
1634
  }
1552
1635
  async throwFromErrorResponse(response) {
@@ -1648,21 +1731,40 @@ var CompositeExecutor = class {
1648
1731
 
1649
1732
  // src/providers/groq/groq-http-client.ts
1650
1733
  var GroqHttpClient = class {
1734
+ configStore;
1651
1735
  transport;
1652
1736
  executor;
1653
- constructor(config, deps = {}) {
1654
- this.transport = deps.transport ?? new GroqHttpTransport(config);
1737
+ constructor(configOrDeps, maybeDeps = {}) {
1738
+ const isConfig = typeof configOrDeps === "object" && configOrDeps !== null && "apiKey" in configOrDeps && typeof configOrDeps.apiKey === "string";
1739
+ const deps = isConfig ? maybeDeps : configOrDeps ?? {};
1740
+ this.configStore = deps.configStore ?? new GroqConfigStore();
1741
+ if (isConfig) {
1742
+ this.configStore.initialize(configOrDeps);
1743
+ }
1744
+ this.transport = deps.transport ?? new GroqHttpTransport(this.configStore);
1655
1745
  const retryManager2 = deps.retryManager ?? new RetryManager();
1656
1746
  const queue = deps.queue ?? new RequestQueue();
1657
1747
  const deduplicator = deps.deduplicator ?? new RequestDeduplicator();
1658
1748
  this.executor = new CompositeExecutor([
1659
1749
  new DedupeExecutor(deduplicator, {
1660
- generateKey: (request) => deduplicatorKey(request, config.apiKey)
1750
+ generateKey: (request) => deduplicatorKey(request, this.configStore.isInitialized() ? this.configStore.get().apiKey : "")
1661
1751
  }),
1662
1752
  new RetryExecutor(retryManager2),
1663
1753
  new QueueExecutor(queue, QUEUE_PRIORITY_USER_REQUEST)
1664
1754
  ]);
1665
1755
  }
1756
+ initialize(config) {
1757
+ this.configStore.initialize(config);
1758
+ }
1759
+ isInitialized() {
1760
+ return this.configStore.isInitialized();
1761
+ }
1762
+ getApiKey() {
1763
+ return this.configStore.get().apiKey;
1764
+ }
1765
+ setApiKey(apiKey) {
1766
+ this.configStore.setApiKey(apiKey);
1767
+ }
1666
1768
  cancelPendingRequests() {
1667
1769
  this.transport.cancelPendingRequests();
1668
1770
  }
@@ -1675,6 +1777,10 @@ var GroqHttpClient = class {
1675
1777
  streamChatCompletion(request, options) {
1676
1778
  return this.transport.streamChatCompletion(request, options);
1677
1779
  }
1780
+ reset() {
1781
+ this.transport.cancelPendingRequests();
1782
+ this.configStore.reset();
1783
+ }
1678
1784
  };
1679
1785
  function deduplicatorKey(request, apiKey) {
1680
1786
  const { model, messages, stream: _stream, ...rest } = request;