@happyvertical/ai 0.79.0 → 0.80.1

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 (63) hide show
  1. package/AGENT.md +1 -1
  2. package/dist/chunks/anthropic-DA8sdt12.js +438 -0
  3. package/dist/chunks/anthropic-DA8sdt12.js.map +1 -0
  4. package/dist/chunks/bedrock-DDiYFUw0.js +699 -0
  5. package/dist/chunks/bedrock-DDiYFUw0.js.map +1 -0
  6. package/dist/chunks/bifrost-fM9FpW_w.js +198 -0
  7. package/dist/chunks/bifrost-fM9FpW_w.js.map +1 -0
  8. package/dist/chunks/claude-cli-CnJh5KQT.js +498 -0
  9. package/dist/chunks/claude-cli-CnJh5KQT.js.map +1 -0
  10. package/dist/chunks/gateway-admin-CiKvHst7.js +283 -0
  11. package/dist/chunks/gateway-admin-CiKvHst7.js.map +1 -0
  12. package/dist/chunks/gemini-Bu7Fke7c.js +593 -0
  13. package/dist/chunks/gemini-Bu7Fke7c.js.map +1 -0
  14. package/dist/chunks/huggingface-B07_6wHW.js +295 -0
  15. package/dist/chunks/huggingface-B07_6wHW.js.map +1 -0
  16. package/dist/chunks/litellm-D_Oo9OQ_.js +185 -0
  17. package/dist/chunks/litellm-D_Oo9OQ_.js.map +1 -0
  18. package/dist/chunks/ollama-D4ksOTO8.js +626 -0
  19. package/dist/chunks/ollama-D4ksOTO8.js.map +1 -0
  20. package/dist/chunks/openai--F38QHiJ.js +691 -0
  21. package/dist/chunks/openai--F38QHiJ.js.map +1 -0
  22. package/dist/chunks/qwen-tts-DRRbOrhA.js +333 -0
  23. package/dist/chunks/qwen-tts-DRRbOrhA.js.map +1 -0
  24. package/dist/chunks/rate-limit-BwyPGXFW.js +199 -0
  25. package/dist/chunks/rate-limit-BwyPGXFW.js.map +1 -0
  26. package/dist/chunks/safety-CEnoJS6X.js +260 -0
  27. package/dist/chunks/safety-CEnoJS6X.js.map +1 -0
  28. package/dist/chunks/types-FHs-KbGL.js +117 -0
  29. package/dist/chunks/types-FHs-KbGL.js.map +1 -0
  30. package/dist/chunks/usage-C1Y1Nlg4.js +35 -0
  31. package/dist/chunks/usage-C1Y1Nlg4.js.map +1 -0
  32. package/dist/cli/claude-context.js +17 -17
  33. package/dist/cli/claude-context.js.map +1 -1
  34. package/dist/index.js +717 -23
  35. package/dist/index.js.map +1 -1
  36. package/metadata.json +1 -1
  37. package/package.json +5 -5
  38. package/dist/chunks/anthropic-2z-82zgr.js +0 -530
  39. package/dist/chunks/anthropic-2z-82zgr.js.map +0 -1
  40. package/dist/chunks/bedrock-Dc2eVPUD.js +0 -920
  41. package/dist/chunks/bedrock-Dc2eVPUD.js.map +0 -1
  42. package/dist/chunks/bifrost-CEnCsciy.js +0 -258
  43. package/dist/chunks/bifrost-CEnCsciy.js.map +0 -1
  44. package/dist/chunks/claude-cli-X1ONjE8K.js +0 -603
  45. package/dist/chunks/claude-cli-X1ONjE8K.js.map +0 -1
  46. package/dist/chunks/gateway-admin-BUhBzXZb.js +0 -359
  47. package/dist/chunks/gateway-admin-BUhBzXZb.js.map +0 -1
  48. package/dist/chunks/gemini-CS56gY0D.js +0 -768
  49. package/dist/chunks/gemini-CS56gY0D.js.map +0 -1
  50. package/dist/chunks/huggingface-wQSfO5xA.js +0 -411
  51. package/dist/chunks/huggingface-wQSfO5xA.js.map +0 -1
  52. package/dist/chunks/index-DCXO0nZA.js +0 -1293
  53. package/dist/chunks/index-DCXO0nZA.js.map +0 -1
  54. package/dist/chunks/litellm-BMFTYbWc.js +0 -245
  55. package/dist/chunks/litellm-BMFTYbWc.js.map +0 -1
  56. package/dist/chunks/ollama-DsGDrA-c.js +0 -962
  57. package/dist/chunks/ollama-DsGDrA-c.js.map +0 -1
  58. package/dist/chunks/openai-CJEo69jb.js +0 -882
  59. package/dist/chunks/openai-CJEo69jb.js.map +0 -1
  60. package/dist/chunks/qwen-tts-BLYZ6d9s.js +0 -365
  61. package/dist/chunks/qwen-tts-BLYZ6d9s.js.map +0 -1
  62. package/dist/chunks/usage-DMWiJ2oB.js +0 -21
  63. package/dist/chunks/usage-DMWiJ2oB.js.map +0 -1
@@ -1,1293 +0,0 @@
1
- import { ValidationError, ApiError, loadEnvConfig } from "@happyvertical/utils";
2
- import OpenAI from "openai";
3
- const AI_PROVIDER_TYPES = [
4
- "openai",
5
- "litellm",
6
- "bifrost",
7
- "ollama",
8
- "gemini",
9
- "anthropic",
10
- "huggingface",
11
- "bedrock",
12
- "claude-cli",
13
- "qwen3-tts"
14
- ];
15
- function extractTextContent(content) {
16
- if (typeof content === "string") {
17
- return content;
18
- }
19
- return content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
20
- }
21
- class AIError extends Error {
22
- constructor(message, code, provider, model, retryable = false) {
23
- super(message);
24
- this.code = code;
25
- this.provider = provider;
26
- this.model = model;
27
- this.retryable = retryable;
28
- this.name = "AIError";
29
- }
30
- }
31
- class AuthenticationError extends AIError {
32
- constructor(provider) {
33
- super("Authentication failed", "AUTH_ERROR", provider, void 0, false);
34
- this.name = "AuthenticationError";
35
- }
36
- }
37
- class RateLimitError extends AIError {
38
- retryAfter;
39
- constructor(provider, retryAfter) {
40
- super(
41
- `Rate limit exceeded${retryAfter ? `, retry after ${retryAfter}s` : ""}`,
42
- "RATE_LIMIT",
43
- provider,
44
- void 0,
45
- true
46
- );
47
- this.name = "RateLimitError";
48
- this.retryAfter = retryAfter;
49
- }
50
- }
51
- class ModelNotFoundError extends AIError {
52
- constructor(model, provider) {
53
- super(
54
- `Model not found: ${model}`,
55
- "MODEL_NOT_FOUND",
56
- provider,
57
- model,
58
- false
59
- );
60
- this.name = "ModelNotFoundError";
61
- }
62
- }
63
- class ContextLengthError extends AIError {
64
- constructor(provider, model) {
65
- super(
66
- "Input exceeds maximum context length",
67
- "CONTEXT_LENGTH_EXCEEDED",
68
- provider,
69
- model,
70
- false
71
- );
72
- this.name = "ContextLengthError";
73
- }
74
- }
75
- class ContentFilterError extends AIError {
76
- constructor(provider, model) {
77
- super(
78
- "Content filtered by safety systems",
79
- "CONTENT_FILTERED",
80
- provider,
81
- model,
82
- false
83
- );
84
- this.name = "ContentFilterError";
85
- }
86
- }
87
- function isOpenAIClientOptions(options) {
88
- return options.type === "openai" && "apiKey" in options && !!options.apiKey;
89
- }
90
- function isAIClientInstance(value) {
91
- return value instanceof AIClient;
92
- }
93
- class AIClient {
94
- /**
95
- * Configuration options for this client
96
- */
97
- options;
98
- /**
99
- * Creates a new AIClient
100
- *
101
- * @param options - Client configuration options
102
- */
103
- constructor(options) {
104
- this.options = options;
105
- }
106
- /**
107
- * Sends a message to the AI
108
- * Base implementation returns a placeholder response
109
- *
110
- * @param text - Message text
111
- * @param options - Message options
112
- * @returns Promise resolving to a placeholder response
113
- */
114
- async message(_text, _options = { role: "user" }) {
115
- return "not a real ai message, this is the base class!";
116
- }
117
- /**
118
- * Factory method to create appropriate AI client based on options
119
- *
120
- * @param options - Client configuration options
121
- * @returns Promise resolving to an initialized AI client
122
- * @throws Error if client type is invalid
123
- */
124
- static async create(options) {
125
- if (isAIClientInstance(options)) {
126
- return options;
127
- }
128
- const clientOptions = options;
129
- if (isOpenAIClientOptions(clientOptions)) {
130
- return OpenAIClient.create(clientOptions);
131
- }
132
- const providedType = clientOptions.type;
133
- if (providedType && providedType !== "openai") {
134
- const { getAI: getAI2 } = await Promise.resolve().then(() => factory);
135
- return await getAI2(clientOptions);
136
- }
137
- if (providedType === "openai") {
138
- throw new ValidationError(
139
- "OpenAI API key is required but missing or empty",
140
- {
141
- supportedTypes: [...AI_PROVIDER_TYPES],
142
- providedType,
143
- hint: "Set OPENAI_API_KEY environment variable or pass apiKey in options"
144
- }
145
- );
146
- }
147
- throw new ValidationError("Invalid client type specified", {
148
- supportedTypes: [...AI_PROVIDER_TYPES],
149
- providedType
150
- });
151
- }
152
- /**
153
- * Gets a text completion from the AI
154
- * In base class, delegates to message method
155
- *
156
- * @param text - Input text for completion
157
- * @param options - Completion options
158
- * @returns Promise resolving to the completion result
159
- */
160
- textCompletion(text, options = {
161
- role: "user"
162
- }) {
163
- return this.message(text, options);
164
- }
165
- }
166
- async function getOpenAI(options) {
167
- return new OpenAI({
168
- apiKey: options.apiKey,
169
- baseURL: options.baseUrl
170
- });
171
- }
172
- class OpenAIClient extends AIClient {
173
- /**
174
- * OpenAI client instance
175
- */
176
- openai;
177
- /**
178
- * Configuration options for this client
179
- */
180
- options;
181
- /**
182
- * Creates a new OpenAIClient
183
- *
184
- * @param options - OpenAI client configuration options
185
- */
186
- constructor(options) {
187
- super(options);
188
- this.options = options;
189
- }
190
- /**
191
- * Sends a message to OpenAI
192
- *
193
- * @param text - Message text
194
- * @param options - Message options
195
- * @returns Promise resolving to the OpenAI response
196
- */
197
- async message(text, options = { role: "user" }) {
198
- const response = await this.textCompletion(text, options);
199
- return response;
200
- }
201
- /**
202
- * Factory method to create and initialize an OpenAIClient
203
- *
204
- * @param options - OpenAI client configuration options
205
- * @returns Promise resolving to an initialized OpenAIClient
206
- */
207
- static async create(options) {
208
- const client = new OpenAIClient(options);
209
- await client.initialize();
210
- return client;
211
- }
212
- /**
213
- * Initializes the OpenAI client
214
- */
215
- async initialize() {
216
- this.openai = new OpenAI({
217
- apiKey: this.options.apiKey,
218
- baseURL: this.options.baseUrl
219
- });
220
- }
221
- /**
222
- * Sends a text completion request to the OpenAI API
223
- *
224
- * @param message - The message to send
225
- * @param options - Configuration options for the completion request
226
- * @returns Promise resolving to the completion text
227
- * @throws Error if the OpenAI API response is invalid
228
- */
229
- async textCompletion(message, options = {}) {
230
- const {
231
- model = "gpt-4o",
232
- role = "user",
233
- history = [],
234
- name: _name,
235
- frequencyPenalty = 0,
236
- logitBias,
237
- logprobs = false,
238
- topLogprobs,
239
- maxTokens,
240
- n = 1,
241
- presencePenalty = 0,
242
- responseFormat,
243
- seed,
244
- stop,
245
- stream: _stream = false,
246
- temperature = 1,
247
- topProbability: topP = 1,
248
- tools,
249
- toolChoice,
250
- user,
251
- onProgress
252
- } = options;
253
- const messages = [
254
- ...history,
255
- {
256
- role,
257
- content: message
258
- }
259
- ];
260
- if (onProgress) {
261
- const stream = await this.openai.chat.completions.create({
262
- model,
263
- messages,
264
- stream: true,
265
- frequency_penalty: frequencyPenalty,
266
- logit_bias: logitBias,
267
- logprobs,
268
- top_logprobs: topLogprobs,
269
- max_tokens: maxTokens,
270
- n,
271
- presence_penalty: presencePenalty,
272
- response_format: responseFormat,
273
- seed,
274
- stop,
275
- temperature,
276
- top_p: topP,
277
- tools,
278
- tool_choice: toolChoice,
279
- user
280
- });
281
- let fullContent = "";
282
- for await (const chunk of stream) {
283
- const content = chunk.choices[0]?.delta?.content || "";
284
- fullContent += content;
285
- onProgress(content);
286
- }
287
- return fullContent;
288
- }
289
- const response = await this.openai.chat.completions.create({
290
- model,
291
- messages,
292
- frequency_penalty: frequencyPenalty,
293
- logit_bias: logitBias,
294
- logprobs,
295
- top_logprobs: topLogprobs,
296
- max_tokens: maxTokens,
297
- n,
298
- presence_penalty: presencePenalty,
299
- response_format: responseFormat,
300
- seed,
301
- stop,
302
- stream: false,
303
- temperature,
304
- top_p: topP,
305
- tools,
306
- tool_choice: toolChoice,
307
- user
308
- });
309
- const choice = response.choices[0];
310
- if (!choice || !choice.message || !choice.message.content) {
311
- throw new ApiError("Invalid response from OpenAI API: Missing content", {
312
- model,
313
- responseId: response.id,
314
- choices: response.choices?.length || 0,
315
- hasChoice: !!choice,
316
- hasMessage: !!choice?.message,
317
- hasContent: !!choice?.message?.content
318
- });
319
- }
320
- return choice.message.content;
321
- }
322
- }
323
- async function getAIClient(options) {
324
- const { getAI: getAI2 } = await Promise.resolve().then(() => factory);
325
- return await getAI2(options);
326
- }
327
- const RATE_LIMITED_METHODS = /* @__PURE__ */ new Set([
328
- "chat",
329
- "complete",
330
- "message",
331
- "embed",
332
- "embedImage",
333
- "describeImage",
334
- "generateImage",
335
- "getModels",
336
- "synthesizeSpeech",
337
- "cloneVoice",
338
- "designVoice",
339
- "getVoices"
340
- ]);
341
- const MAX_BUDGET_COORDINATORS = 128;
342
- const BUDGET_COORDINATOR_TTL_MS = 15 * 60 * 1e3;
343
- class BudgetCoordinator {
344
- nextAvailableAt = 0;
345
- pendingSchedules = 0;
346
- tail = Promise.resolve();
347
- lastUsedAt = Date.now();
348
- touch() {
349
- this.lastUsedAt = Date.now();
350
- }
351
- schedule(work) {
352
- this.pendingSchedules += 1;
353
- this.touch();
354
- const run = this.tail.then(work, work);
355
- this.tail = run.then(
356
- () => void 0,
357
- () => void 0
358
- );
359
- return run.finally(() => {
360
- this.pendingSchedules = Math.max(0, this.pendingSchedules - 1);
361
- this.touch();
362
- });
363
- }
364
- async waitUntilReady() {
365
- this.touch();
366
- const delayMs = this.nextAvailableAt - Date.now();
367
- if (delayMs > 0) {
368
- await sleep(delayMs);
369
- }
370
- }
371
- delayFor(delayMs) {
372
- this.touch();
373
- if (delayMs <= 0) {
374
- return;
375
- }
376
- this.nextAvailableAt = Math.max(this.nextAvailableAt, Date.now() + delayMs);
377
- }
378
- isEvictable(now) {
379
- return this.pendingSchedules === 0 && now >= this.nextAvailableAt;
380
- }
381
- isExpired(now) {
382
- return this.isEvictable(now) && now - this.lastUsedAt >= BUDGET_COORDINATOR_TTL_MS;
383
- }
384
- getLastUsedAt() {
385
- return this.lastUsedAt;
386
- }
387
- }
388
- const budgetCoordinators = /* @__PURE__ */ new Map();
389
- function sleep(delayMs) {
390
- return new Promise((resolve) => {
391
- setTimeout(resolve, delayMs);
392
- });
393
- }
394
- function pruneBudgetCoordinators() {
395
- const now = Date.now();
396
- for (const [key, coordinator] of budgetCoordinators.entries()) {
397
- if (coordinator.isExpired(now)) {
398
- budgetCoordinators.delete(key);
399
- }
400
- }
401
- while (budgetCoordinators.size > MAX_BUDGET_COORDINATORS) {
402
- const evictableEntries = [...budgetCoordinators.entries()].filter(([, coordinator]) => coordinator.isEvictable(now)).sort(
403
- ([, leftCoordinator], [, rightCoordinator]) => leftCoordinator.getLastUsedAt() - rightCoordinator.getLastUsedAt()
404
- );
405
- if (evictableEntries.length === 0) {
406
- break;
407
- }
408
- budgetCoordinators.delete(evictableEntries[0][0]);
409
- }
410
- }
411
- function getBudgetCoordinator(key) {
412
- pruneBudgetCoordinators();
413
- let coordinator = budgetCoordinators.get(key);
414
- if (!coordinator) {
415
- coordinator = new BudgetCoordinator();
416
- budgetCoordinators.set(key, coordinator);
417
- pruneBudgetCoordinators();
418
- }
419
- coordinator.touch();
420
- return coordinator;
421
- }
422
- function hasPacingConfig(rateLimit) {
423
- if (!rateLimit || rateLimit.enabled === false) {
424
- return false;
425
- }
426
- return rateLimit.enabled === true || rateLimit.key !== void 0 || rateLimit.cooldownMs !== void 0 || rateLimit.initialDelayMs !== void 0 || rateLimit.maxAttempts !== void 0;
427
- }
428
- function normalizeNonNegativeInteger(value, fallback) {
429
- if (typeof value !== "number" || !Number.isFinite(value)) {
430
- return fallback;
431
- }
432
- return Math.max(0, Math.trunc(value));
433
- }
434
- function hashKey(value) {
435
- let hash = 2166136261;
436
- for (let index = 0; index < value.length; index += 1) {
437
- hash ^= value.charCodeAt(index);
438
- hash = Math.imul(hash, 16777619);
439
- }
440
- return (hash >>> 0).toString(36);
441
- }
442
- function deriveBudgetKey(options) {
443
- const type = options.type;
444
- const provider = typeof type === "string" && type ? type : "openai";
445
- const credentialLikeValues = [
446
- "apiKey" in options ? options.apiKey : void 0,
447
- "apiToken" in options ? options.apiToken : void 0,
448
- "credentials" in options ? options.credentials?.accessKeyId : void 0,
449
- "endpoint" in options ? options.endpoint : void 0,
450
- "baseUrl" in options ? options.baseUrl : void 0,
451
- "cliPath" in options ? options.cliPath : void 0
452
- ];
453
- const seed = credentialLikeValues.find(
454
- (value) => typeof value === "string" && value.length > 0
455
- );
456
- return seed ? `${provider}:${hashKey(seed)}` : `${provider}:default`;
457
- }
458
- function normalizeRateLimitConfig(options) {
459
- const rateLimit = "rateLimit" in options ? options.rateLimit : void 0;
460
- if (!hasPacingConfig(rateLimit)) {
461
- return null;
462
- }
463
- return {
464
- cooldownMs: normalizeNonNegativeInteger(rateLimit?.cooldownMs, 0),
465
- initialDelayMs: normalizeNonNegativeInteger(
466
- rateLimit?.initialDelayMs,
467
- 5e3
468
- ),
469
- key: rateLimit?.key?.trim() || deriveBudgetKey(options),
470
- maxAttempts: Math.max(
471
- 1,
472
- normalizeNonNegativeInteger(rateLimit?.maxAttempts, 1)
473
- )
474
- };
475
- }
476
- function getRetryDelayMs(error, config) {
477
- const hintedDelayMs = typeof error.retryAfter === "number" && Number.isFinite(error.retryAfter) ? Math.max(0, Math.ceil(error.retryAfter * 1e3)) : void 0;
478
- if (hintedDelayMs !== void 0) {
479
- return Math.max(config.cooldownMs, hintedDelayMs);
480
- }
481
- return Math.max(config.cooldownMs, config.initialDelayMs);
482
- }
483
- async function invokeWithPacing(execute, coordinator, config) {
484
- let attempt = 1;
485
- while (true) {
486
- await coordinator.waitUntilReady();
487
- try {
488
- const result = await execute();
489
- coordinator.delayFor(config.cooldownMs);
490
- return result;
491
- } catch (error) {
492
- if (error instanceof RateLimitError) {
493
- coordinator.delayFor(getRetryDelayMs(error, config));
494
- if (error.retryable && attempt < config.maxAttempts) {
495
- attempt += 1;
496
- continue;
497
- }
498
- }
499
- throw error;
500
- }
501
- }
502
- }
503
- function parseRetryAfterSeconds(retryAfter) {
504
- if (typeof retryAfter === "number" && Number.isFinite(retryAfter)) {
505
- return Math.max(0, retryAfter);
506
- }
507
- if (typeof retryAfter !== "string") {
508
- return void 0;
509
- }
510
- const trimmed = retryAfter.trim();
511
- if (!trimmed) {
512
- return void 0;
513
- }
514
- const seconds = Number.parseFloat(trimmed);
515
- if (!Number.isNaN(seconds)) {
516
- return Math.max(0, seconds);
517
- }
518
- const retryAt = Date.parse(trimmed);
519
- if (Number.isNaN(retryAt)) {
520
- return void 0;
521
- }
522
- return Math.max(0, Math.ceil((retryAt - Date.now()) / 1e3));
523
- }
524
- function getHeaderValue(headers, headerName) {
525
- if (!headers || typeof headers !== "object") {
526
- return void 0;
527
- }
528
- if ("get" in headers && typeof headers.get === "function") {
529
- return headers.get(headerName) ?? headers.get(headerName.toLowerCase());
530
- }
531
- const objectHeaders = headers;
532
- return objectHeaders[headerName] ?? objectHeaders[headerName.toLowerCase()];
533
- }
534
- function extractRetryAfterSeconds(error) {
535
- if (!error || typeof error !== "object") {
536
- return void 0;
537
- }
538
- if ("retryAfter" in error) {
539
- const retryAfter = parseRetryAfterSeconds(
540
- error.retryAfter
541
- );
542
- if (retryAfter !== void 0) {
543
- return retryAfter;
544
- }
545
- }
546
- if ("headers" in error) {
547
- const retryAfter = parseRetryAfterSeconds(
548
- getHeaderValue(error.headers, "retry-after")
549
- );
550
- if (retryAfter !== void 0) {
551
- return retryAfter;
552
- }
553
- }
554
- const message = "message" in error && typeof error.message === "string" ? error.message : "";
555
- const retryAfterMatch = message.match(/retry after\s+(\d+(?:\.\d+)?)\s*s?/i) ?? message.match(/retryDelay[^\d]*(\d+(?:\.\d+)?)s/i);
556
- return retryAfterMatch ? parseRetryAfterSeconds(retryAfterMatch[1]) : void 0;
557
- }
558
- function createRateLimitedAI(client, options) {
559
- const config = normalizeRateLimitConfig(options);
560
- if (!config) {
561
- return client;
562
- }
563
- const wrappedMethods = /* @__PURE__ */ new Map();
564
- return new Proxy(client, {
565
- get(target, property, receiver) {
566
- const value = Reflect.get(target, property, receiver);
567
- if (typeof value !== "function") {
568
- return value;
569
- }
570
- if (!RATE_LIMITED_METHODS.has(property)) {
571
- if (!wrappedMethods.has(property)) {
572
- wrappedMethods.set(property, value.bind(target));
573
- }
574
- return wrappedMethods.get(property);
575
- }
576
- if (!wrappedMethods.has(property)) {
577
- wrappedMethods.set(property, (...args) => {
578
- const coordinator = getBudgetCoordinator(config.key);
579
- return coordinator.schedule(
580
- () => invokeWithPacing(
581
- () => Reflect.apply(value, target, args),
582
- coordinator,
583
- config
584
- )
585
- );
586
- });
587
- }
588
- return wrappedMethods.get(property);
589
- }
590
- });
591
- }
592
- const DEFAULT_AI_TIMEOUT_MS = 12e4;
593
- const DEFAULT_AI_MAX_RETRIES = 0;
594
- const DEFAULT_AI_GENERATION_LIMITS = Object.freeze({
595
- maxOutputTokens: 4096,
596
- maxReasoningTokens: 1024,
597
- maxImagesPerRequest: 1,
598
- onExceeded: "error"
599
- });
600
- function positiveInteger(value, fallback, field) {
601
- if (value === void 0) return fallback;
602
- if (!Number.isFinite(value) || value <= 0) {
603
- throw new AIError(
604
- `${field} must be a positive finite number`,
605
- "AI_LIMIT_INVALID"
606
- );
607
- }
608
- return Math.trunc(value);
609
- }
610
- function normalizeBaseAIOptions(options) {
611
- const configuredLimits = options.generationLimits || {};
612
- const generationLimits = {
613
- maxOutputTokens: positiveInteger(
614
- configuredLimits.maxOutputTokens,
615
- DEFAULT_AI_GENERATION_LIMITS.maxOutputTokens,
616
- "generationLimits.maxOutputTokens"
617
- ),
618
- maxReasoningTokens: positiveInteger(
619
- configuredLimits.maxReasoningTokens,
620
- DEFAULT_AI_GENERATION_LIMITS.maxReasoningTokens,
621
- "generationLimits.maxReasoningTokens"
622
- ),
623
- maxImagesPerRequest: positiveInteger(
624
- configuredLimits.maxImagesPerRequest,
625
- DEFAULT_AI_GENERATION_LIMITS.maxImagesPerRequest,
626
- "generationLimits.maxImagesPerRequest"
627
- ),
628
- onExceeded: configuredLimits.onExceeded || DEFAULT_AI_GENERATION_LIMITS.onExceeded
629
- };
630
- if (!["error", "clamp"].includes(generationLimits.onExceeded)) {
631
- throw new AIError(
632
- 'generationLimits.onExceeded must be "error" or "clamp"',
633
- "AI_LIMIT_INVALID"
634
- );
635
- }
636
- return {
637
- ...options,
638
- timeout: positiveInteger(options.timeout, DEFAULT_AI_TIMEOUT_MS, "timeout"),
639
- maxRetries: (() => {
640
- if (options.maxRetries === void 0) return DEFAULT_AI_MAX_RETRIES;
641
- if (!Number.isFinite(options.maxRetries) || options.maxRetries < 0) {
642
- throw new AIError(
643
- "maxRetries must be a non-negative finite number",
644
- "AI_LIMIT_INVALID"
645
- );
646
- }
647
- return Math.trunc(options.maxRetries);
648
- })(),
649
- generationLimits
650
- };
651
- }
652
- function reasoningTokensForEffort(effort) {
653
- switch (effort) {
654
- case false:
655
- case "none":
656
- return 0;
657
- case "minimal":
658
- return 1024;
659
- case "low":
660
- return 2048;
661
- case "medium":
662
- return 4096;
663
- case "high":
664
- return 8192;
665
- default:
666
- return void 0;
667
- }
668
- }
669
- function enforceLimit(requested, limit, behavior, label, provider, model) {
670
- if (!Number.isFinite(requested) || requested < 0) {
671
- throw new AIError(
672
- `${label} must be a non-negative finite number`,
673
- "AI_LIMIT_INVALID",
674
- provider,
675
- model
676
- );
677
- }
678
- const normalized = Math.trunc(requested);
679
- if (normalized <= limit) return normalized;
680
- if (behavior === "clamp") return limit;
681
- throw new AIError(
682
- `${label} ${normalized} exceeds configured ceiling ${limit}`,
683
- "AI_LIMIT_EXCEEDED",
684
- provider,
685
- model
686
- );
687
- }
688
- function normalizeChatOptions(providerOptions, options, provider, model) {
689
- const normalizedProvider = normalizeBaseAIOptions(providerOptions);
690
- const limits = normalizedProvider.generationLimits;
691
- const requestedOutput = options.maxTokens ?? limits.maxOutputTokens;
692
- const legacyEffort = options.thinkingLevel ?? providerOptions.thinkingLevel;
693
- const reasoningWasRequested = options.reasoning !== void 0 || legacyEffort !== void 0 || options.includeThoughts === true;
694
- const requestedReasoning = reasoningWasRequested ? options.reasoning?.maxTokens ?? reasoningTokensForEffort(options.reasoning?.effort ?? legacyEffort) ?? limits.maxReasoningTokens : 0;
695
- return {
696
- ...options,
697
- maxTokens: enforceLimit(
698
- requestedOutput,
699
- limits.maxOutputTokens,
700
- limits.onExceeded,
701
- "maxTokens",
702
- provider,
703
- model
704
- ),
705
- reasoning: {
706
- ...options.reasoning,
707
- maxTokens: enforceLimit(
708
- requestedReasoning,
709
- limits.maxReasoningTokens,
710
- limits.onExceeded,
711
- "reasoning.maxTokens",
712
- provider,
713
- model
714
- ),
715
- includeThoughts: options.reasoning?.includeThoughts ?? options.includeThoughts
716
- }
717
- };
718
- }
719
- function normalizeImageGenerationOptions(providerOptions, options, provider, model) {
720
- const normalizedProvider = normalizeBaseAIOptions(providerOptions);
721
- const limits = normalizedProvider.generationLimits;
722
- return {
723
- ...options,
724
- n: enforceLimit(
725
- options.n ?? 1,
726
- limits.maxImagesPerRequest,
727
- limits.onExceeded,
728
- "n",
729
- provider,
730
- model
731
- )
732
- };
733
- }
734
- function prepareRequestControls(providerOptions, requestOptions = {}) {
735
- const normalized = normalizeBaseAIOptions(providerOptions);
736
- const timeout = positiveInteger(
737
- requestOptions.timeout,
738
- normalized.timeout,
739
- "timeout"
740
- );
741
- const controller = new AbortController();
742
- let timedOut = false;
743
- const abortFromCaller = () => controller.abort(requestOptions.signal?.reason);
744
- if (requestOptions.signal?.aborted) {
745
- abortFromCaller();
746
- } else {
747
- requestOptions.signal?.addEventListener("abort", abortFromCaller, {
748
- once: true
749
- });
750
- }
751
- const timer = setTimeout(() => {
752
- timedOut = true;
753
- controller.abort(new Error(`AI request timed out after ${timeout}ms`));
754
- }, timeout);
755
- return {
756
- signal: controller.signal,
757
- timeout,
758
- didTimeout: () => timedOut,
759
- cleanup: () => {
760
- clearTimeout(timer);
761
- requestOptions.signal?.removeEventListener("abort", abortFromCaller);
762
- }
763
- };
764
- }
765
- function mergeTags(providerOptions, callTags) {
766
- return providerOptions.usageTags || callTags ? { ...providerOptions.usageTags, ...callTags } : void 0;
767
- }
768
- function emitRequestEvent(providerOptions, event) {
769
- if (!providerOptions.onRequest) return;
770
- try {
771
- providerOptions.onRequest({
772
- ...event,
773
- tags: mergeTags(providerOptions, event.tags)
774
- });
775
- } catch {
776
- }
777
- }
778
- function classifyRequestFailure(error, didTimeout = false) {
779
- const code = error instanceof AIError ? error.code : void 0;
780
- if (code === "AI_LIMIT_EXCEEDED" || code === "AI_LIMIT_INVALID") {
781
- return { status: "rejected", errorCode: code };
782
- }
783
- if (didTimeout || code === "AI_TIMEOUT" || code === "TIMEOUT") {
784
- return { status: "timed_out", errorCode: code || "AI_TIMEOUT" };
785
- }
786
- if (error instanceof Error && error.name === "AbortError") {
787
- return { status: "aborted", errorCode: "ABORTED" };
788
- }
789
- if (code === "AI_ABORTED") {
790
- return { status: "aborted", errorCode: code };
791
- }
792
- return {
793
- status: "failed",
794
- errorCode: code || (error instanceof Error ? error.name : void 0)
795
- };
796
- }
797
- function requestEventBase(options) {
798
- const normalized = normalizeBaseAIOptions(options.providerOptions);
799
- return {
800
- provider: options.provider,
801
- model: options.model,
802
- operation: options.operation,
803
- attempts: normalized.maxRetries + 1,
804
- requestedMaxOutputTokens: options.callOptions?.maxTokens,
805
- effectiveMaxOutputTokens: options.operation === "generateImage" ? void 0 : options.effectiveMaxOutputTokens ?? normalized.generationLimits.maxOutputTokens,
806
- tags: options.callOptions?.usageTags
807
- };
808
- }
809
- const OBSERVED_OPERATIONS = /* @__PURE__ */ new Set([
810
- "chat",
811
- "complete",
812
- "message",
813
- "describeImage",
814
- "generateImage",
815
- "stream"
816
- ]);
817
- function callOptionsFor(operation, args) {
818
- const index = operation === "describeImage" ? 2 : 1;
819
- const value = args[index];
820
- return value && typeof value === "object" ? value : void 0;
821
- }
822
- function providerName(options) {
823
- const configured = options.type;
824
- return configured || "openai";
825
- }
826
- function effectiveOutputTokens(operation, providerOptions, callOptions) {
827
- if (operation === "generateImage") {
828
- normalizeImageGenerationOptions(
829
- providerOptions,
830
- callOptions || {},
831
- providerName(providerOptions),
832
- callOptions?.model
833
- );
834
- return void 0;
835
- }
836
- return normalizeChatOptions(
837
- providerOptions,
838
- callOptions || {},
839
- providerName(providerOptions),
840
- callOptions?.model || providerOptions.defaultModel
841
- ).maxTokens;
842
- }
843
- function createObservedAI(client, providerOptions) {
844
- if (!providerOptions.onRequest) return client;
845
- return new Proxy(client, {
846
- get(target, property, receiver) {
847
- const value = Reflect.get(target, property, receiver);
848
- if (typeof property !== "string" || typeof value !== "function" || !OBSERVED_OPERATIONS.has(property)) {
849
- return typeof value === "function" ? value.bind(target) : value;
850
- }
851
- const operation = property;
852
- if (operation === "stream") {
853
- return async function* (...args) {
854
- const startedAt = Date.now();
855
- const callOptions = callOptionsFor(operation, args);
856
- let base;
857
- try {
858
- base = requestEventBase({
859
- providerOptions,
860
- provider: providerName(providerOptions),
861
- model: callOptions?.model || providerOptions.defaultModel || "unknown",
862
- operation,
863
- callOptions,
864
- effectiveMaxOutputTokens: effectiveOutputTokens(
865
- operation,
866
- providerOptions,
867
- callOptions
868
- )
869
- });
870
- const iterable = Reflect.apply(
871
- value,
872
- target,
873
- args
874
- );
875
- for await (const chunk of iterable) yield chunk;
876
- emitRequestEvent(providerOptions, {
877
- ...base,
878
- status: "succeeded",
879
- duration: Date.now() - startedAt
880
- });
881
- } catch (error) {
882
- const failure = classifyRequestFailure(error);
883
- base ||= requestEventBase({
884
- providerOptions,
885
- provider: providerName(providerOptions),
886
- model: callOptions?.model || providerOptions.defaultModel || "unknown",
887
- operation,
888
- callOptions
889
- });
890
- emitRequestEvent(providerOptions, {
891
- ...base,
892
- ...failure,
893
- duration: Date.now() - startedAt
894
- });
895
- throw error;
896
- }
897
- };
898
- }
899
- return async (...args) => {
900
- const startedAt = Date.now();
901
- const callOptions = callOptionsFor(operation, args);
902
- let base;
903
- try {
904
- base = requestEventBase({
905
- providerOptions,
906
- provider: providerName(providerOptions),
907
- model: callOptions?.model || providerOptions.defaultModel || "unknown",
908
- operation,
909
- callOptions,
910
- effectiveMaxOutputTokens: effectiveOutputTokens(
911
- operation,
912
- providerOptions,
913
- callOptions
914
- )
915
- });
916
- const result = await Reflect.apply(value, target, args);
917
- emitRequestEvent(providerOptions, {
918
- ...base,
919
- status: "succeeded",
920
- duration: Date.now() - startedAt
921
- });
922
- return result;
923
- } catch (error) {
924
- const failure = classifyRequestFailure(error);
925
- base ||= requestEventBase({
926
- providerOptions,
927
- provider: providerName(providerOptions),
928
- model: callOptions?.model || providerOptions.defaultModel || "unknown",
929
- operation,
930
- callOptions
931
- });
932
- emitRequestEvent(providerOptions, {
933
- ...base,
934
- ...failure,
935
- duration: Date.now() - startedAt
936
- });
937
- throw error;
938
- }
939
- };
940
- }
941
- });
942
- }
943
- function isOpenAIOptions(options) {
944
- return !options.type || options.type === "openai";
945
- }
946
- function isLiteLLMOptions(options) {
947
- return options.type === "litellm";
948
- }
949
- function isBifrostOptions(options) {
950
- return options.type === "bifrost";
951
- }
952
- function isOllamaOptions(options) {
953
- return options.type === "ollama";
954
- }
955
- function isGeminiOptions(options) {
956
- return options.type === "gemini";
957
- }
958
- function isAnthropicOptions(options) {
959
- return options.type === "anthropic";
960
- }
961
- function isHuggingFaceOptions(options) {
962
- return options.type === "huggingface";
963
- }
964
- function isBedrockOptions(options) {
965
- return options.type === "bedrock";
966
- }
967
- function isClaudeCliOptions(options) {
968
- return options.type === "claude-cli";
969
- }
970
- function isQwen3TTSOptions(options) {
971
- return options.type === "qwen3-tts";
972
- }
973
- async function getAI(options = {}) {
974
- options = loadEnvConfig(options, {
975
- packageName: "ai",
976
- schema: {
977
- provider: "string",
978
- type: "string",
979
- // Alias for provider
980
- model: "string",
981
- defaultModel: "string",
982
- timeout: "number",
983
- maxRetries: "number",
984
- apiKey: "string",
985
- baseUrl: "string",
986
- adminApiKey: "string",
987
- adminBaseUrl: "string",
988
- adminUrl: "string",
989
- adminUser: "string",
990
- adminUsername: "string",
991
- adminPassword: "string"
992
- }
993
- });
994
- if ("provider" in options && !options.type) {
995
- options.type = options.provider;
996
- }
997
- if ("model" in options && !options.defaultModel) {
998
- options.defaultModel = options.model;
999
- }
1000
- options = normalizeBaseAIOptions(options);
1001
- let client;
1002
- if (isOpenAIOptions(options)) {
1003
- const { OpenAIProvider } = await import("./openai-CJEo69jb.js");
1004
- client = new OpenAIProvider(options);
1005
- } else if (isLiteLLMOptions(options)) {
1006
- const { LiteLLMProvider } = await import("./litellm-BMFTYbWc.js");
1007
- client = new LiteLLMProvider(options);
1008
- } else if (isBifrostOptions(options)) {
1009
- const { BifrostProvider } = await import("./bifrost-CEnCsciy.js");
1010
- client = new BifrostProvider(options);
1011
- } else if (isOllamaOptions(options)) {
1012
- const { OllamaProvider } = await import("./ollama-DsGDrA-c.js");
1013
- client = new OllamaProvider(options);
1014
- } else if (isGeminiOptions(options)) {
1015
- const { GeminiProvider } = await import("./gemini-CS56gY0D.js");
1016
- client = new GeminiProvider(options);
1017
- } else if (isAnthropicOptions(options)) {
1018
- const { AnthropicProvider } = await import("./anthropic-2z-82zgr.js");
1019
- client = new AnthropicProvider(options);
1020
- } else if (isHuggingFaceOptions(options)) {
1021
- const { HuggingFaceProvider } = await import("./huggingface-wQSfO5xA.js");
1022
- client = new HuggingFaceProvider(options);
1023
- } else if (isBedrockOptions(options)) {
1024
- const { BedrockProvider } = await import("./bedrock-Dc2eVPUD.js");
1025
- client = new BedrockProvider(options);
1026
- } else if (isClaudeCliOptions(options)) {
1027
- const { ClaudeCliProvider } = await import("./claude-cli-X1ONjE8K.js");
1028
- client = new ClaudeCliProvider(options);
1029
- } else if (isQwen3TTSOptions(options)) {
1030
- const { Qwen3TTSProvider } = await import("./qwen-tts-BLYZ6d9s.js");
1031
- client = new Qwen3TTSProvider(options);
1032
- } else {
1033
- throw new ValidationError("Unsupported AI provider type", {
1034
- supportedTypes: [...AI_PROVIDER_TYPES],
1035
- providedType: options.type
1036
- });
1037
- }
1038
- return createObservedAI(createRateLimitedAI(client, options), options);
1039
- }
1040
- async function getAIAuto(options) {
1041
- const baseUrl = String(options.baseUrl || "");
1042
- const hasKeepAliveOption = "keepAlive" in options && options.keepAlive !== void 0;
1043
- if (/((?:localhost|127\.0\.0\.1)(?::11434)?(?:\/(?:api|v1))?|ollama(?:\.com)?(?:\/(?:api|v1))?)\/?$/i.test(
1044
- baseUrl
1045
- ) || hasKeepAliveOption) {
1046
- return getAI({ ...options, type: "ollama" });
1047
- }
1048
- if (options.apiKey && !options.type) {
1049
- return getAI({ ...options, type: "openai" });
1050
- }
1051
- if (options.apiToken) {
1052
- return getAI({ ...options, type: "huggingface" });
1053
- }
1054
- if (options.region && options.credentials) {
1055
- return getAI({ ...options, type: "bedrock" });
1056
- }
1057
- if (options.projectId || options.anthropicVersion) {
1058
- if (options.anthropicVersion) {
1059
- return getAI({ ...options, type: "anthropic" });
1060
- }
1061
- if (options.projectId) {
1062
- return getAI({ ...options, type: "gemini" });
1063
- }
1064
- }
1065
- throw new ValidationError("Could not auto-detect AI provider from options", {
1066
- hint: 'Please specify a "type" field in options or provide provider-specific credentials',
1067
- supportedTypes: [...AI_PROVIDER_TYPES],
1068
- providedOptions: Object.keys(options)
1069
- });
1070
- }
1071
- const factory = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1072
- __proto__: null,
1073
- getAI,
1074
- getAIAuto
1075
- }, Symbol.toStringTag, { value: "Module" }));
1076
- class AIMessage {
1077
- /**
1078
- * Original options used to create this message
1079
- */
1080
- options;
1081
- /**
1082
- * Name of the message sender
1083
- */
1084
- name;
1085
- /**
1086
- * Content of the message
1087
- */
1088
- content;
1089
- /**
1090
- * Role of the message sender in the conversation
1091
- */
1092
- role;
1093
- /**
1094
- * Creates a new AI message
1095
- *
1096
- * @param options - Message configuration
1097
- * @param options.role - Role of the message sender
1098
- * @param options.content - Content of the message
1099
- * @param options.name - Name of the message sender
1100
- */
1101
- constructor(options) {
1102
- this.options = options;
1103
- this.role = options.role;
1104
- this.content = options.content;
1105
- this.name = options.name;
1106
- }
1107
- /**
1108
- * Factory method to create a new AI message
1109
- *
1110
- * @param options - Message configuration
1111
- * @param options.thread - Thread this message belongs to
1112
- * @param options.role - Role of the message sender
1113
- * @param options.content - Content of the message
1114
- * @param options.name - Name of the message sender
1115
- * @returns Promise resolving to a new AIMessage instance
1116
- */
1117
- static async create(options) {
1118
- return new AIMessage(options);
1119
- }
1120
- }
1121
- class AIThread {
1122
- /**
1123
- * AI client instance for this thread
1124
- */
1125
- ai;
1126
- /**
1127
- * Options used to configure this thread
1128
- */
1129
- options;
1130
- /**
1131
- * Messages in this conversation thread
1132
- */
1133
- messages = [];
1134
- /**
1135
- * Reference materials to include in the conversation context
1136
- */
1137
- references = {};
1138
- /**
1139
- * Creates a new AI thread
1140
- *
1141
- * @param options - Thread configuration options
1142
- */
1143
- constructor(options) {
1144
- this.options = options;
1145
- }
1146
- /**
1147
- * Factory method to create and initialize a new AI thread
1148
- *
1149
- * @param options - Thread configuration options
1150
- * @returns Promise resolving to an initialized AIThread
1151
- */
1152
- static async create(options) {
1153
- const thread = new AIThread(options);
1154
- await thread.initialize();
1155
- return thread;
1156
- }
1157
- /**
1158
- * Initializes the AI client for this thread
1159
- */
1160
- async initialize() {
1161
- this.ai = await AIClient.create(this.options.ai);
1162
- }
1163
- /**
1164
- * Adds a system message to the conversation
1165
- *
1166
- * @param prompt - System message content
1167
- * @returns Promise resolving to the created AIMessage
1168
- */
1169
- async addSystem(prompt) {
1170
- const message = await AIMessage.create({
1171
- thread: this,
1172
- role: "system",
1173
- name: "system",
1174
- content: prompt
1175
- });
1176
- this.messages.push(message);
1177
- return message;
1178
- }
1179
- /**
1180
- * Adds a message to the conversation
1181
- *
1182
- * @param options - Message options
1183
- * @param options.role - Role of the message sender
1184
- * @param options.name - Optional name of the message sender
1185
- * @param options.content - Content of the message
1186
- * @returns Promise resolving to the created AIMessage
1187
- */
1188
- async add(options) {
1189
- const message = await AIMessage.create({
1190
- thread: this,
1191
- role: options.role,
1192
- name: options.name || options.role,
1193
- // Default name to role if not provided
1194
- content: options.content
1195
- });
1196
- this.messages.push(message);
1197
- return message;
1198
- }
1199
- /**
1200
- * Gets all messages in this thread
1201
- *
1202
- * @returns Array of AIMessage objects
1203
- */
1204
- get() {
1205
- return this.messages;
1206
- }
1207
- /**
1208
- * Adds a reference to be included in the conversation context
1209
- *
1210
- * @param name - Name of the reference
1211
- * @param body - Content of the reference
1212
- */
1213
- addReference(name, body) {
1214
- this.references[name] = body;
1215
- }
1216
- /**
1217
- * Assembles the conversation history for sending to the AI
1218
- * Properly orders system message, references, and conversation messages
1219
- *
1220
- * @returns Array of message parameters formatted for the OpenAI API
1221
- */
1222
- assembleHistory() {
1223
- const history = [];
1224
- const systemMessage = this.messages.find((m) => m.role === "system");
1225
- if (systemMessage) {
1226
- history.push({
1227
- role: systemMessage.role,
1228
- content: systemMessage.content
1229
- });
1230
- }
1231
- for (const name in this.references) {
1232
- history.push({
1233
- role: "user",
1234
- content: `Reference - ${name}:
1235
- ${this.references[name]}`
1236
- });
1237
- }
1238
- this.messages.filter((m) => m.role !== "system").forEach((message) => {
1239
- history.push({ role: message.role, content: message.content });
1240
- });
1241
- return history;
1242
- }
1243
- /**
1244
- * Sends a prompt to the AI and gets a response
1245
- *
1246
- * @param prompt - Prompt message to send
1247
- * @param options - Options for the AI response
1248
- * @param options.responseFormat - Format for the AI to respond with
1249
- * @returns Promise resolving to the AI response
1250
- */
1251
- async do(prompt, options = {
1252
- responseFormat: "text"
1253
- }) {
1254
- const { responseFormat } = options;
1255
- const history = this.assembleHistory();
1256
- const response = await this.ai.textCompletion(prompt, {
1257
- history,
1258
- responseFormat: {
1259
- type: responseFormat === "json" ? "json_object" : "text"
1260
- }
1261
- });
1262
- return response;
1263
- }
1264
- }
1265
- const PACKAGE_VERSION_INITIALIZED = true;
1266
- export {
1267
- AIError as A,
1268
- ContentFilterError as C,
1269
- DEFAULT_AI_GENERATION_LIMITS as D,
1270
- ModelNotFoundError as M,
1271
- OpenAIClient as O,
1272
- PACKAGE_VERSION_INITIALIZED as P,
1273
- RateLimitError as R,
1274
- normalizeImageGenerationOptions as a,
1275
- normalizeBaseAIOptions as b,
1276
- ContextLengthError as c,
1277
- AuthenticationError as d,
1278
- extractRetryAfterSeconds as e,
1279
- extractTextContent as f,
1280
- AIClient as g,
1281
- AIMessage as h,
1282
- AIThread as i,
1283
- AI_PROVIDER_TYPES as j,
1284
- DEFAULT_AI_MAX_RETRIES as k,
1285
- DEFAULT_AI_TIMEOUT_MS as l,
1286
- getAI as m,
1287
- normalizeChatOptions as n,
1288
- getAIAuto as o,
1289
- prepareRequestControls as p,
1290
- getAIClient as q,
1291
- getOpenAI as r
1292
- };
1293
- //# sourceMappingURL=index-DCXO0nZA.js.map