@juspay/neurolink 9.32.0 → 9.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/auth/anthropicOAuth.js +1 -1
- package/dist/cli/commands/proxy.js +18 -5
- package/dist/client/aiSdkAdapter.js +1 -1
- package/dist/client/index.js +137 -501
- package/dist/core/factory.js +0 -1
- package/dist/core/redisConversationMemoryManager.js +1 -1
- package/dist/features/ppt/slideGenerator.js +0 -1
- package/dist/features/ppt/utils.js +0 -1
- package/dist/lib/server/routes/claudeProxyRoutes.js +45 -9
- package/dist/mcp/elicitationProtocol.js +1 -1
- package/dist/mcp/servers/agent/directToolsServer.js +0 -1
- package/dist/providers/azureOpenai.js +1 -1
- package/dist/providers/huggingFace.js +0 -1
- package/dist/providers/openaiCompatible.js +0 -1
- package/dist/sdk/toolRegistration.js +0 -1
- package/dist/server/openapi/generator.js +1 -1
- package/dist/server/routes/claudeProxyRoutes.js +45 -9
- package/dist/types/configTypes.js +0 -5
- package/dist/types/modelTypes.js +0 -1
- package/dist/types/tools.js +0 -1
- package/dist/types/typeAliases.js +0 -1
- package/dist/types/utilities.js +1 -1
- package/dist/types/workflowTypes.js +0 -1
- package/dist/utils/providerRetry.js +0 -1
- package/dist/utils/providerUtils.js +0 -1
- package/package.json +2 -2
- package/dist/client/adapters/providerImageAdapter.js +0 -588
- package/dist/client/adapters/tts/googleTTSHandler.js +0 -344
- package/dist/client/adapters/video/directorPipeline.js +0 -516
- package/dist/client/adapters/video/ffmpegAdapter.js +0 -206
- package/dist/client/adapters/video/frameExtractor.js +0 -143
- package/dist/client/adapters/video/vertexVideoHandler.js +0 -763
- package/dist/client/adapters/video/videoAnalyzer.js +0 -238
- package/dist/client/adapters/video/videoMerger.js +0 -171
- package/dist/client/agent/directTools.js +0 -840
- package/dist/client/auth/AuthProviderFactory.js +0 -111
- package/dist/client/auth/AuthProviderRegistry.js +0 -190
- package/dist/client/auth/RequestContext.js +0 -78
- package/dist/client/auth/accountPool.js +0 -178
- package/dist/client/auth/anthropicOAuth.js +0 -974
- package/dist/client/auth/authContext.js +0 -314
- package/dist/client/auth/errors.js +0 -39
- package/dist/client/auth/index.js +0 -61
- package/dist/client/auth/middleware/AuthMiddleware.js +0 -519
- package/dist/client/auth/middleware/rateLimitByUser.js +0 -554
- package/dist/client/auth/providers/BaseAuthProvider.js +0 -723
- package/dist/client/auth/providers/CognitoProvider.js +0 -304
- package/dist/client/auth/providers/KeycloakProvider.js +0 -393
- package/dist/client/auth/providers/auth0.js +0 -274
- package/dist/client/auth/providers/betterAuth.js +0 -182
- package/dist/client/auth/providers/clerk.js +0 -317
- package/dist/client/auth/providers/custom.js +0 -112
- package/dist/client/auth/providers/firebase.js +0 -226
- package/dist/client/auth/providers/jwt.js +0 -212
- package/dist/client/auth/providers/oauth2.js +0 -303
- package/dist/client/auth/providers/supabase.js +0 -259
- package/dist/client/auth/providers/workos.js +0 -284
- package/dist/client/auth/serverBridge.js +0 -25
- package/dist/client/auth/sessionManager.js +0 -437
- package/dist/client/auth/tokenStore.js +0 -799
- package/dist/client/client/aiSdkAdapter.js +0 -487
- package/dist/client/client/auth.js +0 -473
- package/dist/client/client/errors.js +0 -552
- package/dist/client/client/httpClient.js +0 -837
- package/dist/client/client/index.js +0 -172
- package/dist/client/client/interceptors.js +0 -601
- package/dist/client/client/sseClient.js +0 -545
- package/dist/client/client/streamingClient.js +0 -917
- package/dist/client/client/wsClient.js +0 -369
- package/dist/client/config/configManager.js +0 -303
- package/dist/client/config/conversationMemory.js +0 -86
- package/dist/client/config/taskClassificationConfig.js +0 -148
- package/dist/client/constants/contextWindows.js +0 -295
- package/dist/client/constants/enums.js +0 -853
- package/dist/client/constants/index.js +0 -207
- package/dist/client/constants/performance.js +0 -389
- package/dist/client/constants/retry.js +0 -266
- package/dist/client/constants/timeouts.js +0 -182
- package/dist/client/constants/tokens.js +0 -380
- package/dist/client/constants/videoErrors.js +0 -46
- package/dist/client/context/budgetChecker.js +0 -98
- package/dist/client/context/contextCompactor.js +0 -205
- package/dist/client/context/emergencyTruncation.js +0 -88
- package/dist/client/context/errorDetection.js +0 -171
- package/dist/client/context/errors.js +0 -21
- package/dist/client/context/fileTokenBudget.js +0 -127
- package/dist/client/context/prompts/summarizationPrompt.js +0 -117
- package/dist/client/context/stages/fileReadDeduplicator.js +0 -66
- package/dist/client/context/stages/slidingWindowTruncator.js +0 -190
- package/dist/client/context/stages/structuredSummarizer.js +0 -99
- package/dist/client/context/stages/toolOutputPruner.js +0 -52
- package/dist/client/context/summarizationEngine.js +0 -136
- package/dist/client/context/toolOutputLimits.js +0 -78
- package/dist/client/context/toolPairRepair.js +0 -66
- package/dist/client/core/analytics.js +0 -88
- package/dist/client/core/baseProvider.js +0 -1385
- package/dist/client/core/constants.js +0 -140
- package/dist/client/core/conversationMemoryFactory.js +0 -141
- package/dist/client/core/conversationMemoryInitializer.js +0 -128
- package/dist/client/core/conversationMemoryManager.js +0 -344
- package/dist/client/core/dynamicModels.js +0 -358
- package/dist/client/core/evaluation.js +0 -309
- package/dist/client/core/evaluationProviders.js +0 -248
- package/dist/client/core/factory.js +0 -412
- package/dist/client/core/infrastructure/baseError.js +0 -22
- package/dist/client/core/infrastructure/baseFactory.js +0 -54
- package/dist/client/core/infrastructure/baseRegistry.js +0 -53
- package/dist/client/core/infrastructure/index.js +0 -5
- package/dist/client/core/infrastructure/retry.js +0 -20
- package/dist/client/core/infrastructure/typedEventEmitter.js +0 -23
- package/dist/client/core/modelConfiguration.js +0 -851
- package/dist/client/core/modules/GenerationHandler.js +0 -588
- package/dist/client/core/modules/MessageBuilder.js +0 -273
- package/dist/client/core/modules/StreamHandler.js +0 -185
- package/dist/client/core/modules/TelemetryHandler.js +0 -203
- package/dist/client/core/modules/ToolsManager.js +0 -499
- package/dist/client/core/modules/Utilities.js +0 -331
- package/dist/client/core/redisConversationMemoryManager.js +0 -1435
- package/dist/client/core/streamAnalytics.js +0 -131
- package/dist/client/evaluation/contextBuilder.js +0 -134
- package/dist/client/evaluation/index.js +0 -61
- package/dist/client/evaluation/prompts.js +0 -73
- package/dist/client/evaluation/ragasEvaluator.js +0 -110
- package/dist/client/evaluation/retryManager.js +0 -78
- package/dist/client/evaluation/scoring.js +0 -61
- package/dist/client/factories/providerFactory.js +0 -166
- package/dist/client/factories/providerRegistry.js +0 -166
- package/dist/client/features/ppt/constants.js +0 -896
- package/dist/client/features/ppt/contentPlanner.js +0 -529
- package/dist/client/features/ppt/presentationOrchestrator.js +0 -236
- package/dist/client/features/ppt/slideGenerator.js +0 -532
- package/dist/client/features/ppt/slideRenderers.js +0 -2383
- package/dist/client/features/ppt/slideTypeInference.js +0 -405
- package/dist/client/features/ppt/types.js +0 -13
- package/dist/client/features/ppt/utils.js +0 -443
- package/dist/client/files/fileReferenceRegistry.js +0 -1543
- package/dist/client/files/fileTools.js +0 -450
- package/dist/client/files/streamingReader.js +0 -321
- package/dist/client/files/types.js +0 -23
- package/dist/client/hitl/hitlErrors.js +0 -54
- package/dist/client/hitl/hitlManager.js +0 -460
- package/dist/client/mcp/agentExposure.js +0 -356
- package/dist/client/mcp/auth/index.js +0 -11
- package/dist/client/mcp/auth/oauthClientProvider.js +0 -325
- package/dist/client/mcp/auth/tokenStorage.js +0 -134
- package/dist/client/mcp/batching/index.js +0 -10
- package/dist/client/mcp/batching/requestBatcher.js +0 -441
- package/dist/client/mcp/caching/index.js +0 -10
- package/dist/client/mcp/caching/toolCache.js +0 -433
- package/dist/client/mcp/elicitation/elicitationManager.js +0 -376
- package/dist/client/mcp/elicitation/index.js +0 -11
- package/dist/client/mcp/elicitation/types.js +0 -10
- package/dist/client/mcp/elicitationProtocol.js +0 -375
- package/dist/client/mcp/enhancedToolDiscovery.js +0 -481
- package/dist/client/mcp/externalServerManager.js +0 -1478
- package/dist/client/mcp/factory.js +0 -161
- package/dist/client/mcp/flexibleToolValidator.js +0 -161
- package/dist/client/mcp/httpRateLimiter.js +0 -391
- package/dist/client/mcp/httpRetryHandler.js +0 -178
- package/dist/client/mcp/index.js +0 -74
- package/dist/client/mcp/mcpCircuitBreaker.js +0 -427
- package/dist/client/mcp/mcpClientFactory.js +0 -708
- package/dist/client/mcp/mcpRegistryClient.js +0 -488
- package/dist/client/mcp/mcpServerBase.js +0 -373
- package/dist/client/mcp/multiServerManager.js +0 -579
- package/dist/client/mcp/registry.js +0 -158
- package/dist/client/mcp/routing/index.js +0 -10
- package/dist/client/mcp/routing/toolRouter.js +0 -416
- package/dist/client/mcp/serverCapabilities.js +0 -502
- package/dist/client/mcp/servers/agent/directToolsServer.js +0 -150
- package/dist/client/mcp/toolAnnotations.js +0 -239
- package/dist/client/mcp/toolConverter.js +0 -258
- package/dist/client/mcp/toolDiscoveryService.js +0 -798
- package/dist/client/mcp/toolIntegration.js +0 -334
- package/dist/client/mcp/toolRegistry.js +0 -729
- package/dist/client/memory/hippocampusInitializer.js +0 -19
- package/dist/client/memory/memoryRetrievalTools.js +0 -166
- package/dist/client/middleware/builtin/analytics.js +0 -132
- package/dist/client/middleware/builtin/autoEvaluation.js +0 -203
- package/dist/client/middleware/builtin/guardrails.js +0 -109
- package/dist/client/middleware/builtin/lifecycle.js +0 -168
- package/dist/client/middleware/factory.js +0 -327
- package/dist/client/middleware/registry.js +0 -295
- package/dist/client/middleware/utils/guardrailsUtils.js +0 -396
- package/dist/client/models/anthropicModels.js +0 -527
- package/dist/client/neurolink.js +0 -8233
- package/dist/client/observability/exporterRegistry.js +0 -413
- package/dist/client/observability/exporters/arizeExporter.js +0 -138
- package/dist/client/observability/exporters/baseExporter.js +0 -190
- package/dist/client/observability/exporters/braintrustExporter.js +0 -154
- package/dist/client/observability/exporters/datadogExporter.js +0 -196
- package/dist/client/observability/exporters/laminarExporter.js +0 -302
- package/dist/client/observability/exporters/langfuseExporter.js +0 -209
- package/dist/client/observability/exporters/langsmithExporter.js +0 -143
- package/dist/client/observability/exporters/otelExporter.js +0 -164
- package/dist/client/observability/exporters/posthogExporter.js +0 -287
- package/dist/client/observability/exporters/sentryExporter.js +0 -165
- package/dist/client/observability/index.js +0 -31
- package/dist/client/observability/metricsAggregator.js +0 -556
- package/dist/client/observability/otelBridge.js +0 -131
- package/dist/client/observability/retryPolicy.js +0 -383
- package/dist/client/observability/sampling/samplers.js +0 -216
- package/dist/client/observability/spanProcessor.js +0 -303
- package/dist/client/observability/tokenTracker.js +0 -413
- package/dist/client/observability/types/exporterTypes.js +0 -5
- package/dist/client/observability/types/index.js +0 -4
- package/dist/client/observability/types/spanTypes.js +0 -92
- package/dist/client/observability/utils/safeMetadata.js +0 -25
- package/dist/client/observability/utils/spanSerializer.js +0 -292
- package/dist/client/processors/archive/ArchiveProcessor.js +0 -1308
- package/dist/client/processors/base/BaseFileProcessor.js +0 -614
- package/dist/client/processors/base/types.js +0 -82
- package/dist/client/processors/config/fileTypes.js +0 -520
- package/dist/client/processors/config/index.js +0 -92
- package/dist/client/processors/config/languageMap.js +0 -410
- package/dist/client/processors/config/mimeTypes.js +0 -363
- package/dist/client/processors/config/sizeLimits.js +0 -258
- package/dist/client/processors/document/ExcelProcessor.js +0 -590
- package/dist/client/processors/document/OpenDocumentProcessor.js +0 -212
- package/dist/client/processors/document/PptxProcessor.js +0 -157
- package/dist/client/processors/document/RtfProcessor.js +0 -361
- package/dist/client/processors/document/WordProcessor.js +0 -353
- package/dist/client/processors/errors/FileErrorCode.js +0 -255
- package/dist/client/processors/errors/errorHelpers.js +0 -386
- package/dist/client/processors/errors/errorSerializer.js +0 -507
- package/dist/client/processors/errors/index.js +0 -49
- package/dist/client/processors/markup/SvgProcessor.js +0 -240
- package/dist/client/processors/media/AudioProcessor.js +0 -707
- package/dist/client/processors/media/VideoProcessor.js +0 -1045
- package/dist/client/providers/amazonBedrock.js +0 -1512
- package/dist/client/providers/amazonSagemaker.js +0 -162
- package/dist/client/providers/anthropic.js +0 -831
- package/dist/client/providers/azureOpenai.js +0 -143
- package/dist/client/providers/googleAiStudio.js +0 -1200
- package/dist/client/providers/googleNativeGemini3.js +0 -543
- package/dist/client/providers/googleVertex.js +0 -2936
- package/dist/client/providers/huggingFace.js +0 -315
- package/dist/client/providers/litellm.js +0 -488
- package/dist/client/providers/mistral.js +0 -157
- package/dist/client/providers/ollama.js +0 -1579
- package/dist/client/providers/openAI.js +0 -627
- package/dist/client/providers/openRouter.js +0 -543
- package/dist/client/providers/openaiCompatible.js +0 -290
- package/dist/client/providers/providerTypeUtils.js +0 -46
- package/dist/client/providers/sagemaker/adaptive-semaphore.js +0 -215
- package/dist/client/providers/sagemaker/client.js +0 -472
- package/dist/client/providers/sagemaker/config.js +0 -317
- package/dist/client/providers/sagemaker/detection.js +0 -606
- package/dist/client/providers/sagemaker/error-constants.js +0 -227
- package/dist/client/providers/sagemaker/errors.js +0 -299
- package/dist/client/providers/sagemaker/language-model.js +0 -775
- package/dist/client/providers/sagemaker/parsers.js +0 -634
- package/dist/client/providers/sagemaker/streaming.js +0 -331
- package/dist/client/providers/sagemaker/structured-parser.js +0 -625
- package/dist/client/proxy/accountQuota.js +0 -162
- package/dist/client/proxy/claudeFormat.js +0 -595
- package/dist/client/proxy/modelRouter.js +0 -29
- package/dist/client/proxy/oauthFetch.js +0 -367
- package/dist/client/proxy/proxyFetch.js +0 -586
- package/dist/client/proxy/requestLogger.js +0 -207
- package/dist/client/proxy/tokenRefresh.js +0 -124
- package/dist/client/proxy/usageStats.js +0 -74
- package/dist/client/proxy/utils/noProxyUtils.js +0 -149
- package/dist/client/rag/ChunkerFactory.js +0 -320
- package/dist/client/rag/ChunkerRegistry.js +0 -421
- package/dist/client/rag/chunkers/BaseChunker.js +0 -143
- package/dist/client/rag/chunkers/CharacterChunker.js +0 -28
- package/dist/client/rag/chunkers/HTMLChunker.js +0 -38
- package/dist/client/rag/chunkers/JSONChunker.js +0 -68
- package/dist/client/rag/chunkers/LaTeXChunker.js +0 -63
- package/dist/client/rag/chunkers/MarkdownChunker.js +0 -306
- package/dist/client/rag/chunkers/RecursiveChunker.js +0 -139
- package/dist/client/rag/chunkers/SemanticMarkdownChunker.js +0 -138
- package/dist/client/rag/chunkers/SentenceChunker.js +0 -66
- package/dist/client/rag/chunkers/TokenChunker.js +0 -61
- package/dist/client/rag/chunkers/index.js +0 -15
- package/dist/client/rag/chunking/characterChunker.js +0 -142
- package/dist/client/rag/chunking/chunkerRegistry.js +0 -194
- package/dist/client/rag/chunking/htmlChunker.js +0 -247
- package/dist/client/rag/chunking/index.js +0 -17
- package/dist/client/rag/chunking/jsonChunker.js +0 -281
- package/dist/client/rag/chunking/latexChunker.js +0 -251
- package/dist/client/rag/chunking/markdownChunker.js +0 -373
- package/dist/client/rag/chunking/recursiveChunker.js +0 -148
- package/dist/client/rag/chunking/semanticChunker.js +0 -306
- package/dist/client/rag/chunking/sentenceChunker.js +0 -230
- package/dist/client/rag/chunking/tokenChunker.js +0 -183
- package/dist/client/rag/document/MDocument.js +0 -392
- package/dist/client/rag/document/index.js +0 -5
- package/dist/client/rag/document/loaders.js +0 -500
- package/dist/client/rag/errors/RAGError.js +0 -274
- package/dist/client/rag/errors/index.js +0 -6
- package/dist/client/rag/graphRag/graphRAG.js +0 -401
- package/dist/client/rag/graphRag/index.js +0 -4
- package/dist/client/rag/index.js +0 -141
- package/dist/client/rag/metadata/MetadataExtractorFactory.js +0 -418
- package/dist/client/rag/metadata/MetadataExtractorRegistry.js +0 -362
- package/dist/client/rag/metadata/index.js +0 -9
- package/dist/client/rag/metadata/metadataExtractor.js +0 -280
- package/dist/client/rag/pipeline/RAGPipeline.js +0 -436
- package/dist/client/rag/pipeline/contextAssembly.js +0 -341
- package/dist/client/rag/pipeline/index.js +0 -5
- package/dist/client/rag/ragIntegration.js +0 -321
- package/dist/client/rag/reranker/RerankerFactory.js +0 -430
- package/dist/client/rag/reranker/RerankerRegistry.js +0 -402
- package/dist/client/rag/reranker/index.js +0 -9
- package/dist/client/rag/reranker/reranker.js +0 -277
- package/dist/client/rag/resilience/CircuitBreaker.js +0 -431
- package/dist/client/rag/resilience/RetryHandler.js +0 -304
- package/dist/client/rag/resilience/index.js +0 -7
- package/dist/client/rag/retrieval/hybridSearch.js +0 -335
- package/dist/client/rag/retrieval/index.js +0 -5
- package/dist/client/rag/retrieval/vectorQueryTool.js +0 -307
- package/dist/client/rag/types.js +0 -8
- package/dist/client/sdk/toolRegistration.js +0 -377
- package/dist/client/server/abstract/baseServerAdapter.js +0 -575
- package/dist/client/server/adapters/expressAdapter.js +0 -486
- package/dist/client/server/adapters/fastifyAdapter.js +0 -472
- package/dist/client/server/adapters/honoAdapter.js +0 -632
- package/dist/client/server/adapters/koaAdapter.js +0 -510
- package/dist/client/server/errors.js +0 -486
- package/dist/client/server/factory/serverAdapterFactory.js +0 -160
- package/dist/client/server/index.js +0 -108
- package/dist/client/server/middleware/abortSignal.js +0 -111
- package/dist/client/server/middleware/auth.js +0 -388
- package/dist/client/server/middleware/cache.js +0 -359
- package/dist/client/server/middleware/common.js +0 -281
- package/dist/client/server/middleware/deprecation.js +0 -190
- package/dist/client/server/middleware/mcpBodyAttachment.js +0 -63
- package/dist/client/server/middleware/rateLimit.js +0 -227
- package/dist/client/server/middleware/validation.js +0 -388
- package/dist/client/server/openapi/generator.js +0 -398
- package/dist/client/server/openapi/index.js +0 -36
- package/dist/client/server/openapi/schemas.js +0 -695
- package/dist/client/server/openapi/templates.js +0 -374
- package/dist/client/server/routes/agentRoutes.js +0 -189
- package/dist/client/server/routes/claudeProxyRoutes.js +0 -1600
- package/dist/client/server/routes/healthRoutes.js +0 -187
- package/dist/client/server/routes/index.js +0 -57
- package/dist/client/server/routes/mcpRoutes.js +0 -342
- package/dist/client/server/routes/memoryRoutes.js +0 -350
- package/dist/client/server/routes/openApiRoutes.js +0 -126
- package/dist/client/server/routes/toolRoutes.js +0 -199
- package/dist/client/server/streaming/dataStream.js +0 -486
- package/dist/client/server/streaming/index.js +0 -11
- package/dist/client/server/types.js +0 -67
- package/dist/client/server/utils/redaction.js +0 -334
- package/dist/client/server/utils/validation.js +0 -243
- package/dist/client/server/websocket/WebSocketHandler.js +0 -383
- package/dist/client/server/websocket/index.js +0 -4
- package/dist/client/services/server/ai/observability/instrumentation.js +0 -808
- package/dist/client/telemetry/attributes.js +0 -100
- package/dist/client/telemetry/index.js +0 -26
- package/dist/client/telemetry/telemetryService.js +0 -308
- package/dist/client/telemetry/tracers.js +0 -17
- package/dist/client/telemetry/withSpan.js +0 -34
- package/dist/client/types/actionTypes.js +0 -6
- package/dist/client/types/analytics.js +0 -5
- package/dist/client/types/authTypes.js +0 -9
- package/dist/client/types/circuitBreakerErrors.js +0 -34
- package/dist/client/types/cli.js +0 -21
- package/dist/client/types/clientTypes.js +0 -10
- package/dist/client/types/common.js +0 -51
- package/dist/client/types/configTypes.js +0 -49
- package/dist/client/types/content.js +0 -19
- package/dist/client/types/contextTypes.js +0 -400
- package/dist/client/types/conversation.js +0 -47
- package/dist/client/types/conversationMemoryInterface.js +0 -6
- package/dist/client/types/domainTypes.js +0 -5
- package/dist/client/types/errors.js +0 -167
- package/dist/client/types/evaluation.js +0 -5
- package/dist/client/types/evaluationProviders.js +0 -5
- package/dist/client/types/evaluationTypes.js +0 -1
- package/dist/client/types/externalMcp.js +0 -6
- package/dist/client/types/fileReferenceTypes.js +0 -8
- package/dist/client/types/fileTypes.js +0 -4
- package/dist/client/types/generateTypes.js +0 -1
- package/dist/client/types/guardrails.js +0 -1
- package/dist/client/types/hitlTypes.js +0 -8
- package/dist/client/types/index.js +0 -57
- package/dist/client/types/mcpTypes.js +0 -5
- package/dist/client/types/middlewareTypes.js +0 -1
- package/dist/client/types/modelTypes.js +0 -30
- package/dist/client/types/multimodal.js +0 -135
- package/dist/client/types/observability.js +0 -6
- package/dist/client/types/pptTypes.js +0 -82
- package/dist/client/types/providers.js +0 -111
- package/dist/client/types/proxyTypes.js +0 -16
- package/dist/client/types/ragTypes.js +0 -7
- package/dist/client/types/sdkTypes.js +0 -8
- package/dist/client/types/serviceTypes.js +0 -5
- package/dist/client/types/streamTypes.js +0 -1
- package/dist/client/types/subscriptionTypes.js +0 -9
- package/dist/client/types/taskClassificationTypes.js +0 -5
- package/dist/client/types/tools.js +0 -24
- package/dist/client/types/ttsTypes.js +0 -57
- package/dist/client/types/typeAliases.js +0 -48
- package/dist/client/types/utilities.js +0 -4
- package/dist/client/types/workflowTypes.js +0 -30
- package/dist/client/utils/async/withTimeout.js +0 -98
- package/dist/client/utils/asyncMutex.js +0 -60
- package/dist/client/utils/conversationMemory.js +0 -431
- package/dist/client/utils/csvProcessor.js +0 -846
- package/dist/client/utils/errorHandling.js +0 -936
- package/dist/client/utils/evaluationUtils.js +0 -131
- package/dist/client/utils/factoryProcessing.js +0 -589
- package/dist/client/utils/fileDetector.js +0 -2161
- package/dist/client/utils/imageCache.js +0 -376
- package/dist/client/utils/imageProcessor.js +0 -704
- package/dist/client/utils/logger.js +0 -491
- package/dist/client/utils/mcpDefaults.js +0 -134
- package/dist/client/utils/messageBuilder.js +0 -1653
- package/dist/client/utils/modelAliasResolver.js +0 -54
- package/dist/client/utils/modelDetection.js +0 -80
- package/dist/client/utils/modelRouter.js +0 -292
- package/dist/client/utils/multimodalOptionsBuilder.js +0 -65
- package/dist/client/utils/observabilityHelpers.js +0 -47
- package/dist/client/utils/parameterValidation.js +0 -966
- package/dist/client/utils/pdfProcessor.js +0 -410
- package/dist/client/utils/performance.js +0 -222
- package/dist/client/utils/pricing.js +0 -340
- package/dist/client/utils/promptRedaction.js +0 -62
- package/dist/client/utils/providerConfig.js +0 -1009
- package/dist/client/utils/providerHealth.js +0 -1237
- package/dist/client/utils/providerRetry.js +0 -112
- package/dist/client/utils/providerUtils.js +0 -434
- package/dist/client/utils/rateLimiter.js +0 -200
- package/dist/client/utils/redis.js +0 -368
- package/dist/client/utils/retryHandler.js +0 -269
- package/dist/client/utils/retryability.js +0 -22
- package/dist/client/utils/sanitizers/svg.js +0 -481
- package/dist/client/utils/schemaConversion.js +0 -255
- package/dist/client/utils/taskClassificationUtils.js +0 -149
- package/dist/client/utils/taskClassifier.js +0 -94
- package/dist/client/utils/thinkingConfig.js +0 -104
- package/dist/client/utils/timeout.js +0 -359
- package/dist/client/utils/tokenEstimation.js +0 -142
- package/dist/client/utils/tokenLimits.js +0 -125
- package/dist/client/utils/tokenUtils.js +0 -239
- package/dist/client/utils/toolUtils.js +0 -75
- package/dist/client/utils/transformationUtils.js +0 -554
- package/dist/client/utils/ttsProcessor.js +0 -286
- package/dist/client/utils/typeUtils.js +0 -97
- package/dist/client/utils/videoAnalysisProcessor.js +0 -67
- package/dist/client/workflow/config.js +0 -398
- package/dist/client/workflow/core/ensembleExecutor.js +0 -407
- package/dist/client/workflow/core/judgeScorer.js +0 -544
- package/dist/client/workflow/core/responseConditioner.js +0 -225
- package/dist/client/workflow/core/types/conditionerTypes.js +0 -7
- package/dist/client/workflow/core/types/ensembleTypes.js +0 -7
- package/dist/client/workflow/core/types/index.js +0 -7
- package/dist/client/workflow/core/types/judgeTypes.js +0 -7
- package/dist/client/workflow/core/types/layerTypes.js +0 -7
- package/dist/client/workflow/core/types/registryTypes.js +0 -7
- package/dist/client/workflow/core/workflowRegistry.js +0 -304
- package/dist/client/workflow/core/workflowRunner.js +0 -586
- package/dist/client/workflow/index.js +0 -50
- package/dist/client/workflow/types.js +0 -9
- package/dist/client/workflow/utils/types/index.js +0 -7
- package/dist/client/workflow/utils/workflowMetrics.js +0 -311
- package/dist/client/workflow/utils/workflowValidation.js +0 -420
- package/dist/client/workflow/workflows/adaptiveWorkflow.js +0 -366
- package/dist/client/workflow/workflows/consensusWorkflow.js +0 -192
- package/dist/client/workflow/workflows/fallbackWorkflow.js +0 -225
- package/dist/client/workflow/workflows/multiJudgeWorkflow.js +0 -351
- /package/dist/client/{client/reactHooks.js → reactHooks.js} +0 -0
|
@@ -1,704 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Image processing utilities for multimodal support
|
|
3
|
-
* Handles format conversion for different AI providers
|
|
4
|
-
*/
|
|
5
|
-
import { logger } from "./logger.js";
|
|
6
|
-
import { urlDownloadRateLimiter } from "./rateLimiter.js";
|
|
7
|
-
import { withRetry } from "./retryHandler.js";
|
|
8
|
-
import { SYSTEM_LIMITS } from "../core/constants.js";
|
|
9
|
-
import { getImageCache } from "./imageCache.js";
|
|
10
|
-
/**
|
|
11
|
-
* Network error codes that should trigger a retry
|
|
12
|
-
*/
|
|
13
|
-
const RETRYABLE_ERROR_CODES = new Set([
|
|
14
|
-
"ECONNRESET",
|
|
15
|
-
"ENOTFOUND",
|
|
16
|
-
"ECONNREFUSED",
|
|
17
|
-
"ETIMEDOUT",
|
|
18
|
-
"ERR_NETWORK",
|
|
19
|
-
]);
|
|
20
|
-
/**
|
|
21
|
-
* Determines if an HTTP error is retryable based on status code
|
|
22
|
-
* Only network errors and certain HTTP status codes should be retried
|
|
23
|
-
* 4xx client errors like 404 (Not Found) and 403 (Forbidden) should NOT be retried
|
|
24
|
-
*
|
|
25
|
-
* @param error - The error to check
|
|
26
|
-
* @returns true if the error is retryable, false otherwise
|
|
27
|
-
*/
|
|
28
|
-
function isRetryableDownloadError(error) {
|
|
29
|
-
// Network-related errors should be retried
|
|
30
|
-
if (error && typeof error === "object") {
|
|
31
|
-
const errorCode = error.code;
|
|
32
|
-
const errorName = error.name;
|
|
33
|
-
if (RETRYABLE_ERROR_CODES.has(errorCode || "") ||
|
|
34
|
-
errorName === "AbortError") {
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
// Check for HTTP status code in error message for retryable errors
|
|
39
|
-
// Only retry on 5xx server errors, 429 (Too Many Requests), and 408 (Request Timeout)
|
|
40
|
-
// Do NOT retry on 4xx client errors like 404 (Not Found) or 403 (Forbidden)
|
|
41
|
-
if (error instanceof Error) {
|
|
42
|
-
const message = error.message;
|
|
43
|
-
// Extract HTTP status from error message like "HTTP 503: Service Unavailable"
|
|
44
|
-
const statusMatch = message.match(/HTTP (\d{3}):/);
|
|
45
|
-
if (statusMatch) {
|
|
46
|
-
const status = parseInt(statusMatch[1], 10);
|
|
47
|
-
// Retry on 5xx server errors, 429 (rate limit), 408 (timeout)
|
|
48
|
-
return status >= 500 || status === 429 || status === 408;
|
|
49
|
-
}
|
|
50
|
-
// Check for timeout/network-related error messages
|
|
51
|
-
// Use more precise matching to avoid false positives like "No timeout specified"
|
|
52
|
-
if (/\b(request timed out|operation timed out|connection timed out|timed out)\b/i.test(message) ||
|
|
53
|
-
/\bnetwork (error|failure|unreachable|down)\b/i.test(message)) {
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Image processor class for handling provider-specific image formatting
|
|
61
|
-
*/
|
|
62
|
-
export class ImageProcessor {
|
|
63
|
-
/**
|
|
64
|
-
* Process image Buffer (unified interface)
|
|
65
|
-
* Matches CSVProcessor.process() signature for consistency
|
|
66
|
-
*
|
|
67
|
-
* @param content - Image file as Buffer
|
|
68
|
-
* @param options - Processing options (unused for now)
|
|
69
|
-
* @returns Processed image as data URI
|
|
70
|
-
*/
|
|
71
|
-
static async process(content, _options) {
|
|
72
|
-
// Validate content is non-empty before processing
|
|
73
|
-
if (content.length === 0) {
|
|
74
|
-
logger.error("Empty buffer provided");
|
|
75
|
-
throw new Error("Invalid image processing: buffer is empty");
|
|
76
|
-
}
|
|
77
|
-
const mediaType = this.detectImageType(content);
|
|
78
|
-
const base64 = content.toString("base64");
|
|
79
|
-
const dataUri = `data:${mediaType};base64,${base64}`;
|
|
80
|
-
// Validate output before returning
|
|
81
|
-
this.validateProcessOutput(dataUri, base64, mediaType);
|
|
82
|
-
return {
|
|
83
|
-
type: "image",
|
|
84
|
-
content: dataUri,
|
|
85
|
-
mimeType: mediaType,
|
|
86
|
-
metadata: {
|
|
87
|
-
confidence: 100,
|
|
88
|
-
size: content.length,
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Validate processed output meets required format
|
|
94
|
-
* Checks:
|
|
95
|
-
* - Base64 content is non-empty
|
|
96
|
-
* - Data URI format is valid (data:{mimeType};base64,{content})
|
|
97
|
-
* - MIME type is in the allowed list
|
|
98
|
-
* @param dataUri - The complete data URI string
|
|
99
|
-
* @param base64 - The base64-encoded content
|
|
100
|
-
* @param mediaType - The MIME type of the image
|
|
101
|
-
* @throws Error if any validation fails
|
|
102
|
-
*/
|
|
103
|
-
static validateProcessOutput(dataUri, base64, mediaType) {
|
|
104
|
-
// Validate base64 is non-empty (check first for better error message)
|
|
105
|
-
if (base64.length === 0) {
|
|
106
|
-
logger.error("Empty base64 content generated");
|
|
107
|
-
throw new Error("Invalid image processing: base64 content is empty");
|
|
108
|
-
}
|
|
109
|
-
// Validate data URI format with proper base64 character validation
|
|
110
|
-
// Base64 can only have 0, 1, or 2 padding characters at the end
|
|
111
|
-
const dataUriRegex = /^data:[^;]+;base64,[A-Za-z0-9+/]*={0,2}$/;
|
|
112
|
-
if (!dataUriRegex.test(dataUri)) {
|
|
113
|
-
logger.error("Invalid data URI format generated", { dataUri });
|
|
114
|
-
throw new Error("Invalid data URI format: must be data:{mimeType};base64,{content}");
|
|
115
|
-
}
|
|
116
|
-
// Defensive check: ensure detectImageType() returns valid MIME type
|
|
117
|
-
// This validation protects against future changes to detectImageType()
|
|
118
|
-
if (!this.validateImageFormat(mediaType)) {
|
|
119
|
-
logger.error("Invalid MIME type generated", { mediaType });
|
|
120
|
-
throw new Error(`Invalid MIME type: ${mediaType} is not in allowed list`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Process image for OpenAI (requires data URI format)
|
|
125
|
-
*/
|
|
126
|
-
static processImageForOpenAI(image) {
|
|
127
|
-
try {
|
|
128
|
-
if (typeof image === "string") {
|
|
129
|
-
// Handle URLs
|
|
130
|
-
if (image.startsWith("http")) {
|
|
131
|
-
return image;
|
|
132
|
-
}
|
|
133
|
-
// Handle data URIs
|
|
134
|
-
if (image.startsWith("data:")) {
|
|
135
|
-
return image;
|
|
136
|
-
}
|
|
137
|
-
// Handle base64 - convert to data URI
|
|
138
|
-
return `data:image/jpeg;base64,${image}`;
|
|
139
|
-
}
|
|
140
|
-
// Handle Buffer - convert to data URI
|
|
141
|
-
const base64 = image.toString("base64");
|
|
142
|
-
return `data:image/jpeg;base64,${base64}`;
|
|
143
|
-
}
|
|
144
|
-
catch (error) {
|
|
145
|
-
logger.error("Failed to process image for OpenAI:", error);
|
|
146
|
-
throw new Error(`Image processing failed for OpenAI: ${error instanceof Error ? error.message : "Unknown error"}`, { cause: error });
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Process image for Google AI (requires base64 without data URI prefix)
|
|
151
|
-
*/
|
|
152
|
-
static processImageForGoogle(image) {
|
|
153
|
-
try {
|
|
154
|
-
let base64Data;
|
|
155
|
-
let mimeType = "image/jpeg"; // Default
|
|
156
|
-
if (typeof image === "string") {
|
|
157
|
-
if (image.startsWith("data:")) {
|
|
158
|
-
// Extract mime type and base64 from data URI
|
|
159
|
-
const match = image.match(/^data:([^;]+);base64,(.+)$/);
|
|
160
|
-
if (match) {
|
|
161
|
-
mimeType = match[1];
|
|
162
|
-
base64Data = match[2];
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
base64Data = image.split(",")[1] || image;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
base64Data = image;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
base64Data = image.toString("base64");
|
|
174
|
-
}
|
|
175
|
-
return {
|
|
176
|
-
mimeType,
|
|
177
|
-
data: base64Data, // Google wants base64 WITHOUT data URI prefix
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
catch (error) {
|
|
181
|
-
logger.error("Failed to process image for Google AI:", error);
|
|
182
|
-
throw new Error(`Image processing failed for Google AI: ${error instanceof Error ? error.message : "Unknown error"}`, { cause: error });
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Process image for Anthropic (requires base64 without data URI prefix)
|
|
187
|
-
*/
|
|
188
|
-
static processImageForAnthropic(image) {
|
|
189
|
-
try {
|
|
190
|
-
let base64Data;
|
|
191
|
-
let mediaType = "image/jpeg"; // Default
|
|
192
|
-
if (typeof image === "string") {
|
|
193
|
-
if (image.startsWith("data:")) {
|
|
194
|
-
// Extract mime type and base64 from data URI
|
|
195
|
-
const match = image.match(/^data:([^;]+);base64,(.+)$/);
|
|
196
|
-
if (match) {
|
|
197
|
-
mediaType = match[1];
|
|
198
|
-
base64Data = match[2];
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
base64Data = image.split(",")[1] || image;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
base64Data = image;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
base64Data = image.toString("base64");
|
|
210
|
-
}
|
|
211
|
-
return {
|
|
212
|
-
mediaType,
|
|
213
|
-
data: base64Data, // Anthropic wants base64 WITHOUT data URI prefix
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
catch (error) {
|
|
217
|
-
logger.error("Failed to process image for Anthropic:", error);
|
|
218
|
-
throw new Error(`Image processing failed for Anthropic: ${error instanceof Error ? error.message : "Unknown error"}`, { cause: error });
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* Process image for Vertex AI (model-specific routing)
|
|
223
|
-
*/
|
|
224
|
-
static processImageForVertex(image, model) {
|
|
225
|
-
try {
|
|
226
|
-
// Route based on model type
|
|
227
|
-
if (model.includes("gemini")) {
|
|
228
|
-
// Use Google AI format for Gemini models
|
|
229
|
-
return ImageProcessor.processImageForGoogle(image);
|
|
230
|
-
}
|
|
231
|
-
else if (model.includes("claude")) {
|
|
232
|
-
// Use Anthropic format for Claude models
|
|
233
|
-
return ImageProcessor.processImageForAnthropic(image);
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
// Default to Google format
|
|
237
|
-
return ImageProcessor.processImageForGoogle(image);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
catch (error) {
|
|
241
|
-
logger.error("Failed to process image for Vertex AI:", error);
|
|
242
|
-
throw new Error(`Image processing failed for Vertex AI: ${error instanceof Error ? error.message : "Unknown error"}`, { cause: error });
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Detect image type from filename or data
|
|
247
|
-
*/
|
|
248
|
-
static detectImageType(input) {
|
|
249
|
-
try {
|
|
250
|
-
if (typeof input === "string") {
|
|
251
|
-
// Check if it's a data URI
|
|
252
|
-
if (input.startsWith("data:")) {
|
|
253
|
-
const match = input.match(/^data:([^;]+);/);
|
|
254
|
-
return match ? match[1] : "image/jpeg";
|
|
255
|
-
}
|
|
256
|
-
// Check if it's a filename
|
|
257
|
-
const extension = input.toLowerCase().split(".").pop();
|
|
258
|
-
const imageTypes = {
|
|
259
|
-
jpg: "image/jpeg",
|
|
260
|
-
jpeg: "image/jpeg",
|
|
261
|
-
png: "image/png",
|
|
262
|
-
gif: "image/gif",
|
|
263
|
-
webp: "image/webp",
|
|
264
|
-
bmp: "image/bmp",
|
|
265
|
-
tiff: "image/tiff",
|
|
266
|
-
tif: "image/tiff",
|
|
267
|
-
svg: "image/svg+xml",
|
|
268
|
-
avif: "image/avif",
|
|
269
|
-
};
|
|
270
|
-
return imageTypes[extension || ""] || "image/jpeg";
|
|
271
|
-
}
|
|
272
|
-
// For Buffer, try to detect from magic bytes
|
|
273
|
-
if (input.length >= 4) {
|
|
274
|
-
const header = input.subarray(0, 4);
|
|
275
|
-
// PNG: 89 50 4E 47
|
|
276
|
-
if (header[0] === 0x89 &&
|
|
277
|
-
header[1] === 0x50 &&
|
|
278
|
-
header[2] === 0x4e &&
|
|
279
|
-
header[3] === 0x47) {
|
|
280
|
-
return "image/png";
|
|
281
|
-
}
|
|
282
|
-
// JPEG: FF D8 FF
|
|
283
|
-
if (header[0] === 0xff && header[1] === 0xd8 && header[2] === 0xff) {
|
|
284
|
-
return "image/jpeg";
|
|
285
|
-
}
|
|
286
|
-
// GIF: 47 49 46 38
|
|
287
|
-
if (header[0] === 0x47 &&
|
|
288
|
-
header[1] === 0x49 &&
|
|
289
|
-
header[2] === 0x46 &&
|
|
290
|
-
header[3] === 0x38) {
|
|
291
|
-
return "image/gif";
|
|
292
|
-
}
|
|
293
|
-
// WebP: check for RIFF and WEBP
|
|
294
|
-
if (input.length >= 12) {
|
|
295
|
-
const riff = input.subarray(0, 4);
|
|
296
|
-
const webp = input.subarray(8, 12);
|
|
297
|
-
if (riff.toString() === "RIFF" && webp.toString() === "WEBP") {
|
|
298
|
-
return "image/webp";
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
// SVG: check for "<svg" or "<?xml" at start (text-based)
|
|
302
|
-
if (input.length >= 4) {
|
|
303
|
-
const start = input.subarray(0, 4).toString();
|
|
304
|
-
if (start === "<svg" || start === "<?xm") {
|
|
305
|
-
return "image/svg+xml";
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
// AVIF: check for "ftypavif" signature at bytes 4-11
|
|
309
|
-
if (input.length >= 12) {
|
|
310
|
-
const ftyp = input.subarray(4, 8).toString();
|
|
311
|
-
const brand = input.subarray(8, 12).toString();
|
|
312
|
-
if (ftyp === "ftyp" && brand === "avif") {
|
|
313
|
-
return "image/avif";
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
return "image/jpeg"; // Default fallback
|
|
318
|
-
}
|
|
319
|
-
catch (error) {
|
|
320
|
-
logger.warn("Failed to detect image type, using default:", error);
|
|
321
|
-
return "image/jpeg";
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Validate image size (default 10MB limit)
|
|
326
|
-
*/
|
|
327
|
-
static validateImageSize(data, maxSize = 10 * 1024 * 1024) {
|
|
328
|
-
try {
|
|
329
|
-
const size = typeof data === "string"
|
|
330
|
-
? Buffer.byteLength(data, "base64")
|
|
331
|
-
: data.length;
|
|
332
|
-
return size <= maxSize;
|
|
333
|
-
}
|
|
334
|
-
catch (error) {
|
|
335
|
-
logger.warn("Failed to validate image size:", error);
|
|
336
|
-
return false;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* Validate image format
|
|
341
|
-
*/
|
|
342
|
-
static validateImageFormat(mediaType) {
|
|
343
|
-
const supportedFormats = [
|
|
344
|
-
"image/jpeg",
|
|
345
|
-
"image/png",
|
|
346
|
-
"image/gif",
|
|
347
|
-
"image/webp",
|
|
348
|
-
"image/bmp",
|
|
349
|
-
"image/tiff",
|
|
350
|
-
"image/svg+xml",
|
|
351
|
-
"image/avif",
|
|
352
|
-
];
|
|
353
|
-
return supportedFormats.includes(mediaType.toLowerCase());
|
|
354
|
-
}
|
|
355
|
-
/**
|
|
356
|
-
* Get image dimensions from Buffer (basic implementation)
|
|
357
|
-
*/
|
|
358
|
-
static getImageDimensions(buffer) {
|
|
359
|
-
try {
|
|
360
|
-
// Basic PNG dimension extraction
|
|
361
|
-
if (buffer.length >= 24 &&
|
|
362
|
-
buffer.subarray(0, 8).toString("hex") === "89504e470d0a1a0a") {
|
|
363
|
-
const width = buffer.readUInt32BE(16);
|
|
364
|
-
const height = buffer.readUInt32BE(20);
|
|
365
|
-
return { width, height };
|
|
366
|
-
}
|
|
367
|
-
// Basic JPEG dimension extraction (simplified)
|
|
368
|
-
if (buffer.length >= 4 && buffer[0] === 0xff && buffer[1] === 0xd8) {
|
|
369
|
-
// This is a very basic implementation
|
|
370
|
-
// For production, consider using a proper image library
|
|
371
|
-
return null;
|
|
372
|
-
}
|
|
373
|
-
return null;
|
|
374
|
-
}
|
|
375
|
-
catch (error) {
|
|
376
|
-
logger.warn("Failed to extract image dimensions:", error);
|
|
377
|
-
return null;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* Convert image to ProcessedImage format
|
|
382
|
-
*/
|
|
383
|
-
static processImage(image, provider, model) {
|
|
384
|
-
try {
|
|
385
|
-
const mediaType = ImageProcessor.detectImageType(image);
|
|
386
|
-
const size = typeof image === "string"
|
|
387
|
-
? Buffer.byteLength(image, "base64")
|
|
388
|
-
: image.length;
|
|
389
|
-
let data;
|
|
390
|
-
let format;
|
|
391
|
-
switch (provider.toLowerCase()) {
|
|
392
|
-
case "openai":
|
|
393
|
-
data = ImageProcessor.processImageForOpenAI(image);
|
|
394
|
-
format = "data_uri";
|
|
395
|
-
break;
|
|
396
|
-
case "google-ai":
|
|
397
|
-
case "google": {
|
|
398
|
-
const googleResult = ImageProcessor.processImageForGoogle(image);
|
|
399
|
-
data = googleResult.data;
|
|
400
|
-
format = "base64";
|
|
401
|
-
break;
|
|
402
|
-
}
|
|
403
|
-
case "anthropic": {
|
|
404
|
-
const anthropicResult = ImageProcessor.processImageForAnthropic(image);
|
|
405
|
-
data = anthropicResult.data;
|
|
406
|
-
format = "base64";
|
|
407
|
-
break;
|
|
408
|
-
}
|
|
409
|
-
case "vertex": {
|
|
410
|
-
const vertexResult = ImageProcessor.processImageForVertex(image, model || "");
|
|
411
|
-
data = vertexResult.data;
|
|
412
|
-
format = "base64";
|
|
413
|
-
break;
|
|
414
|
-
}
|
|
415
|
-
default:
|
|
416
|
-
// Default to base64
|
|
417
|
-
if (typeof image === "string") {
|
|
418
|
-
data = image.startsWith("data:")
|
|
419
|
-
? image.split(",")[1] || image
|
|
420
|
-
: image;
|
|
421
|
-
}
|
|
422
|
-
else {
|
|
423
|
-
data = image.toString("base64");
|
|
424
|
-
}
|
|
425
|
-
format = "base64";
|
|
426
|
-
}
|
|
427
|
-
return {
|
|
428
|
-
data,
|
|
429
|
-
mediaType,
|
|
430
|
-
size,
|
|
431
|
-
format,
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
catch (error) {
|
|
435
|
-
logger.error(`Failed to process image for ${provider}:`, error);
|
|
436
|
-
throw new Error(`Image processing failed: ${error instanceof Error ? error.message : "Unknown error"}`, { cause: error });
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
/**
|
|
441
|
-
* Utility functions for image handling
|
|
442
|
-
*/
|
|
443
|
-
export const imageUtils = {
|
|
444
|
-
/**
|
|
445
|
-
* Check if a string is a valid data URI
|
|
446
|
-
*/
|
|
447
|
-
isDataUri: (str) => {
|
|
448
|
-
return (typeof str === "string" &&
|
|
449
|
-
str.startsWith("data:") &&
|
|
450
|
-
str.includes("base64,"));
|
|
451
|
-
},
|
|
452
|
-
/**
|
|
453
|
-
* Check if a string is a valid URL
|
|
454
|
-
*/
|
|
455
|
-
isUrl: (str) => {
|
|
456
|
-
try {
|
|
457
|
-
new URL(str);
|
|
458
|
-
return str.startsWith("http://") || str.startsWith("https://");
|
|
459
|
-
}
|
|
460
|
-
catch {
|
|
461
|
-
return false;
|
|
462
|
-
}
|
|
463
|
-
},
|
|
464
|
-
/**
|
|
465
|
-
* Check if a string is base64 encoded
|
|
466
|
-
*/
|
|
467
|
-
isBase64: (str) => imageUtils.isValidBase64(str),
|
|
468
|
-
/**
|
|
469
|
-
* Extract file extension from filename or URL
|
|
470
|
-
*/
|
|
471
|
-
getFileExtension: (filename) => {
|
|
472
|
-
const match = filename.match(/\.([^.]+)$/);
|
|
473
|
-
return match ? match[1].toLowerCase() : null;
|
|
474
|
-
},
|
|
475
|
-
/**
|
|
476
|
-
* Convert file size to human readable format
|
|
477
|
-
*/
|
|
478
|
-
formatFileSize: (bytes) => {
|
|
479
|
-
if (bytes === 0) {
|
|
480
|
-
return "0 Bytes";
|
|
481
|
-
}
|
|
482
|
-
const k = 1024;
|
|
483
|
-
const sizes = ["Bytes", "KB", "MB", "GB"];
|
|
484
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
485
|
-
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
|
486
|
-
},
|
|
487
|
-
/**
|
|
488
|
-
* Convert Buffer to base64 string
|
|
489
|
-
*/
|
|
490
|
-
bufferToBase64: (buffer) => {
|
|
491
|
-
return buffer.toString("base64");
|
|
492
|
-
},
|
|
493
|
-
/**
|
|
494
|
-
* Convert base64 string to Buffer
|
|
495
|
-
*/
|
|
496
|
-
base64ToBuffer: (base64) => {
|
|
497
|
-
// Remove data URI prefix if present
|
|
498
|
-
const cleanBase64 = base64.includes(",") ? base64.split(",")[1] : base64;
|
|
499
|
-
return Buffer.from(cleanBase64, "base64");
|
|
500
|
-
},
|
|
501
|
-
/**
|
|
502
|
-
* Convert file path to base64 data URI
|
|
503
|
-
*/
|
|
504
|
-
fileToBase64DataUri: async (filePath, maxBytes = 10 * 1024 * 1024) => {
|
|
505
|
-
try {
|
|
506
|
-
const fs = await import("fs/promises");
|
|
507
|
-
// File existence and type validation
|
|
508
|
-
const stat = await fs.stat(filePath);
|
|
509
|
-
if (!stat.isFile()) {
|
|
510
|
-
throw new Error("Not a file");
|
|
511
|
-
}
|
|
512
|
-
// Size check before reading - prevent memory exhaustion
|
|
513
|
-
if (stat.size > maxBytes) {
|
|
514
|
-
throw new Error(`File too large: ${stat.size} bytes (max: ${maxBytes} bytes)`);
|
|
515
|
-
}
|
|
516
|
-
const buffer = await fs.readFile(filePath);
|
|
517
|
-
// Enhanced MIME detection: try buffer content first, fallback to filename
|
|
518
|
-
const mimeType = ImageProcessor.detectImageType(buffer) ||
|
|
519
|
-
ImageProcessor.detectImageType(filePath);
|
|
520
|
-
const base64 = buffer.toString("base64");
|
|
521
|
-
return `data:${mimeType};base64,${base64}`;
|
|
522
|
-
}
|
|
523
|
-
catch (error) {
|
|
524
|
-
throw new Error(`Failed to convert file to base64: ${error instanceof Error ? error.message : "Unknown error"}`, { cause: error });
|
|
525
|
-
}
|
|
526
|
-
},
|
|
527
|
-
/**
|
|
528
|
-
* Convert URL to base64 data URI by downloading the image.
|
|
529
|
-
* Implements retry logic with exponential backoff for network errors.
|
|
530
|
-
*
|
|
531
|
-
* Retries are performed for:
|
|
532
|
-
* - Network errors (ECONNRESET, ENOTFOUND, ECONNREFUSED, ETIMEDOUT, ERR_NETWORK, AbortError)
|
|
533
|
-
* - Server errors (5xx status codes)
|
|
534
|
-
* - Rate limiting (429 Too Many Requests)
|
|
535
|
-
* - Request timeouts (408 Request Timeout)
|
|
536
|
-
*
|
|
537
|
-
* Retries are NOT performed for:
|
|
538
|
-
* - Client errors (4xx status codes except 408, 429)
|
|
539
|
-
* - Invalid content type
|
|
540
|
-
* - Content size limit exceeded
|
|
541
|
-
* - Unsupported protocol
|
|
542
|
-
*
|
|
543
|
-
* @param url - The URL of the image to download
|
|
544
|
-
* @param options - Configuration options
|
|
545
|
-
* @param options.timeoutMs - Timeout for each download attempt (default: 15000ms)
|
|
546
|
-
* @param options.maxBytes - Maximum allowed file size (default: 10MB)
|
|
547
|
-
* @param options.maxAttempts - Maximum number of total attempts including initial attempt (default: 3)
|
|
548
|
-
* @returns Promise<string> - Base64 data URI of the downloaded image
|
|
549
|
-
* Rate-limited to 10 downloads per second to prevent DoS
|
|
550
|
-
* Uses LRU cache to avoid redundant downloads of the same URL
|
|
551
|
-
*/
|
|
552
|
-
urlToBase64DataUri: async (url, { timeoutMs = 15000, maxBytes = 10 * 1024 * 1024, maxAttempts = 3, } = {}) => {
|
|
553
|
-
// Check cache first
|
|
554
|
-
const cache = getImageCache();
|
|
555
|
-
const cached = cache.get(url);
|
|
556
|
-
if (cached) {
|
|
557
|
-
logger.debug("Using cached image for URL", { url: url.substring(0, 50) });
|
|
558
|
-
return cached.dataUri;
|
|
559
|
-
}
|
|
560
|
-
// Apply rate limiting before download
|
|
561
|
-
await urlDownloadRateLimiter.acquire();
|
|
562
|
-
// Basic protocol whitelist - fail fast, no retry needed
|
|
563
|
-
if (!/^https?:\/\//i.test(url)) {
|
|
564
|
-
throw new Error("Unsupported protocol");
|
|
565
|
-
}
|
|
566
|
-
// Perform the actual download with retry logic
|
|
567
|
-
const performDownload = async () => {
|
|
568
|
-
const controller = new AbortController();
|
|
569
|
-
const t = setTimeout(() => controller.abort(), timeoutMs);
|
|
570
|
-
try {
|
|
571
|
-
const response = await fetch(url, { signal: controller.signal });
|
|
572
|
-
if (!response.ok) {
|
|
573
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
574
|
-
}
|
|
575
|
-
const contentType = response.headers.get("content-type") || "";
|
|
576
|
-
if (!/^image\//i.test(contentType)) {
|
|
577
|
-
throw new Error(`Unsupported content-type: ${contentType || "unknown"}`);
|
|
578
|
-
}
|
|
579
|
-
const len = Number(response.headers.get("content-length") || 0);
|
|
580
|
-
if (len && len > maxBytes) {
|
|
581
|
-
throw new Error(`Content too large: ${len} bytes`);
|
|
582
|
-
}
|
|
583
|
-
const buffer = await response.arrayBuffer();
|
|
584
|
-
if (buffer.byteLength > maxBytes) {
|
|
585
|
-
throw new Error(`Downloaded content too large: ${buffer.byteLength} bytes`);
|
|
586
|
-
}
|
|
587
|
-
const imageBuffer = Buffer.from(buffer);
|
|
588
|
-
const base64 = imageBuffer.toString("base64");
|
|
589
|
-
const dataUri = `data:${contentType || "image/jpeg"};base64,${base64}`;
|
|
590
|
-
// Store in cache for future use
|
|
591
|
-
cache.set(url, dataUri, contentType || "image/jpeg", imageBuffer);
|
|
592
|
-
return dataUri;
|
|
593
|
-
}
|
|
594
|
-
finally {
|
|
595
|
-
clearTimeout(t);
|
|
596
|
-
}
|
|
597
|
-
};
|
|
598
|
-
try {
|
|
599
|
-
return await withRetry(performDownload, {
|
|
600
|
-
maxAttempts,
|
|
601
|
-
initialDelay: SYSTEM_LIMITS.DEFAULT_INITIAL_DELAY,
|
|
602
|
-
backoffMultiplier: SYSTEM_LIMITS.DEFAULT_BACKOFF_MULTIPLIER,
|
|
603
|
-
maxDelay: SYSTEM_LIMITS.DEFAULT_MAX_DELAY,
|
|
604
|
-
retryCondition: isRetryableDownloadError,
|
|
605
|
-
onRetry: (attempt, error) => {
|
|
606
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
607
|
-
const attemptsLeft = maxAttempts - attempt;
|
|
608
|
-
logger.warn(`⚠️ Image download attempt ${attempt} failed for ${url}: ${message}. ${attemptsLeft} ${attemptsLeft === 1 ? "attempt" : "attempts"} remaining...`);
|
|
609
|
-
},
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
catch (error) {
|
|
613
|
-
throw new Error(`Failed to download and convert URL to base64: ${error instanceof Error ? error.message : "Unknown error"}`, { cause: error });
|
|
614
|
-
}
|
|
615
|
-
},
|
|
616
|
-
/**
|
|
617
|
-
* Extract base64 data from data URI
|
|
618
|
-
*/
|
|
619
|
-
extractBase64FromDataUri: (dataUri) => {
|
|
620
|
-
if (!dataUri.includes(",")) {
|
|
621
|
-
return dataUri; // Already just base64
|
|
622
|
-
}
|
|
623
|
-
return dataUri.split(",")[1];
|
|
624
|
-
},
|
|
625
|
-
/**
|
|
626
|
-
* Extract MIME type from data URI
|
|
627
|
-
*/
|
|
628
|
-
extractMimeTypeFromDataUri: (dataUri) => {
|
|
629
|
-
const match = dataUri.match(/^data:([^;]+);base64,/);
|
|
630
|
-
return match ? match[1] : "image/jpeg";
|
|
631
|
-
},
|
|
632
|
-
/**
|
|
633
|
-
* Create data URI from base64 and MIME type
|
|
634
|
-
*/
|
|
635
|
-
createDataUri: (base64, mimeType = "image/jpeg") => {
|
|
636
|
-
// Remove data URI prefix if already present
|
|
637
|
-
const cleanBase64 = base64.includes(",") ? base64.split(",")[1] : base64;
|
|
638
|
-
return `data:${mimeType};base64,${cleanBase64}`;
|
|
639
|
-
},
|
|
640
|
-
/**
|
|
641
|
-
* Validate base64 string format
|
|
642
|
-
* Validates format BEFORE buffer allocation to prevent memory exhaustion
|
|
643
|
-
*/
|
|
644
|
-
isValidBase64: (str) => {
|
|
645
|
-
try {
|
|
646
|
-
// Remove data URI prefix if present
|
|
647
|
-
const cleanBase64 = str.includes(",") ? str.split(",")[1] : str;
|
|
648
|
-
// Empty string check
|
|
649
|
-
if (!cleanBase64 || cleanBase64.length === 0) {
|
|
650
|
-
return false;
|
|
651
|
-
}
|
|
652
|
-
// 1. Validate character set FIRST (A-Z, a-z, 0-9, +, /, =)
|
|
653
|
-
// This prevents memory allocation for invalid input like "hello world"
|
|
654
|
-
const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
655
|
-
if (!base64Regex.test(cleanBase64)) {
|
|
656
|
-
return false;
|
|
657
|
-
}
|
|
658
|
-
// 2. Check length is multiple of 4
|
|
659
|
-
if (cleanBase64.length % 4 !== 0) {
|
|
660
|
-
return false;
|
|
661
|
-
}
|
|
662
|
-
// 3. Validate padding position (max 2 equals at end only)
|
|
663
|
-
const paddingIndex = cleanBase64.indexOf("=");
|
|
664
|
-
if (paddingIndex !== -1) {
|
|
665
|
-
// Padding must be at the end
|
|
666
|
-
if (paddingIndex < cleanBase64.length - 2) {
|
|
667
|
-
return false;
|
|
668
|
-
}
|
|
669
|
-
// No characters after padding
|
|
670
|
-
const afterPadding = cleanBase64.slice(paddingIndex);
|
|
671
|
-
if (!/^=+$/.test(afterPadding)) {
|
|
672
|
-
return false;
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
// 4. ONLY NOW decode if format is valid
|
|
676
|
-
const decoded = Buffer.from(cleanBase64, "base64");
|
|
677
|
-
const reencoded = decoded.toString("base64");
|
|
678
|
-
// Remove padding for comparison (base64 can have different padding)
|
|
679
|
-
const normalizeBase64 = (b64) => b64.replace(/=+$/, "");
|
|
680
|
-
return normalizeBase64(cleanBase64) === normalizeBase64(reencoded);
|
|
681
|
-
}
|
|
682
|
-
catch {
|
|
683
|
-
return false;
|
|
684
|
-
}
|
|
685
|
-
},
|
|
686
|
-
/**
|
|
687
|
-
* Get base64 string size in bytes
|
|
688
|
-
*/
|
|
689
|
-
getBase64Size: (base64) => {
|
|
690
|
-
// Remove data URI prefix if present
|
|
691
|
-
const cleanBase64 = base64.includes(",") ? base64.split(",")[1] : base64;
|
|
692
|
-
return Buffer.byteLength(cleanBase64, "base64");
|
|
693
|
-
},
|
|
694
|
-
/**
|
|
695
|
-
* Compress base64 image by reducing quality (basic implementation)
|
|
696
|
-
* Note: This is a placeholder - for production use, consider using sharp or similar
|
|
697
|
-
*/
|
|
698
|
-
compressBase64: (base64, _quality = 0.8) => {
|
|
699
|
-
// This is a basic implementation that just returns the original
|
|
700
|
-
// In a real implementation, you'd use an image processing library
|
|
701
|
-
logger.warn("Base64 compression not implemented - returning original");
|
|
702
|
-
return base64;
|
|
703
|
-
},
|
|
704
|
-
};
|