@adpal/shared-lib 1.0.1 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +69 -1
- package/dist/index.d.ts +69 -1
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +38 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -292,6 +292,74 @@ declare function retryApiCall<T>(fn: () => Promise<T>, options?: Pick<RetryOptio
|
|
|
292
292
|
* );
|
|
293
293
|
*/
|
|
294
294
|
declare function retryCritical<T>(fn: () => Promise<T>, options?: Pick<RetryOptions, 'logger' | 'onRetry'>): Promise<T>;
|
|
295
|
+
/**
|
|
296
|
+
* Опции для withFallback
|
|
297
|
+
*/
|
|
298
|
+
interface FallbackOptions<T> extends RetryOptions {
|
|
299
|
+
/** Значение по умолчанию при неудаче */
|
|
300
|
+
fallback: T | (() => T);
|
|
301
|
+
/** Не логировать ошибку (используется когда fallback ожидаем) */
|
|
302
|
+
silent?: boolean;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Выполнить функцию с retry и fallback значением при неудаче
|
|
306
|
+
*
|
|
307
|
+
* Используется для graceful degradation — когда операция может упасть,
|
|
308
|
+
* но мы хотим продолжить работу с дефолтным значением.
|
|
309
|
+
*
|
|
310
|
+
* @param fn - Асинхронная функция для выполнения
|
|
311
|
+
* @param options - Опции с обязательным fallback
|
|
312
|
+
* @returns Результат выполнения или fallback значение
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* // Rerank с fallback на исходные результаты
|
|
316
|
+
* const reranked = await withFallback(
|
|
317
|
+
* () => rerankResults(query, results),
|
|
318
|
+
* {
|
|
319
|
+
* fallback: results,
|
|
320
|
+
* maxAttempts: 2,
|
|
321
|
+
* logger: voyageLogger,
|
|
322
|
+
* }
|
|
323
|
+
* );
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* // Получить настройки с fallback на defaults
|
|
327
|
+
* const settings = await withFallback(
|
|
328
|
+
* () => fetchUserSettings(userId),
|
|
329
|
+
* {
|
|
330
|
+
* fallback: () => DEFAULT_SETTINGS,
|
|
331
|
+
* silent: true, // Не логировать, если настройки не найдены
|
|
332
|
+
* }
|
|
333
|
+
* );
|
|
334
|
+
*/
|
|
335
|
+
declare function withFallback<T>(fn: () => Promise<T>, options: FallbackOptions<T>): Promise<T>;
|
|
336
|
+
/**
|
|
337
|
+
* Результат операции с информацией об использовании fallback
|
|
338
|
+
*/
|
|
339
|
+
interface FallbackResult<T> {
|
|
340
|
+
/** Результат (данные или fallback) */
|
|
341
|
+
data: T;
|
|
342
|
+
/** true если использован fallback */
|
|
343
|
+
usedFallback: boolean;
|
|
344
|
+
/** Ошибка, если была */
|
|
345
|
+
error?: Error;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Версия withFallback, которая возвращает информацию об использовании fallback
|
|
349
|
+
*
|
|
350
|
+
* Полезно когда нужно знать, пришли ли данные из источника или из fallback.
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* const { data, usedFallback } = await withFallbackInfo(
|
|
354
|
+
* () => fetchLiveData(),
|
|
355
|
+
* { fallback: cachedData }
|
|
356
|
+
* );
|
|
357
|
+
*
|
|
358
|
+
* if (usedFallback) {
|
|
359
|
+
* console.log('Показываем кэшированные данные');
|
|
360
|
+
* }
|
|
361
|
+
*/
|
|
362
|
+
declare function withFallbackInfo<T>(fn: () => Promise<T>, options: FallbackOptions<T>): Promise<FallbackResult<T>>;
|
|
295
363
|
|
|
296
364
|
/**
|
|
297
365
|
* Zod схемы для валидации API ответов
|
|
@@ -773,4 +841,4 @@ declare function safeParse<T>(schema: z.ZodType<T>, data: unknown): T | null;
|
|
|
773
841
|
*/
|
|
774
842
|
declare function parseOrThrow<T>(schema: z.ZodType<T>, data: unknown, errorMessage?: string): T;
|
|
775
843
|
|
|
776
|
-
export { AnthropicApiError, ApiError, AppError, type ChatRequest, ChatRequestSchema, type ClaudeMessage, ClaudeMessageSchema, ConfigError, type LogLevel, type LogMeta, Logger, type RetryOptions, type RetryResult, type Source, SourceSchema, TurbopufferApiError, type TurbopufferSearchResult, TurbopufferSearchResultSchema, ValidationError, type VectorAttributes, VectorAttributesSchema, VoyageApiError, type VoyageEmbeddingResponse, VoyageEmbeddingResponseSchema, type VoyageRerankResponse, VoyageRerankResponseSchema, anthropicLogger, apiLogger, createTimer, isAppError, logger, parseOrThrow, retryApiCall, retryCritical, safeParse, sleep, turbopufferLogger, voyageLogger, withRetry, wrapError };
|
|
844
|
+
export { AnthropicApiError, ApiError, AppError, type ChatRequest, ChatRequestSchema, type ClaudeMessage, ClaudeMessageSchema, ConfigError, type FallbackOptions, type FallbackResult, type LogLevel, type LogMeta, Logger, type RetryOptions, type RetryResult, type Source, SourceSchema, TurbopufferApiError, type TurbopufferSearchResult, TurbopufferSearchResultSchema, ValidationError, type VectorAttributes, VectorAttributesSchema, VoyageApiError, type VoyageEmbeddingResponse, VoyageEmbeddingResponseSchema, type VoyageRerankResponse, VoyageRerankResponseSchema, anthropicLogger, apiLogger, createTimer, isAppError, logger, parseOrThrow, retryApiCall, retryCritical, safeParse, sleep, turbopufferLogger, voyageLogger, withFallback, withFallbackInfo, withRetry, wrapError };
|
package/dist/index.d.ts
CHANGED
|
@@ -292,6 +292,74 @@ declare function retryApiCall<T>(fn: () => Promise<T>, options?: Pick<RetryOptio
|
|
|
292
292
|
* );
|
|
293
293
|
*/
|
|
294
294
|
declare function retryCritical<T>(fn: () => Promise<T>, options?: Pick<RetryOptions, 'logger' | 'onRetry'>): Promise<T>;
|
|
295
|
+
/**
|
|
296
|
+
* Опции для withFallback
|
|
297
|
+
*/
|
|
298
|
+
interface FallbackOptions<T> extends RetryOptions {
|
|
299
|
+
/** Значение по умолчанию при неудаче */
|
|
300
|
+
fallback: T | (() => T);
|
|
301
|
+
/** Не логировать ошибку (используется когда fallback ожидаем) */
|
|
302
|
+
silent?: boolean;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Выполнить функцию с retry и fallback значением при неудаче
|
|
306
|
+
*
|
|
307
|
+
* Используется для graceful degradation — когда операция может упасть,
|
|
308
|
+
* но мы хотим продолжить работу с дефолтным значением.
|
|
309
|
+
*
|
|
310
|
+
* @param fn - Асинхронная функция для выполнения
|
|
311
|
+
* @param options - Опции с обязательным fallback
|
|
312
|
+
* @returns Результат выполнения или fallback значение
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* // Rerank с fallback на исходные результаты
|
|
316
|
+
* const reranked = await withFallback(
|
|
317
|
+
* () => rerankResults(query, results),
|
|
318
|
+
* {
|
|
319
|
+
* fallback: results,
|
|
320
|
+
* maxAttempts: 2,
|
|
321
|
+
* logger: voyageLogger,
|
|
322
|
+
* }
|
|
323
|
+
* );
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* // Получить настройки с fallback на defaults
|
|
327
|
+
* const settings = await withFallback(
|
|
328
|
+
* () => fetchUserSettings(userId),
|
|
329
|
+
* {
|
|
330
|
+
* fallback: () => DEFAULT_SETTINGS,
|
|
331
|
+
* silent: true, // Не логировать, если настройки не найдены
|
|
332
|
+
* }
|
|
333
|
+
* );
|
|
334
|
+
*/
|
|
335
|
+
declare function withFallback<T>(fn: () => Promise<T>, options: FallbackOptions<T>): Promise<T>;
|
|
336
|
+
/**
|
|
337
|
+
* Результат операции с информацией об использовании fallback
|
|
338
|
+
*/
|
|
339
|
+
interface FallbackResult<T> {
|
|
340
|
+
/** Результат (данные или fallback) */
|
|
341
|
+
data: T;
|
|
342
|
+
/** true если использован fallback */
|
|
343
|
+
usedFallback: boolean;
|
|
344
|
+
/** Ошибка, если была */
|
|
345
|
+
error?: Error;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Версия withFallback, которая возвращает информацию об использовании fallback
|
|
349
|
+
*
|
|
350
|
+
* Полезно когда нужно знать, пришли ли данные из источника или из fallback.
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* const { data, usedFallback } = await withFallbackInfo(
|
|
354
|
+
* () => fetchLiveData(),
|
|
355
|
+
* { fallback: cachedData }
|
|
356
|
+
* );
|
|
357
|
+
*
|
|
358
|
+
* if (usedFallback) {
|
|
359
|
+
* console.log('Показываем кэшированные данные');
|
|
360
|
+
* }
|
|
361
|
+
*/
|
|
362
|
+
declare function withFallbackInfo<T>(fn: () => Promise<T>, options: FallbackOptions<T>): Promise<FallbackResult<T>>;
|
|
295
363
|
|
|
296
364
|
/**
|
|
297
365
|
* Zod схемы для валидации API ответов
|
|
@@ -773,4 +841,4 @@ declare function safeParse<T>(schema: z.ZodType<T>, data: unknown): T | null;
|
|
|
773
841
|
*/
|
|
774
842
|
declare function parseOrThrow<T>(schema: z.ZodType<T>, data: unknown, errorMessage?: string): T;
|
|
775
843
|
|
|
776
|
-
export { AnthropicApiError, ApiError, AppError, type ChatRequest, ChatRequestSchema, type ClaudeMessage, ClaudeMessageSchema, ConfigError, type LogLevel, type LogMeta, Logger, type RetryOptions, type RetryResult, type Source, SourceSchema, TurbopufferApiError, type TurbopufferSearchResult, TurbopufferSearchResultSchema, ValidationError, type VectorAttributes, VectorAttributesSchema, VoyageApiError, type VoyageEmbeddingResponse, VoyageEmbeddingResponseSchema, type VoyageRerankResponse, VoyageRerankResponseSchema, anthropicLogger, apiLogger, createTimer, isAppError, logger, parseOrThrow, retryApiCall, retryCritical, safeParse, sleep, turbopufferLogger, voyageLogger, withRetry, wrapError };
|
|
844
|
+
export { AnthropicApiError, ApiError, AppError, type ChatRequest, ChatRequestSchema, type ClaudeMessage, ClaudeMessageSchema, ConfigError, type FallbackOptions, type FallbackResult, type LogLevel, type LogMeta, Logger, type RetryOptions, type RetryResult, type Source, SourceSchema, TurbopufferApiError, type TurbopufferSearchResult, TurbopufferSearchResultSchema, ValidationError, type VectorAttributes, VectorAttributesSchema, VoyageApiError, type VoyageEmbeddingResponse, VoyageEmbeddingResponseSchema, type VoyageRerankResponse, VoyageRerankResponseSchema, anthropicLogger, apiLogger, createTimer, isAppError, logger, parseOrThrow, retryApiCall, retryCritical, safeParse, sleep, turbopufferLogger, voyageLogger, withFallback, withFallbackInfo, withRetry, wrapError };
|
package/dist/index.js
CHANGED
|
@@ -394,6 +394,43 @@ async function retryCritical(fn, options = {}) {
|
|
|
394
394
|
});
|
|
395
395
|
return result.data;
|
|
396
396
|
}
|
|
397
|
+
async function withFallback(fn, options) {
|
|
398
|
+
const { fallback, silent = false, logger: logger2, ...retryOptions } = options;
|
|
399
|
+
try {
|
|
400
|
+
const result = await withRetry(fn, { ...retryOptions, logger: logger2 });
|
|
401
|
+
return result.data;
|
|
402
|
+
} catch (error) {
|
|
403
|
+
if (!silent && logger2) {
|
|
404
|
+
logger2.warn("\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043D\u0435 \u0443\u0434\u0430\u043B\u0430\u0441\u044C, \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u043C fallback", {
|
|
405
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
406
|
+
errorType: error instanceof Error ? error.constructor.name : typeof error
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
return typeof fallback === "function" ? fallback() : fallback;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
async function withFallbackInfo(fn, options) {
|
|
413
|
+
const { fallback, silent = false, logger: logger2, ...retryOptions } = options;
|
|
414
|
+
try {
|
|
415
|
+
const result = await withRetry(fn, { ...retryOptions, logger: logger2 });
|
|
416
|
+
return {
|
|
417
|
+
data: result.data,
|
|
418
|
+
usedFallback: false
|
|
419
|
+
};
|
|
420
|
+
} catch (error) {
|
|
421
|
+
if (!silent && logger2) {
|
|
422
|
+
logger2.warn("\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043D\u0435 \u0443\u0434\u0430\u043B\u0430\u0441\u044C, \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u043C fallback", {
|
|
423
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
const fallbackValue = typeof fallback === "function" ? fallback() : fallback;
|
|
427
|
+
return {
|
|
428
|
+
data: fallbackValue,
|
|
429
|
+
usedFallback: true,
|
|
430
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
}
|
|
397
434
|
var VoyageEmbeddingResponseSchema = zod.z.object({
|
|
398
435
|
/** Массив эмбеддингов */
|
|
399
436
|
data: zod.z.array(
|
|
@@ -571,6 +608,8 @@ exports.safeParse = safeParse;
|
|
|
571
608
|
exports.sleep = sleep;
|
|
572
609
|
exports.turbopufferLogger = turbopufferLogger;
|
|
573
610
|
exports.voyageLogger = voyageLogger;
|
|
611
|
+
exports.withFallback = withFallback;
|
|
612
|
+
exports.withFallbackInfo = withFallbackInfo;
|
|
574
613
|
exports.withRetry = withRetry;
|
|
575
614
|
exports.wrapError = wrapError;
|
|
576
615
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/logger.ts","../src/retry.ts","../src/schemas.ts"],"names":["logger","z"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Кастомные классы ошибок\n *\n * Иерархия ошибок для структурированной обработки исключений.\n * Каждый класс содержит дополнительный контекст для отладки.\n *\n * @module errors\n */\n\n// ============================================================================\n// Базовый класс\n// ============================================================================\n\n/**\n * Базовый класс для всех ошибок приложения\n *\n * Расширяет стандартный Error с дополнительными полями:\n * - code: машиночитаемый код ошибки\n * - context: дополнительные данные для отладки\n * - retryable: можно ли повторить операцию\n */\nexport class AppError extends Error {\n /** Машиночитаемый код ошибки */\n readonly code: string;\n /** Дополнительный контекст для отладки */\n readonly context?: Record<string, unknown>;\n /** Можно ли повторить операцию */\n readonly retryable: boolean;\n /** Временная метка создания ошибки */\n readonly timestamp: Date;\n\n constructor(\n message: string,\n options: {\n code?: string;\n context?: Record<string, unknown>;\n retryable?: boolean;\n cause?: Error;\n } = {}\n ) {\n super(message, { cause: options.cause });\n this.name = 'AppError';\n this.code = options.code || 'APP_ERROR';\n this.context = options.context;\n this.retryable = options.retryable ?? false;\n this.timestamp = new Date();\n }\n\n /**\n * Преобразовать в JSON для логирования\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n context: this.context,\n retryable: this.retryable,\n timestamp: this.timestamp.toISOString(),\n stack: this.stack,\n };\n }\n}\n\n// ============================================================================\n// Ошибки API\n// ============================================================================\n\n/**\n * Ошибка при вызове внешнего API\n *\n * Используется для Voyage AI, Anthropic, Turbopuffer.\n */\nexport class ApiError extends AppError {\n /** HTTP статус код */\n readonly statusCode: number;\n /** Имя сервиса */\n readonly service: string;\n\n constructor(\n message: string,\n options: {\n statusCode: number;\n service: string;\n context?: Record<string, unknown>;\n retryable?: boolean;\n cause?: Error;\n }\n ) {\n super(message, {\n code: `${options.service.toUpperCase()}_API_ERROR`,\n context: { ...options.context, statusCode: options.statusCode },\n retryable: options.retryable ?? isRetryableStatus(options.statusCode),\n cause: options.cause,\n });\n this.name = 'ApiError';\n this.statusCode = options.statusCode;\n this.service = options.service;\n }\n}\n\n/**\n * Ошибка Voyage AI API\n */\nexport class VoyageApiError extends ApiError {\n constructor(\n message: string,\n statusCode: number,\n context?: Record<string, unknown>\n ) {\n super(message, {\n statusCode,\n service: 'voyage',\n context,\n });\n this.name = 'VoyageApiError';\n }\n}\n\n/**\n * Ошибка Anthropic API\n */\nexport class AnthropicApiError extends ApiError {\n constructor(\n message: string,\n statusCode: number,\n context?: Record<string, unknown>\n ) {\n super(message, {\n statusCode,\n service: 'anthropic',\n context,\n });\n this.name = 'AnthropicApiError';\n }\n}\n\n/**\n * Ошибка Turbopuffer API\n */\nexport class TurbopufferApiError extends ApiError {\n constructor(\n message: string,\n statusCode: number,\n context?: Record<string, unknown>\n ) {\n super(message, {\n statusCode,\n service: 'turbopuffer',\n context,\n });\n this.name = 'TurbopufferApiError';\n }\n}\n\n// ============================================================================\n// Ошибки валидации\n// ============================================================================\n\n/**\n * Ошибка валидации данных\n *\n * Используется при невалидных входных данных или ответах API.\n */\nexport class ValidationError extends AppError {\n /** Поле, в котором обнаружена ошибка */\n readonly field?: string;\n /** Ожидаемое значение или тип */\n readonly expected?: string;\n /** Полученное значение */\n readonly received?: unknown;\n\n constructor(\n message: string,\n options: {\n field?: string;\n expected?: string;\n received?: unknown;\n context?: Record<string, unknown>;\n } = {}\n ) {\n super(message, {\n code: 'VALIDATION_ERROR',\n context: {\n ...options.context,\n field: options.field,\n expected: options.expected,\n received: options.received,\n },\n retryable: false,\n });\n this.name = 'ValidationError';\n this.field = options.field;\n this.expected = options.expected;\n this.received = options.received;\n }\n}\n\n// ============================================================================\n// Ошибки конфигурации\n// ============================================================================\n\n/**\n * Ошибка отсутствующей конфигурации\n *\n * Используется при отсутствии обязательных переменных окружения.\n */\nexport class ConfigError extends AppError {\n /** Имя отсутствующей переменной */\n readonly variableName: string;\n\n constructor(variableName: string) {\n super(`Отсутствует обязательная переменная окружения: ${variableName}`, {\n code: 'CONFIG_ERROR',\n context: { variableName },\n retryable: false,\n });\n this.name = 'ConfigError';\n this.variableName = variableName;\n }\n}\n\n// ============================================================================\n// Вспомогательные функции\n// ============================================================================\n\n/**\n * Определить, можно ли повторить запрос по HTTP статусу\n *\n * Повторяемые статусы:\n * - 408: Request Timeout\n * - 429: Too Many Requests\n * - 500: Internal Server Error\n * - 502: Bad Gateway\n * - 503: Service Unavailable\n * - 504: Gateway Timeout\n */\nfunction isRetryableStatus(statusCode: number): boolean {\n return [408, 429, 500, 502, 503, 504].includes(statusCode);\n}\n\n/**\n * Проверить, является ли ошибка экземпляром AppError\n */\nexport function isAppError(error: unknown): error is AppError {\n return error instanceof AppError;\n}\n\n/**\n * Обернуть неизвестную ошибку в AppError\n */\nexport function wrapError(error: unknown, defaultMessage = 'Неизвестная ошибка'): AppError {\n if (error instanceof AppError) {\n return error;\n }\n\n if (error instanceof Error) {\n return new AppError(error.message || defaultMessage, {\n cause: error,\n context: { originalName: error.name },\n });\n }\n\n return new AppError(defaultMessage, {\n context: { originalError: error },\n });\n}\n","/**\n * Структурированное логирование\n *\n * Централизованный логгер с уровнями и форматированием.\n * В продакшене выводит JSON для парсинга CloudWatch/Datadog.\n * В dev режиме — читаемый формат с цветами.\n *\n * @module logger\n */\n\n// ============================================================================\n// Типы\n// ============================================================================\n\n/** Уровни логирования */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\n/** Метаданные для структурированного логирования */\nexport interface LogMeta {\n /** Имя модуля/компонента */\n module?: string;\n /** ID операции для трейсинга */\n operationId?: string;\n /** ID пользователя */\n userId?: string;\n /** Длительность операции в мс */\n durationMs?: number;\n /** Дополнительные поля */\n [key: string]: unknown;\n}\n\n/** Структура лог-записи */\ninterface LogEntry {\n timestamp: string;\n level: LogLevel;\n message: string;\n meta?: LogMeta;\n error?: {\n name: string;\n message: string;\n stack?: string;\n };\n}\n\n// ============================================================================\n// Конфигурация\n// ============================================================================\n\n/** Приоритет уровней (меньше = важнее) */\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n/** Цвета для консоли в dev режиме */\nconst COLORS: Record<LogLevel, string> = {\n debug: '\\x1b[36m', // Cyan\n info: '\\x1b[32m', // Green\n warn: '\\x1b[33m', // Yellow\n error: '\\x1b[31m', // Red\n};\nconst RESET = '\\x1b[0m';\n\n/** Текущий уровень логирования */\nfunction getCurrentLogLevel(): LogLevel {\n const envLevel = process.env.LOG_LEVEL?.toLowerCase();\n if (envLevel && envLevel in LOG_LEVEL_PRIORITY) {\n return envLevel as LogLevel;\n }\n return process.env.NODE_ENV === 'production' ? 'info' : 'debug';\n}\n\n/** Проверка, включён ли dev режим */\nfunction isDev(): boolean {\n return process.env.NODE_ENV !== 'production';\n}\n\n// ============================================================================\n// Форматирование\n// ============================================================================\n\n/**\n * Форматировать лог-запись для консоли\n */\nfunction formatLogEntry(entry: LogEntry): string {\n if (isDev()) {\n // Dev режим: читаемый формат с цветами\n const color = COLORS[entry.level];\n const levelStr = entry.level.toUpperCase().padEnd(5);\n const time = new Date(entry.timestamp).toLocaleTimeString();\n\n let output = `${color}[${levelStr}]${RESET} ${time} ${entry.message}`;\n\n if (entry.meta && Object.keys(entry.meta).length > 0) {\n output += ` ${JSON.stringify(entry.meta)}`;\n }\n\n if (entry.error) {\n output += `\\n Error: ${entry.error.name}: ${entry.error.message}`;\n if (entry.error.stack) {\n output += `\\n ${entry.error.stack.split('\\n').slice(1).join('\\n ')}`;\n }\n }\n\n return output;\n }\n\n // Production: JSON для парсинга\n return JSON.stringify(entry);\n}\n\n/**\n * Сериализовать ошибку для логирования\n */\nfunction serializeError(error: Error): LogEntry['error'] {\n return {\n name: error.name,\n message: error.message,\n stack: error.stack,\n };\n}\n\n// ============================================================================\n// Основной класс логгера\n// ============================================================================\n\n/**\n * Класс логгера\n *\n * Создаёт экземпляр с привязкой к модулю.\n *\n * @example\n * const log = new Logger('voyage');\n * log.info('Запрос отправлен', { tokens: 1500 });\n * log.error('Ошибка API', new Error('timeout'));\n */\nexport class Logger {\n private readonly module: string;\n private readonly minLevel: LogLevel;\n\n constructor(module: string) {\n this.module = module;\n this.minLevel = getCurrentLogLevel();\n }\n\n /**\n * Проверить, включён ли данный уровень\n */\n private isEnabled(level: LogLevel): boolean {\n return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[this.minLevel];\n }\n\n /**\n * Записать лог\n */\n private log(level: LogLevel, message: string, meta?: LogMeta, error?: Error): void {\n if (!this.isEnabled(level)) return;\n\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n level,\n message,\n meta: { module: this.module, ...meta },\n };\n\n if (error) {\n entry.error = serializeError(error);\n }\n\n const formatted = formatLogEntry(entry);\n\n switch (level) {\n case 'error':\n console.error(formatted);\n break;\n case 'warn':\n console.warn(formatted);\n break;\n default:\n console.log(formatted);\n }\n }\n\n /**\n * Debug уровень — детальная информация для отладки\n */\n debug(message: string, meta?: LogMeta): void {\n this.log('debug', message, meta);\n }\n\n /**\n * Info уровень — информационные сообщения\n */\n info(message: string, meta?: LogMeta): void {\n this.log('info', message, meta);\n }\n\n /**\n * Warn уровень — предупреждения\n */\n warn(message: string, meta?: LogMeta): void {\n this.log('warn', message, meta);\n }\n\n /**\n * Error уровень — ошибки\n */\n error(message: string, error?: Error | unknown, meta?: LogMeta): void {\n const err = error instanceof Error ? error : undefined;\n this.log('error', message, meta, err);\n }\n\n /**\n * Создать child logger с дополнительным контекстом\n */\n child(context: LogMeta): ChildLogger {\n return new ChildLogger(this, context);\n }\n}\n\n/**\n * Child logger с привязанным контекстом\n */\nclass ChildLogger {\n constructor(\n private readonly parent: Logger,\n private readonly context: LogMeta\n ) {}\n\n debug(message: string, meta?: LogMeta): void {\n this.parent.debug(message, { ...this.context, ...meta });\n }\n\n info(message: string, meta?: LogMeta): void {\n this.parent.info(message, { ...this.context, ...meta });\n }\n\n warn(message: string, meta?: LogMeta): void {\n this.parent.warn(message, { ...this.context, ...meta });\n }\n\n error(message: string, error?: Error | unknown, meta?: LogMeta): void {\n this.parent.error(message, error, { ...this.context, ...meta });\n }\n}\n\n// ============================================================================\n// Готовые экземпляры логгеров\n// ============================================================================\n\n/** Логгер для Voyage AI */\nexport const voyageLogger = new Logger('voyage');\n\n/** Логгер для Turbopuffer */\nexport const turbopufferLogger = new Logger('turbopuffer');\n\n/** Логгер для Anthropic */\nexport const anthropicLogger = new Logger('anthropic');\n\n/** Логгер для API запросов */\nexport const apiLogger = new Logger('api');\n\n/** Логгер общего назначения */\nexport const logger = new Logger('app');\n\n// ============================================================================\n// Утилиты для измерения времени\n// ============================================================================\n\n/**\n * Создать таймер для измерения длительности операции\n *\n * @example\n * const timer = createTimer();\n * await doSomething();\n * log.info('Операция завершена', { durationMs: timer() });\n */\nexport function createTimer(): () => number {\n const start = performance.now();\n return () => Math.round(performance.now() - start);\n}\n","/**\n * Retry логика с exponential backoff\n *\n * Утилиты для повторения неудачных операций с экспоненциальной\n * задержкой и джиттером для предотвращения thundering herd.\n *\n * @module retry\n */\n\nimport { Logger } from './logger';\nimport { AppError, isAppError } from './errors';\n\n// ============================================================================\n// Типы\n// ============================================================================\n\n/**\n * Опции для retry\n */\nexport interface RetryOptions {\n /** Максимальное количество попыток (включая первую) */\n maxAttempts?: number;\n /** Базовая задержка в мс (удваивается с каждой попыткой) */\n baseDelayMs?: number;\n /** Максимальная задержка в мс */\n maxDelayMs?: number;\n /** Добавлять случайный джиттер (0-1, доля от задержки) */\n jitter?: number;\n /** Функция для определения, нужно ли повторять */\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n /** Callback при каждой неудачной попытке */\n onRetry?: (error: unknown, attempt: number, delayMs: number) => void;\n /** Логгер для записи попыток */\n logger?: Logger;\n}\n\n/**\n * Результат выполнения с retry\n */\nexport interface RetryResult<T> {\n /** Результат успешного выполнения */\n data: T;\n /** Количество попыток (1 = успех с первого раза) */\n attempts: number;\n /** Общее время выполнения в мс */\n totalTimeMs: number;\n}\n\n// ============================================================================\n// Константы по умолчанию\n// ============================================================================\n\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_BASE_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 30000;\nconst DEFAULT_JITTER = 0.1;\n\n// ============================================================================\n// Вспомогательные функции\n// ============================================================================\n\n/**\n * Ожидать указанное количество миллисекунд\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Рассчитать задержку с экспоненциальным ростом и джиттером\n *\n * @param attempt - Номер попытки (начиная с 1)\n * @param baseDelayMs - Базовая задержка\n * @param maxDelayMs - Максимальная задержка\n * @param jitter - Джиттер (0-1)\n * @returns Задержка в мс\n */\nfunction calculateDelay(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n jitter: number\n): number {\n // Экспоненциальный рост: base * 2^(attempt-1)\n const exponentialDelay = baseDelayMs * Math.pow(2, attempt - 1);\n\n // Ограничиваем максимальной задержкой\n const cappedDelay = Math.min(exponentialDelay, maxDelayMs);\n\n // Добавляем джиттер\n const jitterAmount = cappedDelay * jitter * Math.random();\n\n return Math.round(cappedDelay + jitterAmount);\n}\n\n/**\n * Определить по умолчанию, нужно ли повторять\n *\n * Повторяем если:\n * - Ошибка помечена как retryable\n * - Это сетевая ошибка (fetch failed, timeout)\n */\nfunction defaultShouldRetry(error: unknown): boolean {\n // AppError с флагом retryable\n if (isAppError(error) && error.retryable) {\n return true;\n }\n\n // Стандартные сетевые ошибки\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n const networkErrors = [\n 'fetch failed',\n 'network error',\n 'timeout',\n 'econnreset',\n 'econnrefused',\n 'socket hang up',\n ];\n return networkErrors.some((e) => message.includes(e));\n }\n\n return false;\n}\n\n// ============================================================================\n// Основная функция\n// ============================================================================\n\n/**\n * Выполнить функцию с retry и exponential backoff\n *\n * @param fn - Асинхронная функция для выполнения\n * @param options - Опции retry\n * @returns Результат выполнения с метаданными\n * @throws Последняя ошибка, если все попытки исчерпаны\n *\n * @example\n * const result = await withRetry(\n * () => fetch('https://api.example.com/data'),\n * { maxAttempts: 3, baseDelayMs: 1000 }\n * );\n * console.log(`Успех за ${result.attempts} попыток`);\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<RetryResult<T>> {\n const {\n maxAttempts = DEFAULT_MAX_ATTEMPTS,\n baseDelayMs = DEFAULT_BASE_DELAY_MS,\n maxDelayMs = DEFAULT_MAX_DELAY_MS,\n jitter = DEFAULT_JITTER,\n shouldRetry = defaultShouldRetry,\n onRetry,\n logger,\n } = options;\n\n const startTime = performance.now();\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const data = await fn();\n return {\n data,\n attempts: attempt,\n totalTimeMs: Math.round(performance.now() - startTime),\n };\n } catch (error) {\n lastError = error;\n\n // Последняя попытка — бросаем ошибку\n if (attempt >= maxAttempts) {\n logger?.error(`Все ${maxAttempts} попыток исчерпаны`, error);\n break;\n }\n\n // Проверяем, нужно ли повторять\n if (!shouldRetry(error, attempt)) {\n logger?.warn(`Ошибка не подлежит повторению на попытке ${attempt}`, {\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n break;\n }\n\n // Рассчитываем задержку\n const delayMs = calculateDelay(attempt, baseDelayMs, maxDelayMs, jitter);\n\n logger?.info(`Попытка ${attempt}/${maxAttempts} не удалась, повтор через ${delayMs}мс`, {\n errorMessage: error instanceof Error ? error.message : String(error),\n delayMs,\n });\n\n // Вызываем callback\n onRetry?.(error, attempt, delayMs);\n\n // Ждём перед следующей попыткой\n await sleep(delayMs);\n }\n }\n\n // Если дошли сюда — все попытки исчерпаны\n throw lastError;\n}\n\n// ============================================================================\n// Обёртки для специфичных сценариев\n// ============================================================================\n\n/**\n * Retry для API запросов с предустановленными параметрами\n *\n * Оптимизировано для внешних API (Voyage, Anthropic, Turbopuffer).\n *\n * @example\n * const response = await retryApiCall(\n * () => fetch(VOYAGE_API_URL, { method: 'POST', body }),\n * { logger: voyageLogger }\n * );\n */\nexport async function retryApiCall<T>(\n fn: () => Promise<T>,\n options: Pick<RetryOptions, 'logger' | 'onRetry' | 'maxAttempts'> = {}\n): Promise<T> {\n const result = await withRetry(fn, {\n maxAttempts: options.maxAttempts ?? 3,\n baseDelayMs: 1000,\n maxDelayMs: 10000,\n jitter: 0.2,\n logger: options.logger,\n onRetry: options.onRetry,\n });\n\n return result.data;\n}\n\n/**\n * Retry для критичных операций с более агрессивными параметрами\n *\n * Используется для операций, которые обязательно должны выполниться.\n *\n * @example\n * await retryCritical(\n * () => saveToDatabase(data),\n * { logger }\n * );\n */\nexport async function retryCritical<T>(\n fn: () => Promise<T>,\n options: Pick<RetryOptions, 'logger' | 'onRetry'> = {}\n): Promise<T> {\n const result = await withRetry(fn, {\n maxAttempts: 5,\n baseDelayMs: 500,\n maxDelayMs: 30000,\n jitter: 0.3,\n logger: options.logger,\n onRetry: options.onRetry,\n shouldRetry: () => true, // Повторяем всегда\n });\n\n return result.data;\n}\n","/**\n * Zod схемы для валидации API ответов\n *\n * Типобезопасная валидация ответов от внешних API.\n * Гарантирует соответствие данных ожидаемой структуре.\n *\n * @module schemas\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Voyage AI Schemas\n// ============================================================================\n\n/**\n * Схема ответа Voyage Embeddings API\n *\n * @see https://docs.voyageai.com/docs/embeddings\n */\nexport const VoyageEmbeddingResponseSchema = z.object({\n /** Массив эмбеддингов */\n data: z.array(\n z.object({\n /** Вектор эмбеддинга */\n embedding: z.array(z.number()),\n /** Индекс в исходном массиве */\n index: z.number().optional(),\n })\n ),\n /** Статистика использования */\n usage: z.object({\n /** Общее количество токенов */\n total_tokens: z.number(),\n }),\n /** Модель, использованная для генерации */\n model: z.string().optional(),\n});\n\nexport type VoyageEmbeddingResponse = z.infer<typeof VoyageEmbeddingResponseSchema>;\n\n/**\n * Схема ответа Voyage Rerank API\n *\n * @see https://docs.voyageai.com/docs/reranker\n */\nexport const VoyageRerankResponseSchema = z.object({\n /** Массив результатов реранкинга */\n data: z.array(\n z.object({\n /** Индекс документа в исходном массиве */\n index: z.number(),\n /** Оценка релевантности (0-1) */\n relevance_score: z.number().min(0).max(1),\n })\n ),\n /** Статистика использования */\n usage: z.object({\n /** Общее количество токенов */\n total_tokens: z.number(),\n }),\n /** Модель, использованная для реранкинга */\n model: z.string().optional(),\n});\n\nexport type VoyageRerankResponse = z.infer<typeof VoyageRerankResponseSchema>;\n\n// ============================================================================\n// Turbopuffer Schemas\n// ============================================================================\n\n/**\n * Базовая схема атрибутов вектора\n */\nexport const VectorAttributesSchema = z.object({\n /** ID записи в Supabase */\n supabase_id: z.number(),\n /** Уникальный ID сообщения/документа */\n message_id: z.string(),\n /** Тип источника */\n source_type: z.enum(['email', 'pdf', 'website']),\n /** Тип чанка */\n chunk_type: z.string(),\n /** Email отправителя */\n sender: z.string().optional(),\n /** Email получателя */\n recipient: z.string().optional(),\n /** Дата источника */\n source_date: z.string().optional(),\n /** ID цепочки писем */\n thread_id: z.string().optional(),\n /** ID клиента */\n client_id: z.string().optional(),\n /** URL источника */\n source_url: z.string().optional(),\n /** Номер страницы */\n page_number: z.number().optional(),\n /** Заголовок секции */\n section_title: z.string().optional(),\n /** ID в content_sources */\n content_source_id: z.number().optional(),\n /** Тема письма */\n subject: z.string().optional(),\n /** Превью контента */\n content_preview: z.string().optional(),\n /** Заголовок документа */\n title: z.string().optional(),\n /** Полный контент */\n content: z.string().optional(),\n /** Категория */\n category: z.string().optional(),\n /** Тональность */\n sentiment: z.enum(['positive', 'negative', 'neutral']).optional(),\n /** Дата создания */\n created_at: z.string().optional(),\n});\n\nexport type VectorAttributes = z.infer<typeof VectorAttributesSchema>;\n\n/**\n * Схема результата поиска Turbopuffer\n */\nexport const TurbopufferSearchResultSchema = z.object({\n /** ID вектора */\n id: z.string(),\n /** Расстояние до запроса */\n dist: z.number(),\n /** Атрибуты вектора */\n attributes: VectorAttributesSchema.partial(),\n});\n\nexport type TurbopufferSearchResult = z.infer<typeof TurbopufferSearchResultSchema>;\n\n// ============================================================================\n// Anthropic Schemas\n// ============================================================================\n\n/**\n * Схема сообщения в ответе Claude\n */\nexport const ClaudeMessageSchema = z.object({\n /** ID сообщения */\n id: z.string(),\n /** Тип объекта */\n type: z.literal('message'),\n /** Роль */\n role: z.enum(['assistant', 'user']),\n /** Контент */\n content: z.array(\n z.object({\n type: z.enum(['text', 'tool_use']),\n text: z.string().optional(),\n })\n ),\n /** Модель */\n model: z.string(),\n /** Причина остановки */\n stop_reason: z.enum(['end_turn', 'max_tokens', 'stop_sequence', 'tool_use']).nullable(),\n /** Использование токенов */\n usage: z.object({\n input_tokens: z.number(),\n output_tokens: z.number(),\n }),\n});\n\nexport type ClaudeMessage = z.infer<typeof ClaudeMessageSchema>;\n\n// ============================================================================\n// Chat API Schemas\n// ============================================================================\n\n/**\n * Схема входящего запроса к Chat API\n */\nexport const ChatRequestSchema = z.object({\n /** Сообщение пользователя */\n message: z.string().min(1).max(10000),\n /** История сообщений */\n history: z\n .array(\n z.object({\n role: z.enum(['user', 'assistant']),\n content: z.string(),\n })\n )\n .optional()\n .default([]),\n /** ID сессии */\n sessionId: z.string().optional(),\n /** Режим (customer/internal) */\n mode: z.enum(['customer', 'internal']).optional().default('customer'),\n});\n\nexport type ChatRequest = z.infer<typeof ChatRequestSchema>;\n\n/**\n * Схема источника в ответе\n */\nexport const SourceSchema = z.object({\n /** Тип источника */\n type: z.enum(['email', 'pdf', 'website']),\n /** Заголовок */\n title: z.string(),\n /** URL или идентификатор */\n url: z.string().optional(),\n /** Превью контента */\n preview: z.string().optional(),\n /** Оценка релевантности */\n relevance: z.number().optional(),\n});\n\nexport type Source = z.infer<typeof SourceSchema>;\n\n// ============================================================================\n// Утилиты для валидации\n// ============================================================================\n\n/**\n * Безопасно распарсить данные по схеме\n *\n * @param schema - Zod схема\n * @param data - Данные для валидации\n * @returns Результат парсинга или null при ошибке\n *\n * @example\n * const response = await fetch(url);\n * const data = await response.json();\n * const parsed = safeParse(VoyageEmbeddingResponseSchema, data);\n * if (!parsed) throw new ValidationError('Invalid API response');\n */\nexport function safeParse<T>(\n schema: z.ZodType<T>,\n data: unknown\n): T | null {\n const result = schema.safeParse(data);\n return result.success ? result.data : null;\n}\n\n/**\n * Распарсить данные по схеме с выбросом ошибки\n *\n * @param schema - Zod схема\n * @param data - Данные для валидации\n * @param errorMessage - Сообщение об ошибке\n * @returns Валидные данные\n * @throws Error при невалидных данных\n */\nexport function parseOrThrow<T>(\n schema: z.ZodType<T>,\n data: unknown,\n errorMessage = 'Validation failed'\n): T {\n const result = schema.safeParse(data);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ');\n throw new Error(`${errorMessage}: ${issues}`);\n }\n return result.data;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/logger.ts","../src/retry.ts","../src/schemas.ts"],"names":["logger","z"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Кастомные классы ошибок\n *\n * Иерархия ошибок для структурированной обработки исключений.\n * Каждый класс содержит дополнительный контекст для отладки.\n *\n * @module errors\n */\n\n// ============================================================================\n// Базовый класс\n// ============================================================================\n\n/**\n * Базовый класс для всех ошибок приложения\n *\n * Расширяет стандартный Error с дополнительными полями:\n * - code: машиночитаемый код ошибки\n * - context: дополнительные данные для отладки\n * - retryable: можно ли повторить операцию\n */\nexport class AppError extends Error {\n /** Машиночитаемый код ошибки */\n readonly code: string;\n /** Дополнительный контекст для отладки */\n readonly context?: Record<string, unknown>;\n /** Можно ли повторить операцию */\n readonly retryable: boolean;\n /** Временная метка создания ошибки */\n readonly timestamp: Date;\n\n constructor(\n message: string,\n options: {\n code?: string;\n context?: Record<string, unknown>;\n retryable?: boolean;\n cause?: Error;\n } = {}\n ) {\n super(message, { cause: options.cause });\n this.name = 'AppError';\n this.code = options.code || 'APP_ERROR';\n this.context = options.context;\n this.retryable = options.retryable ?? false;\n this.timestamp = new Date();\n }\n\n /**\n * Преобразовать в JSON для логирования\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n context: this.context,\n retryable: this.retryable,\n timestamp: this.timestamp.toISOString(),\n stack: this.stack,\n };\n }\n}\n\n// ============================================================================\n// Ошибки API\n// ============================================================================\n\n/**\n * Ошибка при вызове внешнего API\n *\n * Используется для Voyage AI, Anthropic, Turbopuffer.\n */\nexport class ApiError extends AppError {\n /** HTTP статус код */\n readonly statusCode: number;\n /** Имя сервиса */\n readonly service: string;\n\n constructor(\n message: string,\n options: {\n statusCode: number;\n service: string;\n context?: Record<string, unknown>;\n retryable?: boolean;\n cause?: Error;\n }\n ) {\n super(message, {\n code: `${options.service.toUpperCase()}_API_ERROR`,\n context: { ...options.context, statusCode: options.statusCode },\n retryable: options.retryable ?? isRetryableStatus(options.statusCode),\n cause: options.cause,\n });\n this.name = 'ApiError';\n this.statusCode = options.statusCode;\n this.service = options.service;\n }\n}\n\n/**\n * Ошибка Voyage AI API\n */\nexport class VoyageApiError extends ApiError {\n constructor(\n message: string,\n statusCode: number,\n context?: Record<string, unknown>\n ) {\n super(message, {\n statusCode,\n service: 'voyage',\n context,\n });\n this.name = 'VoyageApiError';\n }\n}\n\n/**\n * Ошибка Anthropic API\n */\nexport class AnthropicApiError extends ApiError {\n constructor(\n message: string,\n statusCode: number,\n context?: Record<string, unknown>\n ) {\n super(message, {\n statusCode,\n service: 'anthropic',\n context,\n });\n this.name = 'AnthropicApiError';\n }\n}\n\n/**\n * Ошибка Turbopuffer API\n */\nexport class TurbopufferApiError extends ApiError {\n constructor(\n message: string,\n statusCode: number,\n context?: Record<string, unknown>\n ) {\n super(message, {\n statusCode,\n service: 'turbopuffer',\n context,\n });\n this.name = 'TurbopufferApiError';\n }\n}\n\n// ============================================================================\n// Ошибки валидации\n// ============================================================================\n\n/**\n * Ошибка валидации данных\n *\n * Используется при невалидных входных данных или ответах API.\n */\nexport class ValidationError extends AppError {\n /** Поле, в котором обнаружена ошибка */\n readonly field?: string;\n /** Ожидаемое значение или тип */\n readonly expected?: string;\n /** Полученное значение */\n readonly received?: unknown;\n\n constructor(\n message: string,\n options: {\n field?: string;\n expected?: string;\n received?: unknown;\n context?: Record<string, unknown>;\n } = {}\n ) {\n super(message, {\n code: 'VALIDATION_ERROR',\n context: {\n ...options.context,\n field: options.field,\n expected: options.expected,\n received: options.received,\n },\n retryable: false,\n });\n this.name = 'ValidationError';\n this.field = options.field;\n this.expected = options.expected;\n this.received = options.received;\n }\n}\n\n// ============================================================================\n// Ошибки конфигурации\n// ============================================================================\n\n/**\n * Ошибка отсутствующей конфигурации\n *\n * Используется при отсутствии обязательных переменных окружения.\n */\nexport class ConfigError extends AppError {\n /** Имя отсутствующей переменной */\n readonly variableName: string;\n\n constructor(variableName: string) {\n super(`Отсутствует обязательная переменная окружения: ${variableName}`, {\n code: 'CONFIG_ERROR',\n context: { variableName },\n retryable: false,\n });\n this.name = 'ConfigError';\n this.variableName = variableName;\n }\n}\n\n// ============================================================================\n// Вспомогательные функции\n// ============================================================================\n\n/**\n * Определить, можно ли повторить запрос по HTTP статусу\n *\n * Повторяемые статусы:\n * - 408: Request Timeout\n * - 429: Too Many Requests\n * - 500: Internal Server Error\n * - 502: Bad Gateway\n * - 503: Service Unavailable\n * - 504: Gateway Timeout\n */\nfunction isRetryableStatus(statusCode: number): boolean {\n return [408, 429, 500, 502, 503, 504].includes(statusCode);\n}\n\n/**\n * Проверить, является ли ошибка экземпляром AppError\n */\nexport function isAppError(error: unknown): error is AppError {\n return error instanceof AppError;\n}\n\n/**\n * Обернуть неизвестную ошибку в AppError\n */\nexport function wrapError(error: unknown, defaultMessage = 'Неизвестная ошибка'): AppError {\n if (error instanceof AppError) {\n return error;\n }\n\n if (error instanceof Error) {\n return new AppError(error.message || defaultMessage, {\n cause: error,\n context: { originalName: error.name },\n });\n }\n\n return new AppError(defaultMessage, {\n context: { originalError: error },\n });\n}\n","/**\n * Структурированное логирование\n *\n * Централизованный логгер с уровнями и форматированием.\n * В продакшене выводит JSON для парсинга CloudWatch/Datadog.\n * В dev режиме — читаемый формат с цветами.\n *\n * @module logger\n */\n\n// ============================================================================\n// Типы\n// ============================================================================\n\n/** Уровни логирования */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\n/** Метаданные для структурированного логирования */\nexport interface LogMeta {\n /** Имя модуля/компонента */\n module?: string;\n /** ID операции для трейсинга */\n operationId?: string;\n /** ID пользователя */\n userId?: string;\n /** Длительность операции в мс */\n durationMs?: number;\n /** Дополнительные поля */\n [key: string]: unknown;\n}\n\n/** Структура лог-записи */\ninterface LogEntry {\n timestamp: string;\n level: LogLevel;\n message: string;\n meta?: LogMeta;\n error?: {\n name: string;\n message: string;\n stack?: string;\n };\n}\n\n// ============================================================================\n// Конфигурация\n// ============================================================================\n\n/** Приоритет уровней (меньше = важнее) */\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n/** Цвета для консоли в dev режиме */\nconst COLORS: Record<LogLevel, string> = {\n debug: '\\x1b[36m', // Cyan\n info: '\\x1b[32m', // Green\n warn: '\\x1b[33m', // Yellow\n error: '\\x1b[31m', // Red\n};\nconst RESET = '\\x1b[0m';\n\n/** Текущий уровень логирования */\nfunction getCurrentLogLevel(): LogLevel {\n const envLevel = process.env.LOG_LEVEL?.toLowerCase();\n if (envLevel && envLevel in LOG_LEVEL_PRIORITY) {\n return envLevel as LogLevel;\n }\n return process.env.NODE_ENV === 'production' ? 'info' : 'debug';\n}\n\n/** Проверка, включён ли dev режим */\nfunction isDev(): boolean {\n return process.env.NODE_ENV !== 'production';\n}\n\n// ============================================================================\n// Форматирование\n// ============================================================================\n\n/**\n * Форматировать лог-запись для консоли\n */\nfunction formatLogEntry(entry: LogEntry): string {\n if (isDev()) {\n // Dev режим: читаемый формат с цветами\n const color = COLORS[entry.level];\n const levelStr = entry.level.toUpperCase().padEnd(5);\n const time = new Date(entry.timestamp).toLocaleTimeString();\n\n let output = `${color}[${levelStr}]${RESET} ${time} ${entry.message}`;\n\n if (entry.meta && Object.keys(entry.meta).length > 0) {\n output += ` ${JSON.stringify(entry.meta)}`;\n }\n\n if (entry.error) {\n output += `\\n Error: ${entry.error.name}: ${entry.error.message}`;\n if (entry.error.stack) {\n output += `\\n ${entry.error.stack.split('\\n').slice(1).join('\\n ')}`;\n }\n }\n\n return output;\n }\n\n // Production: JSON для парсинга\n return JSON.stringify(entry);\n}\n\n/**\n * Сериализовать ошибку для логирования\n */\nfunction serializeError(error: Error): LogEntry['error'] {\n return {\n name: error.name,\n message: error.message,\n stack: error.stack,\n };\n}\n\n// ============================================================================\n// Основной класс логгера\n// ============================================================================\n\n/**\n * Класс логгера\n *\n * Создаёт экземпляр с привязкой к модулю.\n *\n * @example\n * const log = new Logger('voyage');\n * log.info('Запрос отправлен', { tokens: 1500 });\n * log.error('Ошибка API', new Error('timeout'));\n */\nexport class Logger {\n private readonly module: string;\n private readonly minLevel: LogLevel;\n\n constructor(module: string) {\n this.module = module;\n this.minLevel = getCurrentLogLevel();\n }\n\n /**\n * Проверить, включён ли данный уровень\n */\n private isEnabled(level: LogLevel): boolean {\n return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[this.minLevel];\n }\n\n /**\n * Записать лог\n */\n private log(level: LogLevel, message: string, meta?: LogMeta, error?: Error): void {\n if (!this.isEnabled(level)) return;\n\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n level,\n message,\n meta: { module: this.module, ...meta },\n };\n\n if (error) {\n entry.error = serializeError(error);\n }\n\n const formatted = formatLogEntry(entry);\n\n switch (level) {\n case 'error':\n console.error(formatted);\n break;\n case 'warn':\n console.warn(formatted);\n break;\n default:\n console.log(formatted);\n }\n }\n\n /**\n * Debug уровень — детальная информация для отладки\n */\n debug(message: string, meta?: LogMeta): void {\n this.log('debug', message, meta);\n }\n\n /**\n * Info уровень — информационные сообщения\n */\n info(message: string, meta?: LogMeta): void {\n this.log('info', message, meta);\n }\n\n /**\n * Warn уровень — предупреждения\n */\n warn(message: string, meta?: LogMeta): void {\n this.log('warn', message, meta);\n }\n\n /**\n * Error уровень — ошибки\n */\n error(message: string, error?: Error | unknown, meta?: LogMeta): void {\n const err = error instanceof Error ? error : undefined;\n this.log('error', message, meta, err);\n }\n\n /**\n * Создать child logger с дополнительным контекстом\n */\n child(context: LogMeta): ChildLogger {\n return new ChildLogger(this, context);\n }\n}\n\n/**\n * Child logger с привязанным контекстом\n */\nclass ChildLogger {\n constructor(\n private readonly parent: Logger,\n private readonly context: LogMeta\n ) {}\n\n debug(message: string, meta?: LogMeta): void {\n this.parent.debug(message, { ...this.context, ...meta });\n }\n\n info(message: string, meta?: LogMeta): void {\n this.parent.info(message, { ...this.context, ...meta });\n }\n\n warn(message: string, meta?: LogMeta): void {\n this.parent.warn(message, { ...this.context, ...meta });\n }\n\n error(message: string, error?: Error | unknown, meta?: LogMeta): void {\n this.parent.error(message, error, { ...this.context, ...meta });\n }\n}\n\n// ============================================================================\n// Готовые экземпляры логгеров\n// ============================================================================\n\n/** Логгер для Voyage AI */\nexport const voyageLogger = new Logger('voyage');\n\n/** Логгер для Turbopuffer */\nexport const turbopufferLogger = new Logger('turbopuffer');\n\n/** Логгер для Anthropic */\nexport const anthropicLogger = new Logger('anthropic');\n\n/** Логгер для API запросов */\nexport const apiLogger = new Logger('api');\n\n/** Логгер общего назначения */\nexport const logger = new Logger('app');\n\n// ============================================================================\n// Утилиты для измерения времени\n// ============================================================================\n\n/**\n * Создать таймер для измерения длительности операции\n *\n * @example\n * const timer = createTimer();\n * await doSomething();\n * log.info('Операция завершена', { durationMs: timer() });\n */\nexport function createTimer(): () => number {\n const start = performance.now();\n return () => Math.round(performance.now() - start);\n}\n","/**\n * Retry логика с exponential backoff\n *\n * Утилиты для повторения неудачных операций с экспоненциальной\n * задержкой и джиттером для предотвращения thundering herd.\n *\n * @module retry\n */\n\nimport { Logger } from './logger';\nimport { AppError, isAppError } from './errors';\n\n// ============================================================================\n// Типы\n// ============================================================================\n\n/**\n * Опции для retry\n */\nexport interface RetryOptions {\n /** Максимальное количество попыток (включая первую) */\n maxAttempts?: number;\n /** Базовая задержка в мс (удваивается с каждой попыткой) */\n baseDelayMs?: number;\n /** Максимальная задержка в мс */\n maxDelayMs?: number;\n /** Добавлять случайный джиттер (0-1, доля от задержки) */\n jitter?: number;\n /** Функция для определения, нужно ли повторять */\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n /** Callback при каждой неудачной попытке */\n onRetry?: (error: unknown, attempt: number, delayMs: number) => void;\n /** Логгер для записи попыток */\n logger?: Logger;\n}\n\n/**\n * Результат выполнения с retry\n */\nexport interface RetryResult<T> {\n /** Результат успешного выполнения */\n data: T;\n /** Количество попыток (1 = успех с первого раза) */\n attempts: number;\n /** Общее время выполнения в мс */\n totalTimeMs: number;\n}\n\n// ============================================================================\n// Константы по умолчанию\n// ============================================================================\n\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_BASE_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 30000;\nconst DEFAULT_JITTER = 0.1;\n\n// ============================================================================\n// Вспомогательные функции\n// ============================================================================\n\n/**\n * Ожидать указанное количество миллисекунд\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Рассчитать задержку с экспоненциальным ростом и джиттером\n *\n * @param attempt - Номер попытки (начиная с 1)\n * @param baseDelayMs - Базовая задержка\n * @param maxDelayMs - Максимальная задержка\n * @param jitter - Джиттер (0-1)\n * @returns Задержка в мс\n */\nfunction calculateDelay(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n jitter: number\n): number {\n // Экспоненциальный рост: base * 2^(attempt-1)\n const exponentialDelay = baseDelayMs * Math.pow(2, attempt - 1);\n\n // Ограничиваем максимальной задержкой\n const cappedDelay = Math.min(exponentialDelay, maxDelayMs);\n\n // Добавляем джиттер\n const jitterAmount = cappedDelay * jitter * Math.random();\n\n return Math.round(cappedDelay + jitterAmount);\n}\n\n/**\n * Определить по умолчанию, нужно ли повторять\n *\n * Повторяем если:\n * - Ошибка помечена как retryable\n * - Это сетевая ошибка (fetch failed, timeout)\n */\nfunction defaultShouldRetry(error: unknown): boolean {\n // AppError с флагом retryable\n if (isAppError(error) && error.retryable) {\n return true;\n }\n\n // Стандартные сетевые ошибки\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n const networkErrors = [\n 'fetch failed',\n 'network error',\n 'timeout',\n 'econnreset',\n 'econnrefused',\n 'socket hang up',\n ];\n return networkErrors.some((e) => message.includes(e));\n }\n\n return false;\n}\n\n// ============================================================================\n// Основная функция\n// ============================================================================\n\n/**\n * Выполнить функцию с retry и exponential backoff\n *\n * @param fn - Асинхронная функция для выполнения\n * @param options - Опции retry\n * @returns Результат выполнения с метаданными\n * @throws Последняя ошибка, если все попытки исчерпаны\n *\n * @example\n * const result = await withRetry(\n * () => fetch('https://api.example.com/data'),\n * { maxAttempts: 3, baseDelayMs: 1000 }\n * );\n * console.log(`Успех за ${result.attempts} попыток`);\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<RetryResult<T>> {\n const {\n maxAttempts = DEFAULT_MAX_ATTEMPTS,\n baseDelayMs = DEFAULT_BASE_DELAY_MS,\n maxDelayMs = DEFAULT_MAX_DELAY_MS,\n jitter = DEFAULT_JITTER,\n shouldRetry = defaultShouldRetry,\n onRetry,\n logger,\n } = options;\n\n const startTime = performance.now();\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const data = await fn();\n return {\n data,\n attempts: attempt,\n totalTimeMs: Math.round(performance.now() - startTime),\n };\n } catch (error) {\n lastError = error;\n\n // Последняя попытка — бросаем ошибку\n if (attempt >= maxAttempts) {\n logger?.error(`Все ${maxAttempts} попыток исчерпаны`, error);\n break;\n }\n\n // Проверяем, нужно ли повторять\n if (!shouldRetry(error, attempt)) {\n logger?.warn(`Ошибка не подлежит повторению на попытке ${attempt}`, {\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n break;\n }\n\n // Рассчитываем задержку\n const delayMs = calculateDelay(attempt, baseDelayMs, maxDelayMs, jitter);\n\n logger?.info(`Попытка ${attempt}/${maxAttempts} не удалась, повтор через ${delayMs}мс`, {\n errorMessage: error instanceof Error ? error.message : String(error),\n delayMs,\n });\n\n // Вызываем callback\n onRetry?.(error, attempt, delayMs);\n\n // Ждём перед следующей попыткой\n await sleep(delayMs);\n }\n }\n\n // Если дошли сюда — все попытки исчерпаны\n throw lastError;\n}\n\n// ============================================================================\n// Обёртки для специфичных сценариев\n// ============================================================================\n\n/**\n * Retry для API запросов с предустановленными параметрами\n *\n * Оптимизировано для внешних API (Voyage, Anthropic, Turbopuffer).\n *\n * @example\n * const response = await retryApiCall(\n * () => fetch(VOYAGE_API_URL, { method: 'POST', body }),\n * { logger: voyageLogger }\n * );\n */\nexport async function retryApiCall<T>(\n fn: () => Promise<T>,\n options: Pick<RetryOptions, 'logger' | 'onRetry' | 'maxAttempts'> = {}\n): Promise<T> {\n const result = await withRetry(fn, {\n maxAttempts: options.maxAttempts ?? 3,\n baseDelayMs: 1000,\n maxDelayMs: 10000,\n jitter: 0.2,\n logger: options.logger,\n onRetry: options.onRetry,\n });\n\n return result.data;\n}\n\n/**\n * Retry для критичных операций с более агрессивными параметрами\n *\n * Используется для операций, которые обязательно должны выполниться.\n *\n * @example\n * await retryCritical(\n * () => saveToDatabase(data),\n * { logger }\n * );\n */\nexport async function retryCritical<T>(\n fn: () => Promise<T>,\n options: Pick<RetryOptions, 'logger' | 'onRetry'> = {}\n): Promise<T> {\n const result = await withRetry(fn, {\n maxAttempts: 5,\n baseDelayMs: 500,\n maxDelayMs: 30000,\n jitter: 0.3,\n logger: options.logger,\n onRetry: options.onRetry,\n shouldRetry: () => true, // Повторяем всегда\n });\n\n return result.data;\n}\n\n// ============================================================================\n// Fallback Helpers\n// ============================================================================\n\n/**\n * Опции для withFallback\n */\nexport interface FallbackOptions<T> extends RetryOptions {\n /** Значение по умолчанию при неудаче */\n fallback: T | (() => T);\n /** Не логировать ошибку (используется когда fallback ожидаем) */\n silent?: boolean;\n}\n\n/**\n * Выполнить функцию с retry и fallback значением при неудаче\n *\n * Используется для graceful degradation — когда операция может упасть,\n * но мы хотим продолжить работу с дефолтным значением.\n *\n * @param fn - Асинхронная функция для выполнения\n * @param options - Опции с обязательным fallback\n * @returns Результат выполнения или fallback значение\n *\n * @example\n * // Rerank с fallback на исходные результаты\n * const reranked = await withFallback(\n * () => rerankResults(query, results),\n * {\n * fallback: results,\n * maxAttempts: 2,\n * logger: voyageLogger,\n * }\n * );\n *\n * @example\n * // Получить настройки с fallback на defaults\n * const settings = await withFallback(\n * () => fetchUserSettings(userId),\n * {\n * fallback: () => DEFAULT_SETTINGS,\n * silent: true, // Не логировать, если настройки не найдены\n * }\n * );\n */\nexport async function withFallback<T>(\n fn: () => Promise<T>,\n options: FallbackOptions<T>\n): Promise<T> {\n const { fallback, silent = false, logger, ...retryOptions } = options;\n\n try {\n const result = await withRetry(fn, { ...retryOptions, logger });\n return result.data;\n } catch (error) {\n if (!silent && logger) {\n logger.warn('Операция не удалась, используем fallback', {\n errorMessage: error instanceof Error ? error.message : String(error),\n errorType: error instanceof Error ? error.constructor.name : typeof error,\n });\n }\n\n // Вычисляем fallback значение\n return typeof fallback === 'function' ? (fallback as () => T)() : fallback;\n }\n}\n\n/**\n * Результат операции с информацией об использовании fallback\n */\nexport interface FallbackResult<T> {\n /** Результат (данные или fallback) */\n data: T;\n /** true если использован fallback */\n usedFallback: boolean;\n /** Ошибка, если была */\n error?: Error;\n}\n\n/**\n * Версия withFallback, которая возвращает информацию об использовании fallback\n *\n * Полезно когда нужно знать, пришли ли данные из источника или из fallback.\n *\n * @example\n * const { data, usedFallback } = await withFallbackInfo(\n * () => fetchLiveData(),\n * { fallback: cachedData }\n * );\n *\n * if (usedFallback) {\n * console.log('Показываем кэшированные данные');\n * }\n */\nexport async function withFallbackInfo<T>(\n fn: () => Promise<T>,\n options: FallbackOptions<T>\n): Promise<FallbackResult<T>> {\n const { fallback, silent = false, logger, ...retryOptions } = options;\n\n try {\n const result = await withRetry(fn, { ...retryOptions, logger });\n return {\n data: result.data,\n usedFallback: false,\n };\n } catch (error) {\n if (!silent && logger) {\n logger.warn('Операция не удалась, используем fallback', {\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n }\n\n const fallbackValue = typeof fallback === 'function'\n ? (fallback as () => T)()\n : fallback;\n\n return {\n data: fallbackValue,\n usedFallback: true,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n}\n","/**\n * Zod схемы для валидации API ответов\n *\n * Типобезопасная валидация ответов от внешних API.\n * Гарантирует соответствие данных ожидаемой структуре.\n *\n * @module schemas\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Voyage AI Schemas\n// ============================================================================\n\n/**\n * Схема ответа Voyage Embeddings API\n *\n * @see https://docs.voyageai.com/docs/embeddings\n */\nexport const VoyageEmbeddingResponseSchema = z.object({\n /** Массив эмбеддингов */\n data: z.array(\n z.object({\n /** Вектор эмбеддинга */\n embedding: z.array(z.number()),\n /** Индекс в исходном массиве */\n index: z.number().optional(),\n })\n ),\n /** Статистика использования */\n usage: z.object({\n /** Общее количество токенов */\n total_tokens: z.number(),\n }),\n /** Модель, использованная для генерации */\n model: z.string().optional(),\n});\n\nexport type VoyageEmbeddingResponse = z.infer<typeof VoyageEmbeddingResponseSchema>;\n\n/**\n * Схема ответа Voyage Rerank API\n *\n * @see https://docs.voyageai.com/docs/reranker\n */\nexport const VoyageRerankResponseSchema = z.object({\n /** Массив результатов реранкинга */\n data: z.array(\n z.object({\n /** Индекс документа в исходном массиве */\n index: z.number(),\n /** Оценка релевантности (0-1) */\n relevance_score: z.number().min(0).max(1),\n })\n ),\n /** Статистика использования */\n usage: z.object({\n /** Общее количество токенов */\n total_tokens: z.number(),\n }),\n /** Модель, использованная для реранкинга */\n model: z.string().optional(),\n});\n\nexport type VoyageRerankResponse = z.infer<typeof VoyageRerankResponseSchema>;\n\n// ============================================================================\n// Turbopuffer Schemas\n// ============================================================================\n\n/**\n * Базовая схема атрибутов вектора\n */\nexport const VectorAttributesSchema = z.object({\n /** ID записи в Supabase */\n supabase_id: z.number(),\n /** Уникальный ID сообщения/документа */\n message_id: z.string(),\n /** Тип источника */\n source_type: z.enum(['email', 'pdf', 'website']),\n /** Тип чанка */\n chunk_type: z.string(),\n /** Email отправителя */\n sender: z.string().optional(),\n /** Email получателя */\n recipient: z.string().optional(),\n /** Дата источника */\n source_date: z.string().optional(),\n /** ID цепочки писем */\n thread_id: z.string().optional(),\n /** ID клиента */\n client_id: z.string().optional(),\n /** URL источника */\n source_url: z.string().optional(),\n /** Номер страницы */\n page_number: z.number().optional(),\n /** Заголовок секции */\n section_title: z.string().optional(),\n /** ID в content_sources */\n content_source_id: z.number().optional(),\n /** Тема письма */\n subject: z.string().optional(),\n /** Превью контента */\n content_preview: z.string().optional(),\n /** Заголовок документа */\n title: z.string().optional(),\n /** Полный контент */\n content: z.string().optional(),\n /** Категория */\n category: z.string().optional(),\n /** Тональность */\n sentiment: z.enum(['positive', 'negative', 'neutral']).optional(),\n /** Дата создания */\n created_at: z.string().optional(),\n});\n\nexport type VectorAttributes = z.infer<typeof VectorAttributesSchema>;\n\n/**\n * Схема результата поиска Turbopuffer\n */\nexport const TurbopufferSearchResultSchema = z.object({\n /** ID вектора */\n id: z.string(),\n /** Расстояние до запроса */\n dist: z.number(),\n /** Атрибуты вектора */\n attributes: VectorAttributesSchema.partial(),\n});\n\nexport type TurbopufferSearchResult = z.infer<typeof TurbopufferSearchResultSchema>;\n\n// ============================================================================\n// Anthropic Schemas\n// ============================================================================\n\n/**\n * Схема сообщения в ответе Claude\n */\nexport const ClaudeMessageSchema = z.object({\n /** ID сообщения */\n id: z.string(),\n /** Тип объекта */\n type: z.literal('message'),\n /** Роль */\n role: z.enum(['assistant', 'user']),\n /** Контент */\n content: z.array(\n z.object({\n type: z.enum(['text', 'tool_use']),\n text: z.string().optional(),\n })\n ),\n /** Модель */\n model: z.string(),\n /** Причина остановки */\n stop_reason: z.enum(['end_turn', 'max_tokens', 'stop_sequence', 'tool_use']).nullable(),\n /** Использование токенов */\n usage: z.object({\n input_tokens: z.number(),\n output_tokens: z.number(),\n }),\n});\n\nexport type ClaudeMessage = z.infer<typeof ClaudeMessageSchema>;\n\n// ============================================================================\n// Chat API Schemas\n// ============================================================================\n\n/**\n * Схема входящего запроса к Chat API\n */\nexport const ChatRequestSchema = z.object({\n /** Сообщение пользователя */\n message: z.string().min(1).max(10000),\n /** История сообщений */\n history: z\n .array(\n z.object({\n role: z.enum(['user', 'assistant']),\n content: z.string(),\n })\n )\n .optional()\n .default([]),\n /** ID сессии */\n sessionId: z.string().optional(),\n /** Режим (customer/internal) */\n mode: z.enum(['customer', 'internal']).optional().default('customer'),\n});\n\nexport type ChatRequest = z.infer<typeof ChatRequestSchema>;\n\n/**\n * Схема источника в ответе\n */\nexport const SourceSchema = z.object({\n /** Тип источника */\n type: z.enum(['email', 'pdf', 'website']),\n /** Заголовок */\n title: z.string(),\n /** URL или идентификатор */\n url: z.string().optional(),\n /** Превью контента */\n preview: z.string().optional(),\n /** Оценка релевантности */\n relevance: z.number().optional(),\n});\n\nexport type Source = z.infer<typeof SourceSchema>;\n\n// ============================================================================\n// Утилиты для валидации\n// ============================================================================\n\n/**\n * Безопасно распарсить данные по схеме\n *\n * @param schema - Zod схема\n * @param data - Данные для валидации\n * @returns Результат парсинга или null при ошибке\n *\n * @example\n * const response = await fetch(url);\n * const data = await response.json();\n * const parsed = safeParse(VoyageEmbeddingResponseSchema, data);\n * if (!parsed) throw new ValidationError('Invalid API response');\n */\nexport function safeParse<T>(\n schema: z.ZodType<T>,\n data: unknown\n): T | null {\n const result = schema.safeParse(data);\n return result.success ? result.data : null;\n}\n\n/**\n * Распарсить данные по схеме с выбросом ошибки\n *\n * @param schema - Zod схема\n * @param data - Данные для валидации\n * @param errorMessage - Сообщение об ошибке\n * @returns Валидные данные\n * @throws Error при невалидных данных\n */\nexport function parseOrThrow<T>(\n schema: z.ZodType<T>,\n data: unknown,\n errorMessage = 'Validation failed'\n): T {\n const result = schema.safeParse(data);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ');\n throw new Error(`${errorMessage}: ${issues}`);\n }\n return result.data;\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -392,6 +392,43 @@ async function retryCritical(fn, options = {}) {
|
|
|
392
392
|
});
|
|
393
393
|
return result.data;
|
|
394
394
|
}
|
|
395
|
+
async function withFallback(fn, options) {
|
|
396
|
+
const { fallback, silent = false, logger: logger2, ...retryOptions } = options;
|
|
397
|
+
try {
|
|
398
|
+
const result = await withRetry(fn, { ...retryOptions, logger: logger2 });
|
|
399
|
+
return result.data;
|
|
400
|
+
} catch (error) {
|
|
401
|
+
if (!silent && logger2) {
|
|
402
|
+
logger2.warn("\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043D\u0435 \u0443\u0434\u0430\u043B\u0430\u0441\u044C, \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u043C fallback", {
|
|
403
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
404
|
+
errorType: error instanceof Error ? error.constructor.name : typeof error
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
return typeof fallback === "function" ? fallback() : fallback;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
async function withFallbackInfo(fn, options) {
|
|
411
|
+
const { fallback, silent = false, logger: logger2, ...retryOptions } = options;
|
|
412
|
+
try {
|
|
413
|
+
const result = await withRetry(fn, { ...retryOptions, logger: logger2 });
|
|
414
|
+
return {
|
|
415
|
+
data: result.data,
|
|
416
|
+
usedFallback: false
|
|
417
|
+
};
|
|
418
|
+
} catch (error) {
|
|
419
|
+
if (!silent && logger2) {
|
|
420
|
+
logger2.warn("\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F \u043D\u0435 \u0443\u0434\u0430\u043B\u0430\u0441\u044C, \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u043C fallback", {
|
|
421
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
const fallbackValue = typeof fallback === "function" ? fallback() : fallback;
|
|
425
|
+
return {
|
|
426
|
+
data: fallbackValue,
|
|
427
|
+
usedFallback: true,
|
|
428
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
}
|
|
395
432
|
var VoyageEmbeddingResponseSchema = z.object({
|
|
396
433
|
/** Массив эмбеддингов */
|
|
397
434
|
data: z.array(
|
|
@@ -542,6 +579,6 @@ function parseOrThrow(schema, data, errorMessage = "Validation failed") {
|
|
|
542
579
|
return result.data;
|
|
543
580
|
}
|
|
544
581
|
|
|
545
|
-
export { AnthropicApiError, ApiError, AppError, ChatRequestSchema, ClaudeMessageSchema, ConfigError, Logger, SourceSchema, TurbopufferApiError, TurbopufferSearchResultSchema, ValidationError, VectorAttributesSchema, VoyageApiError, VoyageEmbeddingResponseSchema, VoyageRerankResponseSchema, anthropicLogger, apiLogger, createTimer, isAppError, logger, parseOrThrow, retryApiCall, retryCritical, safeParse, sleep, turbopufferLogger, voyageLogger, withRetry, wrapError };
|
|
582
|
+
export { AnthropicApiError, ApiError, AppError, ChatRequestSchema, ClaudeMessageSchema, ConfigError, Logger, SourceSchema, TurbopufferApiError, TurbopufferSearchResultSchema, ValidationError, VectorAttributesSchema, VoyageApiError, VoyageEmbeddingResponseSchema, VoyageRerankResponseSchema, anthropicLogger, apiLogger, createTimer, isAppError, logger, parseOrThrow, retryApiCall, retryCritical, safeParse, sleep, turbopufferLogger, voyageLogger, withFallback, withFallbackInfo, withRetry, wrapError };
|
|
546
583
|
//# sourceMappingURL=index.mjs.map
|
|
547
584
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/logger.ts","../src/retry.ts","../src/schemas.ts"],"names":["logger"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Кастомные классы ошибок\n *\n * Иерархия ошибок для структурированной обработки исключений.\n * Каждый класс содержит дополнительный контекст для отладки.\n *\n * @module errors\n */\n\n// ============================================================================\n// Базовый класс\n// ============================================================================\n\n/**\n * Базовый класс для всех ошибок приложения\n *\n * Расширяет стандартный Error с дополнительными полями:\n * - code: машиночитаемый код ошибки\n * - context: дополнительные данные для отладки\n * - retryable: можно ли повторить операцию\n */\nexport class AppError extends Error {\n /** Машиночитаемый код ошибки */\n readonly code: string;\n /** Дополнительный контекст для отладки */\n readonly context?: Record<string, unknown>;\n /** Можно ли повторить операцию */\n readonly retryable: boolean;\n /** Временная метка создания ошибки */\n readonly timestamp: Date;\n\n constructor(\n message: string,\n options: {\n code?: string;\n context?: Record<string, unknown>;\n retryable?: boolean;\n cause?: Error;\n } = {}\n ) {\n super(message, { cause: options.cause });\n this.name = 'AppError';\n this.code = options.code || 'APP_ERROR';\n this.context = options.context;\n this.retryable = options.retryable ?? false;\n this.timestamp = new Date();\n }\n\n /**\n * Преобразовать в JSON для логирования\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n context: this.context,\n retryable: this.retryable,\n timestamp: this.timestamp.toISOString(),\n stack: this.stack,\n };\n }\n}\n\n// ============================================================================\n// Ошибки API\n// ============================================================================\n\n/**\n * Ошибка при вызове внешнего API\n *\n * Используется для Voyage AI, Anthropic, Turbopuffer.\n */\nexport class ApiError extends AppError {\n /** HTTP статус код */\n readonly statusCode: number;\n /** Имя сервиса */\n readonly service: string;\n\n constructor(\n message: string,\n options: {\n statusCode: number;\n service: string;\n context?: Record<string, unknown>;\n retryable?: boolean;\n cause?: Error;\n }\n ) {\n super(message, {\n code: `${options.service.toUpperCase()}_API_ERROR`,\n context: { ...options.context, statusCode: options.statusCode },\n retryable: options.retryable ?? isRetryableStatus(options.statusCode),\n cause: options.cause,\n });\n this.name = 'ApiError';\n this.statusCode = options.statusCode;\n this.service = options.service;\n }\n}\n\n/**\n * Ошибка Voyage AI API\n */\nexport class VoyageApiError extends ApiError {\n constructor(\n message: string,\n statusCode: number,\n context?: Record<string, unknown>\n ) {\n super(message, {\n statusCode,\n service: 'voyage',\n context,\n });\n this.name = 'VoyageApiError';\n }\n}\n\n/**\n * Ошибка Anthropic API\n */\nexport class AnthropicApiError extends ApiError {\n constructor(\n message: string,\n statusCode: number,\n context?: Record<string, unknown>\n ) {\n super(message, {\n statusCode,\n service: 'anthropic',\n context,\n });\n this.name = 'AnthropicApiError';\n }\n}\n\n/**\n * Ошибка Turbopuffer API\n */\nexport class TurbopufferApiError extends ApiError {\n constructor(\n message: string,\n statusCode: number,\n context?: Record<string, unknown>\n ) {\n super(message, {\n statusCode,\n service: 'turbopuffer',\n context,\n });\n this.name = 'TurbopufferApiError';\n }\n}\n\n// ============================================================================\n// Ошибки валидации\n// ============================================================================\n\n/**\n * Ошибка валидации данных\n *\n * Используется при невалидных входных данных или ответах API.\n */\nexport class ValidationError extends AppError {\n /** Поле, в котором обнаружена ошибка */\n readonly field?: string;\n /** Ожидаемое значение или тип */\n readonly expected?: string;\n /** Полученное значение */\n readonly received?: unknown;\n\n constructor(\n message: string,\n options: {\n field?: string;\n expected?: string;\n received?: unknown;\n context?: Record<string, unknown>;\n } = {}\n ) {\n super(message, {\n code: 'VALIDATION_ERROR',\n context: {\n ...options.context,\n field: options.field,\n expected: options.expected,\n received: options.received,\n },\n retryable: false,\n });\n this.name = 'ValidationError';\n this.field = options.field;\n this.expected = options.expected;\n this.received = options.received;\n }\n}\n\n// ============================================================================\n// Ошибки конфигурации\n// ============================================================================\n\n/**\n * Ошибка отсутствующей конфигурации\n *\n * Используется при отсутствии обязательных переменных окружения.\n */\nexport class ConfigError extends AppError {\n /** Имя отсутствующей переменной */\n readonly variableName: string;\n\n constructor(variableName: string) {\n super(`Отсутствует обязательная переменная окружения: ${variableName}`, {\n code: 'CONFIG_ERROR',\n context: { variableName },\n retryable: false,\n });\n this.name = 'ConfigError';\n this.variableName = variableName;\n }\n}\n\n// ============================================================================\n// Вспомогательные функции\n// ============================================================================\n\n/**\n * Определить, можно ли повторить запрос по HTTP статусу\n *\n * Повторяемые статусы:\n * - 408: Request Timeout\n * - 429: Too Many Requests\n * - 500: Internal Server Error\n * - 502: Bad Gateway\n * - 503: Service Unavailable\n * - 504: Gateway Timeout\n */\nfunction isRetryableStatus(statusCode: number): boolean {\n return [408, 429, 500, 502, 503, 504].includes(statusCode);\n}\n\n/**\n * Проверить, является ли ошибка экземпляром AppError\n */\nexport function isAppError(error: unknown): error is AppError {\n return error instanceof AppError;\n}\n\n/**\n * Обернуть неизвестную ошибку в AppError\n */\nexport function wrapError(error: unknown, defaultMessage = 'Неизвестная ошибка'): AppError {\n if (error instanceof AppError) {\n return error;\n }\n\n if (error instanceof Error) {\n return new AppError(error.message || defaultMessage, {\n cause: error,\n context: { originalName: error.name },\n });\n }\n\n return new AppError(defaultMessage, {\n context: { originalError: error },\n });\n}\n","/**\n * Структурированное логирование\n *\n * Централизованный логгер с уровнями и форматированием.\n * В продакшене выводит JSON для парсинга CloudWatch/Datadog.\n * В dev режиме — читаемый формат с цветами.\n *\n * @module logger\n */\n\n// ============================================================================\n// Типы\n// ============================================================================\n\n/** Уровни логирования */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\n/** Метаданные для структурированного логирования */\nexport interface LogMeta {\n /** Имя модуля/компонента */\n module?: string;\n /** ID операции для трейсинга */\n operationId?: string;\n /** ID пользователя */\n userId?: string;\n /** Длительность операции в мс */\n durationMs?: number;\n /** Дополнительные поля */\n [key: string]: unknown;\n}\n\n/** Структура лог-записи */\ninterface LogEntry {\n timestamp: string;\n level: LogLevel;\n message: string;\n meta?: LogMeta;\n error?: {\n name: string;\n message: string;\n stack?: string;\n };\n}\n\n// ============================================================================\n// Конфигурация\n// ============================================================================\n\n/** Приоритет уровней (меньше = важнее) */\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n/** Цвета для консоли в dev режиме */\nconst COLORS: Record<LogLevel, string> = {\n debug: '\\x1b[36m', // Cyan\n info: '\\x1b[32m', // Green\n warn: '\\x1b[33m', // Yellow\n error: '\\x1b[31m', // Red\n};\nconst RESET = '\\x1b[0m';\n\n/** Текущий уровень логирования */\nfunction getCurrentLogLevel(): LogLevel {\n const envLevel = process.env.LOG_LEVEL?.toLowerCase();\n if (envLevel && envLevel in LOG_LEVEL_PRIORITY) {\n return envLevel as LogLevel;\n }\n return process.env.NODE_ENV === 'production' ? 'info' : 'debug';\n}\n\n/** Проверка, включён ли dev режим */\nfunction isDev(): boolean {\n return process.env.NODE_ENV !== 'production';\n}\n\n// ============================================================================\n// Форматирование\n// ============================================================================\n\n/**\n * Форматировать лог-запись для консоли\n */\nfunction formatLogEntry(entry: LogEntry): string {\n if (isDev()) {\n // Dev режим: читаемый формат с цветами\n const color = COLORS[entry.level];\n const levelStr = entry.level.toUpperCase().padEnd(5);\n const time = new Date(entry.timestamp).toLocaleTimeString();\n\n let output = `${color}[${levelStr}]${RESET} ${time} ${entry.message}`;\n\n if (entry.meta && Object.keys(entry.meta).length > 0) {\n output += ` ${JSON.stringify(entry.meta)}`;\n }\n\n if (entry.error) {\n output += `\\n Error: ${entry.error.name}: ${entry.error.message}`;\n if (entry.error.stack) {\n output += `\\n ${entry.error.stack.split('\\n').slice(1).join('\\n ')}`;\n }\n }\n\n return output;\n }\n\n // Production: JSON для парсинга\n return JSON.stringify(entry);\n}\n\n/**\n * Сериализовать ошибку для логирования\n */\nfunction serializeError(error: Error): LogEntry['error'] {\n return {\n name: error.name,\n message: error.message,\n stack: error.stack,\n };\n}\n\n// ============================================================================\n// Основной класс логгера\n// ============================================================================\n\n/**\n * Класс логгера\n *\n * Создаёт экземпляр с привязкой к модулю.\n *\n * @example\n * const log = new Logger('voyage');\n * log.info('Запрос отправлен', { tokens: 1500 });\n * log.error('Ошибка API', new Error('timeout'));\n */\nexport class Logger {\n private readonly module: string;\n private readonly minLevel: LogLevel;\n\n constructor(module: string) {\n this.module = module;\n this.minLevel = getCurrentLogLevel();\n }\n\n /**\n * Проверить, включён ли данный уровень\n */\n private isEnabled(level: LogLevel): boolean {\n return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[this.minLevel];\n }\n\n /**\n * Записать лог\n */\n private log(level: LogLevel, message: string, meta?: LogMeta, error?: Error): void {\n if (!this.isEnabled(level)) return;\n\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n level,\n message,\n meta: { module: this.module, ...meta },\n };\n\n if (error) {\n entry.error = serializeError(error);\n }\n\n const formatted = formatLogEntry(entry);\n\n switch (level) {\n case 'error':\n console.error(formatted);\n break;\n case 'warn':\n console.warn(formatted);\n break;\n default:\n console.log(formatted);\n }\n }\n\n /**\n * Debug уровень — детальная информация для отладки\n */\n debug(message: string, meta?: LogMeta): void {\n this.log('debug', message, meta);\n }\n\n /**\n * Info уровень — информационные сообщения\n */\n info(message: string, meta?: LogMeta): void {\n this.log('info', message, meta);\n }\n\n /**\n * Warn уровень — предупреждения\n */\n warn(message: string, meta?: LogMeta): void {\n this.log('warn', message, meta);\n }\n\n /**\n * Error уровень — ошибки\n */\n error(message: string, error?: Error | unknown, meta?: LogMeta): void {\n const err = error instanceof Error ? error : undefined;\n this.log('error', message, meta, err);\n }\n\n /**\n * Создать child logger с дополнительным контекстом\n */\n child(context: LogMeta): ChildLogger {\n return new ChildLogger(this, context);\n }\n}\n\n/**\n * Child logger с привязанным контекстом\n */\nclass ChildLogger {\n constructor(\n private readonly parent: Logger,\n private readonly context: LogMeta\n ) {}\n\n debug(message: string, meta?: LogMeta): void {\n this.parent.debug(message, { ...this.context, ...meta });\n }\n\n info(message: string, meta?: LogMeta): void {\n this.parent.info(message, { ...this.context, ...meta });\n }\n\n warn(message: string, meta?: LogMeta): void {\n this.parent.warn(message, { ...this.context, ...meta });\n }\n\n error(message: string, error?: Error | unknown, meta?: LogMeta): void {\n this.parent.error(message, error, { ...this.context, ...meta });\n }\n}\n\n// ============================================================================\n// Готовые экземпляры логгеров\n// ============================================================================\n\n/** Логгер для Voyage AI */\nexport const voyageLogger = new Logger('voyage');\n\n/** Логгер для Turbopuffer */\nexport const turbopufferLogger = new Logger('turbopuffer');\n\n/** Логгер для Anthropic */\nexport const anthropicLogger = new Logger('anthropic');\n\n/** Логгер для API запросов */\nexport const apiLogger = new Logger('api');\n\n/** Логгер общего назначения */\nexport const logger = new Logger('app');\n\n// ============================================================================\n// Утилиты для измерения времени\n// ============================================================================\n\n/**\n * Создать таймер для измерения длительности операции\n *\n * @example\n * const timer = createTimer();\n * await doSomething();\n * log.info('Операция завершена', { durationMs: timer() });\n */\nexport function createTimer(): () => number {\n const start = performance.now();\n return () => Math.round(performance.now() - start);\n}\n","/**\n * Retry логика с exponential backoff\n *\n * Утилиты для повторения неудачных операций с экспоненциальной\n * задержкой и джиттером для предотвращения thundering herd.\n *\n * @module retry\n */\n\nimport { Logger } from './logger';\nimport { AppError, isAppError } from './errors';\n\n// ============================================================================\n// Типы\n// ============================================================================\n\n/**\n * Опции для retry\n */\nexport interface RetryOptions {\n /** Максимальное количество попыток (включая первую) */\n maxAttempts?: number;\n /** Базовая задержка в мс (удваивается с каждой попыткой) */\n baseDelayMs?: number;\n /** Максимальная задержка в мс */\n maxDelayMs?: number;\n /** Добавлять случайный джиттер (0-1, доля от задержки) */\n jitter?: number;\n /** Функция для определения, нужно ли повторять */\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n /** Callback при каждой неудачной попытке */\n onRetry?: (error: unknown, attempt: number, delayMs: number) => void;\n /** Логгер для записи попыток */\n logger?: Logger;\n}\n\n/**\n * Результат выполнения с retry\n */\nexport interface RetryResult<T> {\n /** Результат успешного выполнения */\n data: T;\n /** Количество попыток (1 = успех с первого раза) */\n attempts: number;\n /** Общее время выполнения в мс */\n totalTimeMs: number;\n}\n\n// ============================================================================\n// Константы по умолчанию\n// ============================================================================\n\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_BASE_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 30000;\nconst DEFAULT_JITTER = 0.1;\n\n// ============================================================================\n// Вспомогательные функции\n// ============================================================================\n\n/**\n * Ожидать указанное количество миллисекунд\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Рассчитать задержку с экспоненциальным ростом и джиттером\n *\n * @param attempt - Номер попытки (начиная с 1)\n * @param baseDelayMs - Базовая задержка\n * @param maxDelayMs - Максимальная задержка\n * @param jitter - Джиттер (0-1)\n * @returns Задержка в мс\n */\nfunction calculateDelay(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n jitter: number\n): number {\n // Экспоненциальный рост: base * 2^(attempt-1)\n const exponentialDelay = baseDelayMs * Math.pow(2, attempt - 1);\n\n // Ограничиваем максимальной задержкой\n const cappedDelay = Math.min(exponentialDelay, maxDelayMs);\n\n // Добавляем джиттер\n const jitterAmount = cappedDelay * jitter * Math.random();\n\n return Math.round(cappedDelay + jitterAmount);\n}\n\n/**\n * Определить по умолчанию, нужно ли повторять\n *\n * Повторяем если:\n * - Ошибка помечена как retryable\n * - Это сетевая ошибка (fetch failed, timeout)\n */\nfunction defaultShouldRetry(error: unknown): boolean {\n // AppError с флагом retryable\n if (isAppError(error) && error.retryable) {\n return true;\n }\n\n // Стандартные сетевые ошибки\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n const networkErrors = [\n 'fetch failed',\n 'network error',\n 'timeout',\n 'econnreset',\n 'econnrefused',\n 'socket hang up',\n ];\n return networkErrors.some((e) => message.includes(e));\n }\n\n return false;\n}\n\n// ============================================================================\n// Основная функция\n// ============================================================================\n\n/**\n * Выполнить функцию с retry и exponential backoff\n *\n * @param fn - Асинхронная функция для выполнения\n * @param options - Опции retry\n * @returns Результат выполнения с метаданными\n * @throws Последняя ошибка, если все попытки исчерпаны\n *\n * @example\n * const result = await withRetry(\n * () => fetch('https://api.example.com/data'),\n * { maxAttempts: 3, baseDelayMs: 1000 }\n * );\n * console.log(`Успех за ${result.attempts} попыток`);\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<RetryResult<T>> {\n const {\n maxAttempts = DEFAULT_MAX_ATTEMPTS,\n baseDelayMs = DEFAULT_BASE_DELAY_MS,\n maxDelayMs = DEFAULT_MAX_DELAY_MS,\n jitter = DEFAULT_JITTER,\n shouldRetry = defaultShouldRetry,\n onRetry,\n logger,\n } = options;\n\n const startTime = performance.now();\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const data = await fn();\n return {\n data,\n attempts: attempt,\n totalTimeMs: Math.round(performance.now() - startTime),\n };\n } catch (error) {\n lastError = error;\n\n // Последняя попытка — бросаем ошибку\n if (attempt >= maxAttempts) {\n logger?.error(`Все ${maxAttempts} попыток исчерпаны`, error);\n break;\n }\n\n // Проверяем, нужно ли повторять\n if (!shouldRetry(error, attempt)) {\n logger?.warn(`Ошибка не подлежит повторению на попытке ${attempt}`, {\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n break;\n }\n\n // Рассчитываем задержку\n const delayMs = calculateDelay(attempt, baseDelayMs, maxDelayMs, jitter);\n\n logger?.info(`Попытка ${attempt}/${maxAttempts} не удалась, повтор через ${delayMs}мс`, {\n errorMessage: error instanceof Error ? error.message : String(error),\n delayMs,\n });\n\n // Вызываем callback\n onRetry?.(error, attempt, delayMs);\n\n // Ждём перед следующей попыткой\n await sleep(delayMs);\n }\n }\n\n // Если дошли сюда — все попытки исчерпаны\n throw lastError;\n}\n\n// ============================================================================\n// Обёртки для специфичных сценариев\n// ============================================================================\n\n/**\n * Retry для API запросов с предустановленными параметрами\n *\n * Оптимизировано для внешних API (Voyage, Anthropic, Turbopuffer).\n *\n * @example\n * const response = await retryApiCall(\n * () => fetch(VOYAGE_API_URL, { method: 'POST', body }),\n * { logger: voyageLogger }\n * );\n */\nexport async function retryApiCall<T>(\n fn: () => Promise<T>,\n options: Pick<RetryOptions, 'logger' | 'onRetry' | 'maxAttempts'> = {}\n): Promise<T> {\n const result = await withRetry(fn, {\n maxAttempts: options.maxAttempts ?? 3,\n baseDelayMs: 1000,\n maxDelayMs: 10000,\n jitter: 0.2,\n logger: options.logger,\n onRetry: options.onRetry,\n });\n\n return result.data;\n}\n\n/**\n * Retry для критичных операций с более агрессивными параметрами\n *\n * Используется для операций, которые обязательно должны выполниться.\n *\n * @example\n * await retryCritical(\n * () => saveToDatabase(data),\n * { logger }\n * );\n */\nexport async function retryCritical<T>(\n fn: () => Promise<T>,\n options: Pick<RetryOptions, 'logger' | 'onRetry'> = {}\n): Promise<T> {\n const result = await withRetry(fn, {\n maxAttempts: 5,\n baseDelayMs: 500,\n maxDelayMs: 30000,\n jitter: 0.3,\n logger: options.logger,\n onRetry: options.onRetry,\n shouldRetry: () => true, // Повторяем всегда\n });\n\n return result.data;\n}\n","/**\n * Zod схемы для валидации API ответов\n *\n * Типобезопасная валидация ответов от внешних API.\n * Гарантирует соответствие данных ожидаемой структуре.\n *\n * @module schemas\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Voyage AI Schemas\n// ============================================================================\n\n/**\n * Схема ответа Voyage Embeddings API\n *\n * @see https://docs.voyageai.com/docs/embeddings\n */\nexport const VoyageEmbeddingResponseSchema = z.object({\n /** Массив эмбеддингов */\n data: z.array(\n z.object({\n /** Вектор эмбеддинга */\n embedding: z.array(z.number()),\n /** Индекс в исходном массиве */\n index: z.number().optional(),\n })\n ),\n /** Статистика использования */\n usage: z.object({\n /** Общее количество токенов */\n total_tokens: z.number(),\n }),\n /** Модель, использованная для генерации */\n model: z.string().optional(),\n});\n\nexport type VoyageEmbeddingResponse = z.infer<typeof VoyageEmbeddingResponseSchema>;\n\n/**\n * Схема ответа Voyage Rerank API\n *\n * @see https://docs.voyageai.com/docs/reranker\n */\nexport const VoyageRerankResponseSchema = z.object({\n /** Массив результатов реранкинга */\n data: z.array(\n z.object({\n /** Индекс документа в исходном массиве */\n index: z.number(),\n /** Оценка релевантности (0-1) */\n relevance_score: z.number().min(0).max(1),\n })\n ),\n /** Статистика использования */\n usage: z.object({\n /** Общее количество токенов */\n total_tokens: z.number(),\n }),\n /** Модель, использованная для реранкинга */\n model: z.string().optional(),\n});\n\nexport type VoyageRerankResponse = z.infer<typeof VoyageRerankResponseSchema>;\n\n// ============================================================================\n// Turbopuffer Schemas\n// ============================================================================\n\n/**\n * Базовая схема атрибутов вектора\n */\nexport const VectorAttributesSchema = z.object({\n /** ID записи в Supabase */\n supabase_id: z.number(),\n /** Уникальный ID сообщения/документа */\n message_id: z.string(),\n /** Тип источника */\n source_type: z.enum(['email', 'pdf', 'website']),\n /** Тип чанка */\n chunk_type: z.string(),\n /** Email отправителя */\n sender: z.string().optional(),\n /** Email получателя */\n recipient: z.string().optional(),\n /** Дата источника */\n source_date: z.string().optional(),\n /** ID цепочки писем */\n thread_id: z.string().optional(),\n /** ID клиента */\n client_id: z.string().optional(),\n /** URL источника */\n source_url: z.string().optional(),\n /** Номер страницы */\n page_number: z.number().optional(),\n /** Заголовок секции */\n section_title: z.string().optional(),\n /** ID в content_sources */\n content_source_id: z.number().optional(),\n /** Тема письма */\n subject: z.string().optional(),\n /** Превью контента */\n content_preview: z.string().optional(),\n /** Заголовок документа */\n title: z.string().optional(),\n /** Полный контент */\n content: z.string().optional(),\n /** Категория */\n category: z.string().optional(),\n /** Тональность */\n sentiment: z.enum(['positive', 'negative', 'neutral']).optional(),\n /** Дата создания */\n created_at: z.string().optional(),\n});\n\nexport type VectorAttributes = z.infer<typeof VectorAttributesSchema>;\n\n/**\n * Схема результата поиска Turbopuffer\n */\nexport const TurbopufferSearchResultSchema = z.object({\n /** ID вектора */\n id: z.string(),\n /** Расстояние до запроса */\n dist: z.number(),\n /** Атрибуты вектора */\n attributes: VectorAttributesSchema.partial(),\n});\n\nexport type TurbopufferSearchResult = z.infer<typeof TurbopufferSearchResultSchema>;\n\n// ============================================================================\n// Anthropic Schemas\n// ============================================================================\n\n/**\n * Схема сообщения в ответе Claude\n */\nexport const ClaudeMessageSchema = z.object({\n /** ID сообщения */\n id: z.string(),\n /** Тип объекта */\n type: z.literal('message'),\n /** Роль */\n role: z.enum(['assistant', 'user']),\n /** Контент */\n content: z.array(\n z.object({\n type: z.enum(['text', 'tool_use']),\n text: z.string().optional(),\n })\n ),\n /** Модель */\n model: z.string(),\n /** Причина остановки */\n stop_reason: z.enum(['end_turn', 'max_tokens', 'stop_sequence', 'tool_use']).nullable(),\n /** Использование токенов */\n usage: z.object({\n input_tokens: z.number(),\n output_tokens: z.number(),\n }),\n});\n\nexport type ClaudeMessage = z.infer<typeof ClaudeMessageSchema>;\n\n// ============================================================================\n// Chat API Schemas\n// ============================================================================\n\n/**\n * Схема входящего запроса к Chat API\n */\nexport const ChatRequestSchema = z.object({\n /** Сообщение пользователя */\n message: z.string().min(1).max(10000),\n /** История сообщений */\n history: z\n .array(\n z.object({\n role: z.enum(['user', 'assistant']),\n content: z.string(),\n })\n )\n .optional()\n .default([]),\n /** ID сессии */\n sessionId: z.string().optional(),\n /** Режим (customer/internal) */\n mode: z.enum(['customer', 'internal']).optional().default('customer'),\n});\n\nexport type ChatRequest = z.infer<typeof ChatRequestSchema>;\n\n/**\n * Схема источника в ответе\n */\nexport const SourceSchema = z.object({\n /** Тип источника */\n type: z.enum(['email', 'pdf', 'website']),\n /** Заголовок */\n title: z.string(),\n /** URL или идентификатор */\n url: z.string().optional(),\n /** Превью контента */\n preview: z.string().optional(),\n /** Оценка релевантности */\n relevance: z.number().optional(),\n});\n\nexport type Source = z.infer<typeof SourceSchema>;\n\n// ============================================================================\n// Утилиты для валидации\n// ============================================================================\n\n/**\n * Безопасно распарсить данные по схеме\n *\n * @param schema - Zod схема\n * @param data - Данные для валидации\n * @returns Результат парсинга или null при ошибке\n *\n * @example\n * const response = await fetch(url);\n * const data = await response.json();\n * const parsed = safeParse(VoyageEmbeddingResponseSchema, data);\n * if (!parsed) throw new ValidationError('Invalid API response');\n */\nexport function safeParse<T>(\n schema: z.ZodType<T>,\n data: unknown\n): T | null {\n const result = schema.safeParse(data);\n return result.success ? result.data : null;\n}\n\n/**\n * Распарсить данные по схеме с выбросом ошибки\n *\n * @param schema - Zod схема\n * @param data - Данные для валидации\n * @param errorMessage - Сообщение об ошибке\n * @returns Валидные данные\n * @throws Error при невалидных данных\n */\nexport function parseOrThrow<T>(\n schema: z.ZodType<T>,\n data: unknown,\n errorMessage = 'Validation failed'\n): T {\n const result = schema.safeParse(data);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ');\n throw new Error(`${errorMessage}: ${issues}`);\n }\n return result.data;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/logger.ts","../src/retry.ts","../src/schemas.ts"],"names":["logger"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Кастомные классы ошибок\n *\n * Иерархия ошибок для структурированной обработки исключений.\n * Каждый класс содержит дополнительный контекст для отладки.\n *\n * @module errors\n */\n\n// ============================================================================\n// Базовый класс\n// ============================================================================\n\n/**\n * Базовый класс для всех ошибок приложения\n *\n * Расширяет стандартный Error с дополнительными полями:\n * - code: машиночитаемый код ошибки\n * - context: дополнительные данные для отладки\n * - retryable: можно ли повторить операцию\n */\nexport class AppError extends Error {\n /** Машиночитаемый код ошибки */\n readonly code: string;\n /** Дополнительный контекст для отладки */\n readonly context?: Record<string, unknown>;\n /** Можно ли повторить операцию */\n readonly retryable: boolean;\n /** Временная метка создания ошибки */\n readonly timestamp: Date;\n\n constructor(\n message: string,\n options: {\n code?: string;\n context?: Record<string, unknown>;\n retryable?: boolean;\n cause?: Error;\n } = {}\n ) {\n super(message, { cause: options.cause });\n this.name = 'AppError';\n this.code = options.code || 'APP_ERROR';\n this.context = options.context;\n this.retryable = options.retryable ?? false;\n this.timestamp = new Date();\n }\n\n /**\n * Преобразовать в JSON для логирования\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n context: this.context,\n retryable: this.retryable,\n timestamp: this.timestamp.toISOString(),\n stack: this.stack,\n };\n }\n}\n\n// ============================================================================\n// Ошибки API\n// ============================================================================\n\n/**\n * Ошибка при вызове внешнего API\n *\n * Используется для Voyage AI, Anthropic, Turbopuffer.\n */\nexport class ApiError extends AppError {\n /** HTTP статус код */\n readonly statusCode: number;\n /** Имя сервиса */\n readonly service: string;\n\n constructor(\n message: string,\n options: {\n statusCode: number;\n service: string;\n context?: Record<string, unknown>;\n retryable?: boolean;\n cause?: Error;\n }\n ) {\n super(message, {\n code: `${options.service.toUpperCase()}_API_ERROR`,\n context: { ...options.context, statusCode: options.statusCode },\n retryable: options.retryable ?? isRetryableStatus(options.statusCode),\n cause: options.cause,\n });\n this.name = 'ApiError';\n this.statusCode = options.statusCode;\n this.service = options.service;\n }\n}\n\n/**\n * Ошибка Voyage AI API\n */\nexport class VoyageApiError extends ApiError {\n constructor(\n message: string,\n statusCode: number,\n context?: Record<string, unknown>\n ) {\n super(message, {\n statusCode,\n service: 'voyage',\n context,\n });\n this.name = 'VoyageApiError';\n }\n}\n\n/**\n * Ошибка Anthropic API\n */\nexport class AnthropicApiError extends ApiError {\n constructor(\n message: string,\n statusCode: number,\n context?: Record<string, unknown>\n ) {\n super(message, {\n statusCode,\n service: 'anthropic',\n context,\n });\n this.name = 'AnthropicApiError';\n }\n}\n\n/**\n * Ошибка Turbopuffer API\n */\nexport class TurbopufferApiError extends ApiError {\n constructor(\n message: string,\n statusCode: number,\n context?: Record<string, unknown>\n ) {\n super(message, {\n statusCode,\n service: 'turbopuffer',\n context,\n });\n this.name = 'TurbopufferApiError';\n }\n}\n\n// ============================================================================\n// Ошибки валидации\n// ============================================================================\n\n/**\n * Ошибка валидации данных\n *\n * Используется при невалидных входных данных или ответах API.\n */\nexport class ValidationError extends AppError {\n /** Поле, в котором обнаружена ошибка */\n readonly field?: string;\n /** Ожидаемое значение или тип */\n readonly expected?: string;\n /** Полученное значение */\n readonly received?: unknown;\n\n constructor(\n message: string,\n options: {\n field?: string;\n expected?: string;\n received?: unknown;\n context?: Record<string, unknown>;\n } = {}\n ) {\n super(message, {\n code: 'VALIDATION_ERROR',\n context: {\n ...options.context,\n field: options.field,\n expected: options.expected,\n received: options.received,\n },\n retryable: false,\n });\n this.name = 'ValidationError';\n this.field = options.field;\n this.expected = options.expected;\n this.received = options.received;\n }\n}\n\n// ============================================================================\n// Ошибки конфигурации\n// ============================================================================\n\n/**\n * Ошибка отсутствующей конфигурации\n *\n * Используется при отсутствии обязательных переменных окружения.\n */\nexport class ConfigError extends AppError {\n /** Имя отсутствующей переменной */\n readonly variableName: string;\n\n constructor(variableName: string) {\n super(`Отсутствует обязательная переменная окружения: ${variableName}`, {\n code: 'CONFIG_ERROR',\n context: { variableName },\n retryable: false,\n });\n this.name = 'ConfigError';\n this.variableName = variableName;\n }\n}\n\n// ============================================================================\n// Вспомогательные функции\n// ============================================================================\n\n/**\n * Определить, можно ли повторить запрос по HTTP статусу\n *\n * Повторяемые статусы:\n * - 408: Request Timeout\n * - 429: Too Many Requests\n * - 500: Internal Server Error\n * - 502: Bad Gateway\n * - 503: Service Unavailable\n * - 504: Gateway Timeout\n */\nfunction isRetryableStatus(statusCode: number): boolean {\n return [408, 429, 500, 502, 503, 504].includes(statusCode);\n}\n\n/**\n * Проверить, является ли ошибка экземпляром AppError\n */\nexport function isAppError(error: unknown): error is AppError {\n return error instanceof AppError;\n}\n\n/**\n * Обернуть неизвестную ошибку в AppError\n */\nexport function wrapError(error: unknown, defaultMessage = 'Неизвестная ошибка'): AppError {\n if (error instanceof AppError) {\n return error;\n }\n\n if (error instanceof Error) {\n return new AppError(error.message || defaultMessage, {\n cause: error,\n context: { originalName: error.name },\n });\n }\n\n return new AppError(defaultMessage, {\n context: { originalError: error },\n });\n}\n","/**\n * Структурированное логирование\n *\n * Централизованный логгер с уровнями и форматированием.\n * В продакшене выводит JSON для парсинга CloudWatch/Datadog.\n * В dev режиме — читаемый формат с цветами.\n *\n * @module logger\n */\n\n// ============================================================================\n// Типы\n// ============================================================================\n\n/** Уровни логирования */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\n/** Метаданные для структурированного логирования */\nexport interface LogMeta {\n /** Имя модуля/компонента */\n module?: string;\n /** ID операции для трейсинга */\n operationId?: string;\n /** ID пользователя */\n userId?: string;\n /** Длительность операции в мс */\n durationMs?: number;\n /** Дополнительные поля */\n [key: string]: unknown;\n}\n\n/** Структура лог-записи */\ninterface LogEntry {\n timestamp: string;\n level: LogLevel;\n message: string;\n meta?: LogMeta;\n error?: {\n name: string;\n message: string;\n stack?: string;\n };\n}\n\n// ============================================================================\n// Конфигурация\n// ============================================================================\n\n/** Приоритет уровней (меньше = важнее) */\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n/** Цвета для консоли в dev режиме */\nconst COLORS: Record<LogLevel, string> = {\n debug: '\\x1b[36m', // Cyan\n info: '\\x1b[32m', // Green\n warn: '\\x1b[33m', // Yellow\n error: '\\x1b[31m', // Red\n};\nconst RESET = '\\x1b[0m';\n\n/** Текущий уровень логирования */\nfunction getCurrentLogLevel(): LogLevel {\n const envLevel = process.env.LOG_LEVEL?.toLowerCase();\n if (envLevel && envLevel in LOG_LEVEL_PRIORITY) {\n return envLevel as LogLevel;\n }\n return process.env.NODE_ENV === 'production' ? 'info' : 'debug';\n}\n\n/** Проверка, включён ли dev режим */\nfunction isDev(): boolean {\n return process.env.NODE_ENV !== 'production';\n}\n\n// ============================================================================\n// Форматирование\n// ============================================================================\n\n/**\n * Форматировать лог-запись для консоли\n */\nfunction formatLogEntry(entry: LogEntry): string {\n if (isDev()) {\n // Dev режим: читаемый формат с цветами\n const color = COLORS[entry.level];\n const levelStr = entry.level.toUpperCase().padEnd(5);\n const time = new Date(entry.timestamp).toLocaleTimeString();\n\n let output = `${color}[${levelStr}]${RESET} ${time} ${entry.message}`;\n\n if (entry.meta && Object.keys(entry.meta).length > 0) {\n output += ` ${JSON.stringify(entry.meta)}`;\n }\n\n if (entry.error) {\n output += `\\n Error: ${entry.error.name}: ${entry.error.message}`;\n if (entry.error.stack) {\n output += `\\n ${entry.error.stack.split('\\n').slice(1).join('\\n ')}`;\n }\n }\n\n return output;\n }\n\n // Production: JSON для парсинга\n return JSON.stringify(entry);\n}\n\n/**\n * Сериализовать ошибку для логирования\n */\nfunction serializeError(error: Error): LogEntry['error'] {\n return {\n name: error.name,\n message: error.message,\n stack: error.stack,\n };\n}\n\n// ============================================================================\n// Основной класс логгера\n// ============================================================================\n\n/**\n * Класс логгера\n *\n * Создаёт экземпляр с привязкой к модулю.\n *\n * @example\n * const log = new Logger('voyage');\n * log.info('Запрос отправлен', { tokens: 1500 });\n * log.error('Ошибка API', new Error('timeout'));\n */\nexport class Logger {\n private readonly module: string;\n private readonly minLevel: LogLevel;\n\n constructor(module: string) {\n this.module = module;\n this.minLevel = getCurrentLogLevel();\n }\n\n /**\n * Проверить, включён ли данный уровень\n */\n private isEnabled(level: LogLevel): boolean {\n return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[this.minLevel];\n }\n\n /**\n * Записать лог\n */\n private log(level: LogLevel, message: string, meta?: LogMeta, error?: Error): void {\n if (!this.isEnabled(level)) return;\n\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n level,\n message,\n meta: { module: this.module, ...meta },\n };\n\n if (error) {\n entry.error = serializeError(error);\n }\n\n const formatted = formatLogEntry(entry);\n\n switch (level) {\n case 'error':\n console.error(formatted);\n break;\n case 'warn':\n console.warn(formatted);\n break;\n default:\n console.log(formatted);\n }\n }\n\n /**\n * Debug уровень — детальная информация для отладки\n */\n debug(message: string, meta?: LogMeta): void {\n this.log('debug', message, meta);\n }\n\n /**\n * Info уровень — информационные сообщения\n */\n info(message: string, meta?: LogMeta): void {\n this.log('info', message, meta);\n }\n\n /**\n * Warn уровень — предупреждения\n */\n warn(message: string, meta?: LogMeta): void {\n this.log('warn', message, meta);\n }\n\n /**\n * Error уровень — ошибки\n */\n error(message: string, error?: Error | unknown, meta?: LogMeta): void {\n const err = error instanceof Error ? error : undefined;\n this.log('error', message, meta, err);\n }\n\n /**\n * Создать child logger с дополнительным контекстом\n */\n child(context: LogMeta): ChildLogger {\n return new ChildLogger(this, context);\n }\n}\n\n/**\n * Child logger с привязанным контекстом\n */\nclass ChildLogger {\n constructor(\n private readonly parent: Logger,\n private readonly context: LogMeta\n ) {}\n\n debug(message: string, meta?: LogMeta): void {\n this.parent.debug(message, { ...this.context, ...meta });\n }\n\n info(message: string, meta?: LogMeta): void {\n this.parent.info(message, { ...this.context, ...meta });\n }\n\n warn(message: string, meta?: LogMeta): void {\n this.parent.warn(message, { ...this.context, ...meta });\n }\n\n error(message: string, error?: Error | unknown, meta?: LogMeta): void {\n this.parent.error(message, error, { ...this.context, ...meta });\n }\n}\n\n// ============================================================================\n// Готовые экземпляры логгеров\n// ============================================================================\n\n/** Логгер для Voyage AI */\nexport const voyageLogger = new Logger('voyage');\n\n/** Логгер для Turbopuffer */\nexport const turbopufferLogger = new Logger('turbopuffer');\n\n/** Логгер для Anthropic */\nexport const anthropicLogger = new Logger('anthropic');\n\n/** Логгер для API запросов */\nexport const apiLogger = new Logger('api');\n\n/** Логгер общего назначения */\nexport const logger = new Logger('app');\n\n// ============================================================================\n// Утилиты для измерения времени\n// ============================================================================\n\n/**\n * Создать таймер для измерения длительности операции\n *\n * @example\n * const timer = createTimer();\n * await doSomething();\n * log.info('Операция завершена', { durationMs: timer() });\n */\nexport function createTimer(): () => number {\n const start = performance.now();\n return () => Math.round(performance.now() - start);\n}\n","/**\n * Retry логика с exponential backoff\n *\n * Утилиты для повторения неудачных операций с экспоненциальной\n * задержкой и джиттером для предотвращения thundering herd.\n *\n * @module retry\n */\n\nimport { Logger } from './logger';\nimport { AppError, isAppError } from './errors';\n\n// ============================================================================\n// Типы\n// ============================================================================\n\n/**\n * Опции для retry\n */\nexport interface RetryOptions {\n /** Максимальное количество попыток (включая первую) */\n maxAttempts?: number;\n /** Базовая задержка в мс (удваивается с каждой попыткой) */\n baseDelayMs?: number;\n /** Максимальная задержка в мс */\n maxDelayMs?: number;\n /** Добавлять случайный джиттер (0-1, доля от задержки) */\n jitter?: number;\n /** Функция для определения, нужно ли повторять */\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n /** Callback при каждой неудачной попытке */\n onRetry?: (error: unknown, attempt: number, delayMs: number) => void;\n /** Логгер для записи попыток */\n logger?: Logger;\n}\n\n/**\n * Результат выполнения с retry\n */\nexport interface RetryResult<T> {\n /** Результат успешного выполнения */\n data: T;\n /** Количество попыток (1 = успех с первого раза) */\n attempts: number;\n /** Общее время выполнения в мс */\n totalTimeMs: number;\n}\n\n// ============================================================================\n// Константы по умолчанию\n// ============================================================================\n\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_BASE_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 30000;\nconst DEFAULT_JITTER = 0.1;\n\n// ============================================================================\n// Вспомогательные функции\n// ============================================================================\n\n/**\n * Ожидать указанное количество миллисекунд\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Рассчитать задержку с экспоненциальным ростом и джиттером\n *\n * @param attempt - Номер попытки (начиная с 1)\n * @param baseDelayMs - Базовая задержка\n * @param maxDelayMs - Максимальная задержка\n * @param jitter - Джиттер (0-1)\n * @returns Задержка в мс\n */\nfunction calculateDelay(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n jitter: number\n): number {\n // Экспоненциальный рост: base * 2^(attempt-1)\n const exponentialDelay = baseDelayMs * Math.pow(2, attempt - 1);\n\n // Ограничиваем максимальной задержкой\n const cappedDelay = Math.min(exponentialDelay, maxDelayMs);\n\n // Добавляем джиттер\n const jitterAmount = cappedDelay * jitter * Math.random();\n\n return Math.round(cappedDelay + jitterAmount);\n}\n\n/**\n * Определить по умолчанию, нужно ли повторять\n *\n * Повторяем если:\n * - Ошибка помечена как retryable\n * - Это сетевая ошибка (fetch failed, timeout)\n */\nfunction defaultShouldRetry(error: unknown): boolean {\n // AppError с флагом retryable\n if (isAppError(error) && error.retryable) {\n return true;\n }\n\n // Стандартные сетевые ошибки\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n const networkErrors = [\n 'fetch failed',\n 'network error',\n 'timeout',\n 'econnreset',\n 'econnrefused',\n 'socket hang up',\n ];\n return networkErrors.some((e) => message.includes(e));\n }\n\n return false;\n}\n\n// ============================================================================\n// Основная функция\n// ============================================================================\n\n/**\n * Выполнить функцию с retry и exponential backoff\n *\n * @param fn - Асинхронная функция для выполнения\n * @param options - Опции retry\n * @returns Результат выполнения с метаданными\n * @throws Последняя ошибка, если все попытки исчерпаны\n *\n * @example\n * const result = await withRetry(\n * () => fetch('https://api.example.com/data'),\n * { maxAttempts: 3, baseDelayMs: 1000 }\n * );\n * console.log(`Успех за ${result.attempts} попыток`);\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<RetryResult<T>> {\n const {\n maxAttempts = DEFAULT_MAX_ATTEMPTS,\n baseDelayMs = DEFAULT_BASE_DELAY_MS,\n maxDelayMs = DEFAULT_MAX_DELAY_MS,\n jitter = DEFAULT_JITTER,\n shouldRetry = defaultShouldRetry,\n onRetry,\n logger,\n } = options;\n\n const startTime = performance.now();\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const data = await fn();\n return {\n data,\n attempts: attempt,\n totalTimeMs: Math.round(performance.now() - startTime),\n };\n } catch (error) {\n lastError = error;\n\n // Последняя попытка — бросаем ошибку\n if (attempt >= maxAttempts) {\n logger?.error(`Все ${maxAttempts} попыток исчерпаны`, error);\n break;\n }\n\n // Проверяем, нужно ли повторять\n if (!shouldRetry(error, attempt)) {\n logger?.warn(`Ошибка не подлежит повторению на попытке ${attempt}`, {\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n break;\n }\n\n // Рассчитываем задержку\n const delayMs = calculateDelay(attempt, baseDelayMs, maxDelayMs, jitter);\n\n logger?.info(`Попытка ${attempt}/${maxAttempts} не удалась, повтор через ${delayMs}мс`, {\n errorMessage: error instanceof Error ? error.message : String(error),\n delayMs,\n });\n\n // Вызываем callback\n onRetry?.(error, attempt, delayMs);\n\n // Ждём перед следующей попыткой\n await sleep(delayMs);\n }\n }\n\n // Если дошли сюда — все попытки исчерпаны\n throw lastError;\n}\n\n// ============================================================================\n// Обёртки для специфичных сценариев\n// ============================================================================\n\n/**\n * Retry для API запросов с предустановленными параметрами\n *\n * Оптимизировано для внешних API (Voyage, Anthropic, Turbopuffer).\n *\n * @example\n * const response = await retryApiCall(\n * () => fetch(VOYAGE_API_URL, { method: 'POST', body }),\n * { logger: voyageLogger }\n * );\n */\nexport async function retryApiCall<T>(\n fn: () => Promise<T>,\n options: Pick<RetryOptions, 'logger' | 'onRetry' | 'maxAttempts'> = {}\n): Promise<T> {\n const result = await withRetry(fn, {\n maxAttempts: options.maxAttempts ?? 3,\n baseDelayMs: 1000,\n maxDelayMs: 10000,\n jitter: 0.2,\n logger: options.logger,\n onRetry: options.onRetry,\n });\n\n return result.data;\n}\n\n/**\n * Retry для критичных операций с более агрессивными параметрами\n *\n * Используется для операций, которые обязательно должны выполниться.\n *\n * @example\n * await retryCritical(\n * () => saveToDatabase(data),\n * { logger }\n * );\n */\nexport async function retryCritical<T>(\n fn: () => Promise<T>,\n options: Pick<RetryOptions, 'logger' | 'onRetry'> = {}\n): Promise<T> {\n const result = await withRetry(fn, {\n maxAttempts: 5,\n baseDelayMs: 500,\n maxDelayMs: 30000,\n jitter: 0.3,\n logger: options.logger,\n onRetry: options.onRetry,\n shouldRetry: () => true, // Повторяем всегда\n });\n\n return result.data;\n}\n\n// ============================================================================\n// Fallback Helpers\n// ============================================================================\n\n/**\n * Опции для withFallback\n */\nexport interface FallbackOptions<T> extends RetryOptions {\n /** Значение по умолчанию при неудаче */\n fallback: T | (() => T);\n /** Не логировать ошибку (используется когда fallback ожидаем) */\n silent?: boolean;\n}\n\n/**\n * Выполнить функцию с retry и fallback значением при неудаче\n *\n * Используется для graceful degradation — когда операция может упасть,\n * но мы хотим продолжить работу с дефолтным значением.\n *\n * @param fn - Асинхронная функция для выполнения\n * @param options - Опции с обязательным fallback\n * @returns Результат выполнения или fallback значение\n *\n * @example\n * // Rerank с fallback на исходные результаты\n * const reranked = await withFallback(\n * () => rerankResults(query, results),\n * {\n * fallback: results,\n * maxAttempts: 2,\n * logger: voyageLogger,\n * }\n * );\n *\n * @example\n * // Получить настройки с fallback на defaults\n * const settings = await withFallback(\n * () => fetchUserSettings(userId),\n * {\n * fallback: () => DEFAULT_SETTINGS,\n * silent: true, // Не логировать, если настройки не найдены\n * }\n * );\n */\nexport async function withFallback<T>(\n fn: () => Promise<T>,\n options: FallbackOptions<T>\n): Promise<T> {\n const { fallback, silent = false, logger, ...retryOptions } = options;\n\n try {\n const result = await withRetry(fn, { ...retryOptions, logger });\n return result.data;\n } catch (error) {\n if (!silent && logger) {\n logger.warn('Операция не удалась, используем fallback', {\n errorMessage: error instanceof Error ? error.message : String(error),\n errorType: error instanceof Error ? error.constructor.name : typeof error,\n });\n }\n\n // Вычисляем fallback значение\n return typeof fallback === 'function' ? (fallback as () => T)() : fallback;\n }\n}\n\n/**\n * Результат операции с информацией об использовании fallback\n */\nexport interface FallbackResult<T> {\n /** Результат (данные или fallback) */\n data: T;\n /** true если использован fallback */\n usedFallback: boolean;\n /** Ошибка, если была */\n error?: Error;\n}\n\n/**\n * Версия withFallback, которая возвращает информацию об использовании fallback\n *\n * Полезно когда нужно знать, пришли ли данные из источника или из fallback.\n *\n * @example\n * const { data, usedFallback } = await withFallbackInfo(\n * () => fetchLiveData(),\n * { fallback: cachedData }\n * );\n *\n * if (usedFallback) {\n * console.log('Показываем кэшированные данные');\n * }\n */\nexport async function withFallbackInfo<T>(\n fn: () => Promise<T>,\n options: FallbackOptions<T>\n): Promise<FallbackResult<T>> {\n const { fallback, silent = false, logger, ...retryOptions } = options;\n\n try {\n const result = await withRetry(fn, { ...retryOptions, logger });\n return {\n data: result.data,\n usedFallback: false,\n };\n } catch (error) {\n if (!silent && logger) {\n logger.warn('Операция не удалась, используем fallback', {\n errorMessage: error instanceof Error ? error.message : String(error),\n });\n }\n\n const fallbackValue = typeof fallback === 'function'\n ? (fallback as () => T)()\n : fallback;\n\n return {\n data: fallbackValue,\n usedFallback: true,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n}\n","/**\n * Zod схемы для валидации API ответов\n *\n * Типобезопасная валидация ответов от внешних API.\n * Гарантирует соответствие данных ожидаемой структуре.\n *\n * @module schemas\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Voyage AI Schemas\n// ============================================================================\n\n/**\n * Схема ответа Voyage Embeddings API\n *\n * @see https://docs.voyageai.com/docs/embeddings\n */\nexport const VoyageEmbeddingResponseSchema = z.object({\n /** Массив эмбеддингов */\n data: z.array(\n z.object({\n /** Вектор эмбеддинга */\n embedding: z.array(z.number()),\n /** Индекс в исходном массиве */\n index: z.number().optional(),\n })\n ),\n /** Статистика использования */\n usage: z.object({\n /** Общее количество токенов */\n total_tokens: z.number(),\n }),\n /** Модель, использованная для генерации */\n model: z.string().optional(),\n});\n\nexport type VoyageEmbeddingResponse = z.infer<typeof VoyageEmbeddingResponseSchema>;\n\n/**\n * Схема ответа Voyage Rerank API\n *\n * @see https://docs.voyageai.com/docs/reranker\n */\nexport const VoyageRerankResponseSchema = z.object({\n /** Массив результатов реранкинга */\n data: z.array(\n z.object({\n /** Индекс документа в исходном массиве */\n index: z.number(),\n /** Оценка релевантности (0-1) */\n relevance_score: z.number().min(0).max(1),\n })\n ),\n /** Статистика использования */\n usage: z.object({\n /** Общее количество токенов */\n total_tokens: z.number(),\n }),\n /** Модель, использованная для реранкинга */\n model: z.string().optional(),\n});\n\nexport type VoyageRerankResponse = z.infer<typeof VoyageRerankResponseSchema>;\n\n// ============================================================================\n// Turbopuffer Schemas\n// ============================================================================\n\n/**\n * Базовая схема атрибутов вектора\n */\nexport const VectorAttributesSchema = z.object({\n /** ID записи в Supabase */\n supabase_id: z.number(),\n /** Уникальный ID сообщения/документа */\n message_id: z.string(),\n /** Тип источника */\n source_type: z.enum(['email', 'pdf', 'website']),\n /** Тип чанка */\n chunk_type: z.string(),\n /** Email отправителя */\n sender: z.string().optional(),\n /** Email получателя */\n recipient: z.string().optional(),\n /** Дата источника */\n source_date: z.string().optional(),\n /** ID цепочки писем */\n thread_id: z.string().optional(),\n /** ID клиента */\n client_id: z.string().optional(),\n /** URL источника */\n source_url: z.string().optional(),\n /** Номер страницы */\n page_number: z.number().optional(),\n /** Заголовок секции */\n section_title: z.string().optional(),\n /** ID в content_sources */\n content_source_id: z.number().optional(),\n /** Тема письма */\n subject: z.string().optional(),\n /** Превью контента */\n content_preview: z.string().optional(),\n /** Заголовок документа */\n title: z.string().optional(),\n /** Полный контент */\n content: z.string().optional(),\n /** Категория */\n category: z.string().optional(),\n /** Тональность */\n sentiment: z.enum(['positive', 'negative', 'neutral']).optional(),\n /** Дата создания */\n created_at: z.string().optional(),\n});\n\nexport type VectorAttributes = z.infer<typeof VectorAttributesSchema>;\n\n/**\n * Схема результата поиска Turbopuffer\n */\nexport const TurbopufferSearchResultSchema = z.object({\n /** ID вектора */\n id: z.string(),\n /** Расстояние до запроса */\n dist: z.number(),\n /** Атрибуты вектора */\n attributes: VectorAttributesSchema.partial(),\n});\n\nexport type TurbopufferSearchResult = z.infer<typeof TurbopufferSearchResultSchema>;\n\n// ============================================================================\n// Anthropic Schemas\n// ============================================================================\n\n/**\n * Схема сообщения в ответе Claude\n */\nexport const ClaudeMessageSchema = z.object({\n /** ID сообщения */\n id: z.string(),\n /** Тип объекта */\n type: z.literal('message'),\n /** Роль */\n role: z.enum(['assistant', 'user']),\n /** Контент */\n content: z.array(\n z.object({\n type: z.enum(['text', 'tool_use']),\n text: z.string().optional(),\n })\n ),\n /** Модель */\n model: z.string(),\n /** Причина остановки */\n stop_reason: z.enum(['end_turn', 'max_tokens', 'stop_sequence', 'tool_use']).nullable(),\n /** Использование токенов */\n usage: z.object({\n input_tokens: z.number(),\n output_tokens: z.number(),\n }),\n});\n\nexport type ClaudeMessage = z.infer<typeof ClaudeMessageSchema>;\n\n// ============================================================================\n// Chat API Schemas\n// ============================================================================\n\n/**\n * Схема входящего запроса к Chat API\n */\nexport const ChatRequestSchema = z.object({\n /** Сообщение пользователя */\n message: z.string().min(1).max(10000),\n /** История сообщений */\n history: z\n .array(\n z.object({\n role: z.enum(['user', 'assistant']),\n content: z.string(),\n })\n )\n .optional()\n .default([]),\n /** ID сессии */\n sessionId: z.string().optional(),\n /** Режим (customer/internal) */\n mode: z.enum(['customer', 'internal']).optional().default('customer'),\n});\n\nexport type ChatRequest = z.infer<typeof ChatRequestSchema>;\n\n/**\n * Схема источника в ответе\n */\nexport const SourceSchema = z.object({\n /** Тип источника */\n type: z.enum(['email', 'pdf', 'website']),\n /** Заголовок */\n title: z.string(),\n /** URL или идентификатор */\n url: z.string().optional(),\n /** Превью контента */\n preview: z.string().optional(),\n /** Оценка релевантности */\n relevance: z.number().optional(),\n});\n\nexport type Source = z.infer<typeof SourceSchema>;\n\n// ============================================================================\n// Утилиты для валидации\n// ============================================================================\n\n/**\n * Безопасно распарсить данные по схеме\n *\n * @param schema - Zod схема\n * @param data - Данные для валидации\n * @returns Результат парсинга или null при ошибке\n *\n * @example\n * const response = await fetch(url);\n * const data = await response.json();\n * const parsed = safeParse(VoyageEmbeddingResponseSchema, data);\n * if (!parsed) throw new ValidationError('Invalid API response');\n */\nexport function safeParse<T>(\n schema: z.ZodType<T>,\n data: unknown\n): T | null {\n const result = schema.safeParse(data);\n return result.success ? result.data : null;\n}\n\n/**\n * Распарсить данные по схеме с выбросом ошибки\n *\n * @param schema - Zod схема\n * @param data - Данные для валидации\n * @param errorMessage - Сообщение об ошибке\n * @returns Валидные данные\n * @throws Error при невалидных данных\n */\nexport function parseOrThrow<T>(\n schema: z.ZodType<T>,\n data: unknown,\n errorMessage = 'Validation failed'\n): T {\n const result = schema.safeParse(data);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => `${i.path.join('.')}: ${i.message}`)\n .join('; ');\n throw new Error(`${errorMessage}: ${issues}`);\n }\n return result.data;\n}\n"]}
|