@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,799 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* NeuroLink OAuth Token Store
|
|
3
|
-
*
|
|
4
|
-
* Secure storage for OAuth tokens with encoding support and multi-provider capability.
|
|
5
|
-
* Stores tokens in the user's home directory with restrictive permissions.
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - Multi-provider token storage in a single tokens.json file
|
|
9
|
-
* - Secure file storage with 0o600 permissions
|
|
10
|
-
* - Token expiration checking with configurable buffer
|
|
11
|
-
* - Simple XOR-based obfuscation (not encryption, but not plaintext)
|
|
12
|
-
* - Automatic token refresh via configurable refresher functions
|
|
13
|
-
* - Cross-platform support (Unix/macOS/Windows)
|
|
14
|
-
*/
|
|
15
|
-
import { promises as fs } from "fs";
|
|
16
|
-
import { join } from "path";
|
|
17
|
-
import { homedir } from "os";
|
|
18
|
-
import { createHash } from "crypto";
|
|
19
|
-
import { logger } from "../utils/logger.js";
|
|
20
|
-
import { TokenStoreError } from "../types/errors.js";
|
|
21
|
-
import { AsyncMutex } from "../utils/asyncMutex.js";
|
|
22
|
-
const { readFile, writeFile, mkdir, unlink, access, chmod, rename } = fs;
|
|
23
|
-
// =============================================================================
|
|
24
|
-
// TOKEN STORE CLASS
|
|
25
|
-
// =============================================================================
|
|
26
|
-
/**
|
|
27
|
-
* Secure token storage for OAuth tokens with multi-provider support
|
|
28
|
-
*
|
|
29
|
-
* Provides persistent storage for OAuth tokens with:
|
|
30
|
-
* - Multi-provider support in a single file
|
|
31
|
-
* - Secure file permissions (0o600)
|
|
32
|
-
* - Optional obfuscation/encoding
|
|
33
|
-
* - Token expiration checking with buffer
|
|
34
|
-
* - Automatic token refresh via configurable refreshers
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* ```typescript
|
|
38
|
-
* const store = new TokenStore();
|
|
39
|
-
*
|
|
40
|
-
* // Save tokens for a provider
|
|
41
|
-
* await store.saveTokens("anthropic", {
|
|
42
|
-
* accessToken: "sk-...",
|
|
43
|
-
* refreshToken: "rt-...",
|
|
44
|
-
* expiresAt: Date.now() + 3600000,
|
|
45
|
-
* tokenType: "Bearer",
|
|
46
|
-
* });
|
|
47
|
-
*
|
|
48
|
-
* // Set up automatic refresh
|
|
49
|
-
* store.setTokenRefresher("anthropic", async (refreshToken) => {
|
|
50
|
-
* // Call OAuth refresh endpoint
|
|
51
|
-
* return newTokens;
|
|
52
|
-
* });
|
|
53
|
-
*
|
|
54
|
-
* // Get a valid token (auto-refreshes if needed)
|
|
55
|
-
* const token = await store.getValidToken("anthropic");
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
export class TokenStore {
|
|
59
|
-
static STORAGE_VERSION = "2.0";
|
|
60
|
-
static NEUROLINK_DIR = ".neurolink";
|
|
61
|
-
static TOKEN_FILE = "tokens.json";
|
|
62
|
-
static FILE_PERMISSIONS = 0o600;
|
|
63
|
-
static DIR_PERMISSIONS = 0o700;
|
|
64
|
-
/** Default expiration buffer: 1 hour (proactive refresh before actual expiry) */
|
|
65
|
-
static DEFAULT_EXPIRY_BUFFER_MS = 60 * 60 * 1000;
|
|
66
|
-
storagePath;
|
|
67
|
-
encryptionEnabled;
|
|
68
|
-
encryptionKey;
|
|
69
|
-
tokenRefreshers = new Map();
|
|
70
|
-
inFlightRefreshes = new Map();
|
|
71
|
-
_mutex = new AsyncMutex();
|
|
72
|
-
/**
|
|
73
|
-
* Creates a new TokenStore instance
|
|
74
|
-
*
|
|
75
|
-
* @param options - Configuration options
|
|
76
|
-
* @param options.encryptionEnabled - Whether to enable token obfuscation (default: true)
|
|
77
|
-
* @param options.customStoragePath - Override the default storage path
|
|
78
|
-
*/
|
|
79
|
-
constructor(options = {}) {
|
|
80
|
-
const { encryptionEnabled = true, customStoragePath } = options;
|
|
81
|
-
this.encryptionEnabled = encryptionEnabled;
|
|
82
|
-
this.encryptionKey = this.deriveEncryptionKey();
|
|
83
|
-
if (customStoragePath) {
|
|
84
|
-
this.storagePath = customStoragePath;
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
this.storagePath = join(homedir(), TokenStore.NEUROLINK_DIR, TokenStore.TOKEN_FILE);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
// ===========================================================================
|
|
91
|
-
// PUBLIC METHODS
|
|
92
|
-
// ===========================================================================
|
|
93
|
-
/**
|
|
94
|
-
* Gets the path where tokens are stored
|
|
95
|
-
*
|
|
96
|
-
* @returns The absolute path to the token storage file
|
|
97
|
-
*/
|
|
98
|
-
getStoragePath() {
|
|
99
|
-
return this.storagePath;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Saves OAuth tokens for a specific provider
|
|
103
|
-
*
|
|
104
|
-
* @param provider - The provider name (e.g., "anthropic", "openai")
|
|
105
|
-
* @param tokens - The OAuth tokens to save
|
|
106
|
-
* @throws TokenStoreError if storage fails
|
|
107
|
-
*/
|
|
108
|
-
async saveTokens(provider, tokens) {
|
|
109
|
-
return this._mutex.runExclusive(async () => {
|
|
110
|
-
await this._saveTokensInternal(provider, tokens);
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Internal save without mutex — callers must already hold the mutex.
|
|
115
|
-
*/
|
|
116
|
-
async _saveTokensInternal(provider, tokens) {
|
|
117
|
-
// Validate tokens before saving
|
|
118
|
-
this.validateTokens(tokens);
|
|
119
|
-
const storageDir = join(this.storagePath, "..");
|
|
120
|
-
await this.ensureDirectory(storageDir);
|
|
121
|
-
// Load existing data or create new
|
|
122
|
-
let storageData;
|
|
123
|
-
try {
|
|
124
|
-
storageData = await this.loadStorageData();
|
|
125
|
-
}
|
|
126
|
-
catch (error) {
|
|
127
|
-
if (error instanceof TokenStoreError && error.code === "NOT_FOUND") {
|
|
128
|
-
// Create new storage structure
|
|
129
|
-
storageData = {
|
|
130
|
-
version: TokenStore.STORAGE_VERSION,
|
|
131
|
-
lastModified: Date.now(),
|
|
132
|
-
providers: {},
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
throw error;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
// Update provider tokens
|
|
140
|
-
storageData.providers[provider] = {
|
|
141
|
-
tokens,
|
|
142
|
-
createdAt: Date.now(),
|
|
143
|
-
lastAccessed: Date.now(),
|
|
144
|
-
};
|
|
145
|
-
storageData.lastModified = Date.now();
|
|
146
|
-
try {
|
|
147
|
-
const content = this.encryptionEnabled
|
|
148
|
-
? this.obfuscate(JSON.stringify(storageData))
|
|
149
|
-
: JSON.stringify(storageData, null, 2);
|
|
150
|
-
// Write to temporary file first for atomic operation
|
|
151
|
-
const tempPath = `${this.storagePath}.tmp`;
|
|
152
|
-
await writeFile(tempPath, content, "utf-8");
|
|
153
|
-
// Set restrictive permissions before moving to final location
|
|
154
|
-
await chmod(tempPath, TokenStore.FILE_PERMISSIONS);
|
|
155
|
-
// Rename to final location (atomic on most filesystems)
|
|
156
|
-
await fs.rename(tempPath, this.storagePath);
|
|
157
|
-
logger.debug("OAuth tokens saved successfully", {
|
|
158
|
-
provider,
|
|
159
|
-
path: this.storagePath,
|
|
160
|
-
encrypted: this.encryptionEnabled,
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
catch (error) {
|
|
164
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
165
|
-
logger.error("Failed to save OAuth tokens", {
|
|
166
|
-
provider,
|
|
167
|
-
error: errorMessage,
|
|
168
|
-
});
|
|
169
|
-
throw new TokenStoreError(`Failed to save tokens for ${provider}: ${errorMessage}`, "STORAGE_ERROR");
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Loads stored OAuth tokens for a specific provider
|
|
174
|
-
*
|
|
175
|
-
* @param provider - The provider name (e.g., "anthropic", "openai")
|
|
176
|
-
* @returns The stored tokens, or null if not found
|
|
177
|
-
* @throws TokenStoreError if reading fails (other than file not found)
|
|
178
|
-
*/
|
|
179
|
-
async loadTokens(provider) {
|
|
180
|
-
return this._mutex.runExclusive(async () => {
|
|
181
|
-
return this._loadTokensInternal(provider);
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Internal load without mutex — callers must already hold the mutex.
|
|
186
|
-
*/
|
|
187
|
-
async _loadTokensInternal(provider) {
|
|
188
|
-
try {
|
|
189
|
-
const storageData = await this.loadStorageData();
|
|
190
|
-
const providerData = storageData.providers[provider];
|
|
191
|
-
if (!providerData) {
|
|
192
|
-
logger.debug("No stored tokens found for provider", { provider });
|
|
193
|
-
return null;
|
|
194
|
-
}
|
|
195
|
-
// Update last accessed time
|
|
196
|
-
providerData.lastAccessed = Date.now();
|
|
197
|
-
await this.saveStorageData(storageData);
|
|
198
|
-
logger.debug("OAuth tokens retrieved successfully", {
|
|
199
|
-
provider,
|
|
200
|
-
expiresAt: new Date(providerData.tokens.expiresAt).toISOString(),
|
|
201
|
-
isExpired: this.isTokenExpired(providerData.tokens),
|
|
202
|
-
});
|
|
203
|
-
return providerData.tokens;
|
|
204
|
-
}
|
|
205
|
-
catch (error) {
|
|
206
|
-
if (error instanceof TokenStoreError && error.code === "NOT_FOUND") {
|
|
207
|
-
return null;
|
|
208
|
-
}
|
|
209
|
-
throw error;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Clears stored tokens for a specific provider
|
|
214
|
-
*
|
|
215
|
-
* @param provider - The provider name (e.g., "anthropic", "openai")
|
|
216
|
-
* @throws TokenStoreError if deletion fails
|
|
217
|
-
*/
|
|
218
|
-
async clearTokens(provider) {
|
|
219
|
-
return this._mutex.runExclusive(async () => {
|
|
220
|
-
// Clear in-memory refresh state so re-adding an account starts fresh
|
|
221
|
-
this.inFlightRefreshes.delete(provider);
|
|
222
|
-
this.tokenRefreshers.delete(provider);
|
|
223
|
-
try {
|
|
224
|
-
const storageData = await this.loadStorageData();
|
|
225
|
-
if (!storageData.providers[provider]) {
|
|
226
|
-
logger.debug("No tokens to clear for provider", { provider });
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
delete storageData.providers[provider];
|
|
230
|
-
storageData.lastModified = Date.now();
|
|
231
|
-
// If no more providers, delete the file entirely
|
|
232
|
-
if (Object.keys(storageData.providers).length === 0) {
|
|
233
|
-
await this.deleteStorageFile();
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
await this.saveStorageData(storageData);
|
|
237
|
-
}
|
|
238
|
-
logger.info("OAuth tokens cleared successfully", { provider });
|
|
239
|
-
}
|
|
240
|
-
catch (error) {
|
|
241
|
-
if (error instanceof TokenStoreError && error.code === "NOT_FOUND") {
|
|
242
|
-
logger.debug("No tokens to clear for provider", { provider });
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
246
|
-
logger.error("Failed to clear OAuth tokens", {
|
|
247
|
-
provider,
|
|
248
|
-
error: errorMessage,
|
|
249
|
-
});
|
|
250
|
-
throw new TokenStoreError(`Failed to clear tokens for ${provider}: ${errorMessage}`, "STORAGE_ERROR");
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Checks if the given tokens are expired
|
|
256
|
-
*
|
|
257
|
-
* @param tokens - The OAuth tokens to check
|
|
258
|
-
* @param bufferMs - Buffer time in milliseconds before actual expiration (default: 5 minutes)
|
|
259
|
-
* @returns true if token is expired or will expire within buffer time
|
|
260
|
-
*/
|
|
261
|
-
isTokenExpired(tokens, bufferMs = TokenStore.DEFAULT_EXPIRY_BUFFER_MS) {
|
|
262
|
-
const now = Date.now();
|
|
263
|
-
return tokens.expiresAt - bufferMs <= now;
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Gets a valid access token for a provider, refreshing if needed
|
|
267
|
-
*
|
|
268
|
-
* If the stored token is expired or about to expire, and a refresher
|
|
269
|
-
* function has been set, it will automatically refresh the token.
|
|
270
|
-
*
|
|
271
|
-
* @param provider - The provider name (e.g., "anthropic", "openai")
|
|
272
|
-
* @returns The valid access token, or null if not available
|
|
273
|
-
* @throws TokenStoreError if refresh fails
|
|
274
|
-
*/
|
|
275
|
-
async getValidToken(provider) {
|
|
276
|
-
// Phase 1: Read token under mutex (fast)
|
|
277
|
-
const snapshot = await this._mutex.runExclusive(async () => {
|
|
278
|
-
const tokens = await this._loadTokensInternal(provider);
|
|
279
|
-
if (!tokens) {
|
|
280
|
-
return null;
|
|
281
|
-
}
|
|
282
|
-
return { ...tokens };
|
|
283
|
-
});
|
|
284
|
-
if (!snapshot) {
|
|
285
|
-
logger.debug("No tokens found for provider", { provider });
|
|
286
|
-
return null;
|
|
287
|
-
}
|
|
288
|
-
// Token is still valid — return immediately
|
|
289
|
-
if (!this.isTokenExpired(snapshot)) {
|
|
290
|
-
return snapshot.accessToken;
|
|
291
|
-
}
|
|
292
|
-
logger.debug("Token expired or expiring soon", {
|
|
293
|
-
provider,
|
|
294
|
-
expiresAt: new Date(snapshot.expiresAt).toISOString(),
|
|
295
|
-
});
|
|
296
|
-
// Phase 2: Refresh OUTSIDE the mutex so other reads are not blocked
|
|
297
|
-
const refresher = this.tokenRefreshers.get(provider);
|
|
298
|
-
if (!refresher || !snapshot.refreshToken) {
|
|
299
|
-
logger.debug("No refresher configured or no refresh token available", {
|
|
300
|
-
provider,
|
|
301
|
-
hasRefresher: !!refresher,
|
|
302
|
-
hasRefreshToken: !!snapshot.refreshToken,
|
|
303
|
-
});
|
|
304
|
-
// No refresher/refresh-token available — fall back to hard expiry check.
|
|
305
|
-
// The proactive buffer only applies when a refresh is possible.
|
|
306
|
-
return this.isTokenExpired(snapshot, 0) ? null : snapshot.accessToken;
|
|
307
|
-
}
|
|
308
|
-
// Deduplicate concurrent refresh calls for the same provider:
|
|
309
|
-
// If a refresh is already in-flight, await it instead of starting another.
|
|
310
|
-
const existing = this.inFlightRefreshes.get(provider);
|
|
311
|
-
if (existing) {
|
|
312
|
-
logger.debug("Awaiting in-flight refresh for provider", { provider });
|
|
313
|
-
const result = await existing;
|
|
314
|
-
return result.accessToken;
|
|
315
|
-
}
|
|
316
|
-
const refreshTokenValue = snapshot.refreshToken;
|
|
317
|
-
const refreshPromise = (async () => {
|
|
318
|
-
let newTokens;
|
|
319
|
-
try {
|
|
320
|
-
logger.info("Refreshing expired token", { provider });
|
|
321
|
-
newTokens = await refresher(refreshTokenValue);
|
|
322
|
-
}
|
|
323
|
-
catch (error) {
|
|
324
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
325
|
-
logger.error("Failed to refresh token", {
|
|
326
|
-
provider,
|
|
327
|
-
error: errorMessage,
|
|
328
|
-
});
|
|
329
|
-
throw new TokenStoreError(`Failed to refresh token for ${provider}: ${errorMessage}`, "REFRESH_ERROR");
|
|
330
|
-
}
|
|
331
|
-
// Phase 3: Write refreshed token under mutex (fast).
|
|
332
|
-
// Re-check that the token is still expired before overwriting —
|
|
333
|
-
// another caller may have already persisted a fresh token.
|
|
334
|
-
// Also guard against resurrecting cleared/disabled entries:
|
|
335
|
-
// if the entry was removed or disabled during the in-flight refresh,
|
|
336
|
-
// skip the save to avoid re-creating a dead entry.
|
|
337
|
-
const persistedTokens = await this._mutex.runExclusive(async () => {
|
|
338
|
-
// Guard: do not resurrect cleared entries
|
|
339
|
-
const current = await this._loadTokensInternal(provider);
|
|
340
|
-
if (!current) {
|
|
341
|
-
logger.debug("Skipping token persist — provider entry was cleared during refresh", { provider });
|
|
342
|
-
return newTokens; // return refreshed tokens to caller but don't persist
|
|
343
|
-
}
|
|
344
|
-
// Guard: do not resurrect disabled entries
|
|
345
|
-
try {
|
|
346
|
-
const storageData = await this.loadStorageData();
|
|
347
|
-
const providerData = storageData.providers[provider];
|
|
348
|
-
if (providerData?.disabled) {
|
|
349
|
-
logger.debug("Skipping token persist — provider was disabled during refresh", { provider });
|
|
350
|
-
return newTokens;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
catch {
|
|
354
|
-
// Storage read failure — proceed cautiously
|
|
355
|
-
}
|
|
356
|
-
if (!this.isTokenExpired(current)) {
|
|
357
|
-
// Another caller already persisted a fresh token — use theirs.
|
|
358
|
-
logger.debug("Skipping token persist — another refresh already wrote a valid token", { provider });
|
|
359
|
-
return current;
|
|
360
|
-
}
|
|
361
|
-
await this._saveTokensInternal(provider, newTokens);
|
|
362
|
-
return newTokens;
|
|
363
|
-
});
|
|
364
|
-
logger.info("Token refreshed successfully", { provider });
|
|
365
|
-
return persistedTokens;
|
|
366
|
-
})();
|
|
367
|
-
this.inFlightRefreshes.set(provider, refreshPromise);
|
|
368
|
-
try {
|
|
369
|
-
const newTokens = await refreshPromise;
|
|
370
|
-
return newTokens.accessToken;
|
|
371
|
-
}
|
|
372
|
-
finally {
|
|
373
|
-
this.inFlightRefreshes.delete(provider);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Sets the token refresher function for a provider
|
|
378
|
-
*
|
|
379
|
-
* The refresher function will be called automatically when getValidToken
|
|
380
|
-
* detects that the stored token is expired or about to expire.
|
|
381
|
-
*
|
|
382
|
-
* @param provider - The provider name (e.g., "anthropic", "openai")
|
|
383
|
-
* @param refresher - Function that takes a refresh token and returns new tokens
|
|
384
|
-
*/
|
|
385
|
-
setTokenRefresher(provider, refresher) {
|
|
386
|
-
this.tokenRefreshers.set(provider, refresher);
|
|
387
|
-
logger.debug("Token refresher set for provider", { provider });
|
|
388
|
-
}
|
|
389
|
-
/**
|
|
390
|
-
* Removes the token refresher function for a provider
|
|
391
|
-
*
|
|
392
|
-
* @param provider - The provider name (e.g., "anthropic", "openai")
|
|
393
|
-
*/
|
|
394
|
-
clearTokenRefresher(provider) {
|
|
395
|
-
this.tokenRefreshers.delete(provider);
|
|
396
|
-
logger.debug("Token refresher cleared for provider", { provider });
|
|
397
|
-
}
|
|
398
|
-
/**
|
|
399
|
-
* Checks if tokens exist for a specific provider
|
|
400
|
-
*
|
|
401
|
-
* @param provider - The provider name (e.g., "anthropic", "openai")
|
|
402
|
-
* @returns true if tokens are stored for the provider
|
|
403
|
-
*/
|
|
404
|
-
async hasTokens(provider) {
|
|
405
|
-
try {
|
|
406
|
-
const tokens = await this.loadTokens(provider);
|
|
407
|
-
return tokens !== null;
|
|
408
|
-
}
|
|
409
|
-
catch {
|
|
410
|
-
return false;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
/**
|
|
414
|
-
* Lists all providers that have stored tokens
|
|
415
|
-
*
|
|
416
|
-
* @returns Array of provider names
|
|
417
|
-
*/
|
|
418
|
-
async listProviders() {
|
|
419
|
-
try {
|
|
420
|
-
const storageData = await this.loadStorageData();
|
|
421
|
-
return Object.keys(storageData.providers);
|
|
422
|
-
}
|
|
423
|
-
catch (error) {
|
|
424
|
-
if (error instanceof TokenStoreError && error.code === "NOT_FOUND") {
|
|
425
|
-
return [];
|
|
426
|
-
}
|
|
427
|
-
throw error;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
/**
|
|
431
|
-
* Lists all provider keys that start with the given prefix
|
|
432
|
-
*
|
|
433
|
-
* @param prefix - The prefix to filter by (e.g., "anthropic:")
|
|
434
|
-
* @returns Array of matching provider keys
|
|
435
|
-
*/
|
|
436
|
-
async listByPrefix(prefix) {
|
|
437
|
-
const allProviders = await this.listProviders();
|
|
438
|
-
return allProviders.filter((key) => key.startsWith(prefix));
|
|
439
|
-
}
|
|
440
|
-
// ===========================================================================
|
|
441
|
-
// DISABLED STATE METHODS
|
|
442
|
-
// ===========================================================================
|
|
443
|
-
/**
|
|
444
|
-
* Marks a provider's tokens as permanently disabled (persisted to disk).
|
|
445
|
-
*
|
|
446
|
-
* Disabled accounts are skipped immediately by consumers — no wasted
|
|
447
|
-
* round-trips. The state survives proxy restarts because it is stored
|
|
448
|
-
* alongside the tokens in the JSON file.
|
|
449
|
-
*
|
|
450
|
-
* @param provider - The provider key (e.g., "anthropic:user@example.com")
|
|
451
|
-
* @param reason - Optional human-readable reason (e.g., "refresh_failed")
|
|
452
|
-
*/
|
|
453
|
-
async markDisabled(provider, reason) {
|
|
454
|
-
return this._mutex.runExclusive(async () => {
|
|
455
|
-
let storageData;
|
|
456
|
-
try {
|
|
457
|
-
storageData = await this.loadStorageData();
|
|
458
|
-
}
|
|
459
|
-
catch (error) {
|
|
460
|
-
if (error instanceof TokenStoreError && error.code === "NOT_FOUND") {
|
|
461
|
-
logger.debug("No token storage found — nothing to disable", {
|
|
462
|
-
provider,
|
|
463
|
-
});
|
|
464
|
-
return;
|
|
465
|
-
}
|
|
466
|
-
throw error;
|
|
467
|
-
}
|
|
468
|
-
const providerData = storageData.providers[provider];
|
|
469
|
-
if (!providerData) {
|
|
470
|
-
logger.debug("No tokens found for provider — nothing to disable", {
|
|
471
|
-
provider,
|
|
472
|
-
});
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
|
-
providerData.disabled = true;
|
|
476
|
-
providerData.disabledAt = Date.now();
|
|
477
|
-
providerData.disabledReason = reason;
|
|
478
|
-
storageData.lastModified = Date.now();
|
|
479
|
-
await this.saveStorageData(storageData);
|
|
480
|
-
logger.info("Provider marked as disabled", {
|
|
481
|
-
provider,
|
|
482
|
-
reason: reason ?? "unspecified",
|
|
483
|
-
});
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
/**
|
|
487
|
-
* Re-enables a previously disabled provider (persisted to disk).
|
|
488
|
-
*
|
|
489
|
-
* Clears the disabled flag, timestamp, and reason so the account can
|
|
490
|
-
* be used again by the proxy pool.
|
|
491
|
-
*
|
|
492
|
-
* @param provider - The provider key (e.g., "anthropic:user@example.com")
|
|
493
|
-
*/
|
|
494
|
-
async markEnabled(provider) {
|
|
495
|
-
return this._mutex.runExclusive(async () => {
|
|
496
|
-
let storageData;
|
|
497
|
-
try {
|
|
498
|
-
storageData = await this.loadStorageData();
|
|
499
|
-
}
|
|
500
|
-
catch (error) {
|
|
501
|
-
if (error instanceof TokenStoreError && error.code === "NOT_FOUND") {
|
|
502
|
-
logger.debug("No token storage found — nothing to enable", {
|
|
503
|
-
provider,
|
|
504
|
-
});
|
|
505
|
-
return;
|
|
506
|
-
}
|
|
507
|
-
throw error;
|
|
508
|
-
}
|
|
509
|
-
const providerData = storageData.providers[provider];
|
|
510
|
-
if (!providerData) {
|
|
511
|
-
logger.debug("No tokens found for provider — nothing to enable", {
|
|
512
|
-
provider,
|
|
513
|
-
});
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
516
|
-
providerData.disabled = false;
|
|
517
|
-
delete providerData.disabledAt;
|
|
518
|
-
delete providerData.disabledReason;
|
|
519
|
-
storageData.lastModified = Date.now();
|
|
520
|
-
await this.saveStorageData(storageData);
|
|
521
|
-
logger.info("Provider re-enabled", { provider });
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
/**
|
|
525
|
-
* Checks whether a provider's tokens are currently disabled.
|
|
526
|
-
*
|
|
527
|
-
* Returns false for providers that don't exist in the store (no tokens
|
|
528
|
-
* at all) and for entries that predate the disabled field (backward compat).
|
|
529
|
-
*
|
|
530
|
-
* @param provider - The provider key
|
|
531
|
-
* @returns true if the provider entry exists and is disabled
|
|
532
|
-
*/
|
|
533
|
-
async isDisabled(provider) {
|
|
534
|
-
return this._mutex.runExclusive(async () => {
|
|
535
|
-
try {
|
|
536
|
-
const storageData = await this.loadStorageData();
|
|
537
|
-
const providerData = storageData.providers[provider];
|
|
538
|
-
return providerData?.disabled === true;
|
|
539
|
-
}
|
|
540
|
-
catch (error) {
|
|
541
|
-
if (error instanceof TokenStoreError && error.code === "NOT_FOUND") {
|
|
542
|
-
return false;
|
|
543
|
-
}
|
|
544
|
-
throw error;
|
|
545
|
-
}
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
/**
|
|
549
|
-
* Lists all provider keys that are currently disabled.
|
|
550
|
-
*
|
|
551
|
-
* @returns Array of disabled provider keys (empty if none or no storage file)
|
|
552
|
-
*/
|
|
553
|
-
async listDisabled() {
|
|
554
|
-
return this._mutex.runExclusive(async () => {
|
|
555
|
-
try {
|
|
556
|
-
const storageData = await this.loadStorageData();
|
|
557
|
-
return Object.entries(storageData.providers)
|
|
558
|
-
.filter(([, data]) => data.disabled === true)
|
|
559
|
-
.map(([key]) => key);
|
|
560
|
-
}
|
|
561
|
-
catch (error) {
|
|
562
|
-
if (error instanceof TokenStoreError && error.code === "NOT_FOUND") {
|
|
563
|
-
return [];
|
|
564
|
-
}
|
|
565
|
-
throw error;
|
|
566
|
-
}
|
|
567
|
-
});
|
|
568
|
-
}
|
|
569
|
-
/**
|
|
570
|
-
* Removes expired and unrefreshable token entries from disk.
|
|
571
|
-
*
|
|
572
|
-
* An entry is pruned when:
|
|
573
|
-
* - Its access token is expired (with optional buffer) AND it has no
|
|
574
|
-
* refresh token, AND it is NOT manually disabled.
|
|
575
|
-
*
|
|
576
|
-
* Manually disabled entries are preserved so that `auth enable` can
|
|
577
|
-
* re-enable them later. They are only removed via explicit `clearTokens`.
|
|
578
|
-
*
|
|
579
|
-
* @param bufferMs - Extra buffer in milliseconds to subtract from expiresAt
|
|
580
|
-
* when checking expiry (default: 0 — strict expiry check)
|
|
581
|
-
* @returns Array of provider keys that were removed
|
|
582
|
-
*/
|
|
583
|
-
async pruneExpired(bufferMs = 0) {
|
|
584
|
-
return this._mutex.runExclusive(async () => {
|
|
585
|
-
let storageData;
|
|
586
|
-
try {
|
|
587
|
-
storageData = await this.loadStorageData();
|
|
588
|
-
}
|
|
589
|
-
catch (error) {
|
|
590
|
-
if (error instanceof TokenStoreError && error.code === "NOT_FOUND") {
|
|
591
|
-
return [];
|
|
592
|
-
}
|
|
593
|
-
throw error;
|
|
594
|
-
}
|
|
595
|
-
const now = Date.now();
|
|
596
|
-
const pruned = [];
|
|
597
|
-
for (const [key, providerData] of Object.entries(storageData.providers)) {
|
|
598
|
-
const isExpired = providerData.tokens.expiresAt - bufferMs <= now;
|
|
599
|
-
const hasNoRefreshToken = !providerData.tokens.refreshToken;
|
|
600
|
-
const isManuallyDisabled = providerData.disabled === true;
|
|
601
|
-
// Only prune expired+unrefreshable entries that are NOT manually disabled
|
|
602
|
-
if (isExpired && hasNoRefreshToken && !isManuallyDisabled) {
|
|
603
|
-
delete storageData.providers[key];
|
|
604
|
-
pruned.push(key);
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
if (pruned.length > 0) {
|
|
608
|
-
storageData.lastModified = Date.now();
|
|
609
|
-
if (Object.keys(storageData.providers).length === 0) {
|
|
610
|
-
await this.deleteStorageFile();
|
|
611
|
-
}
|
|
612
|
-
else {
|
|
613
|
-
await this.saveStorageData(storageData);
|
|
614
|
-
}
|
|
615
|
-
logger.info("Pruned expired token entries", {
|
|
616
|
-
removed: pruned,
|
|
617
|
-
count: pruned.length,
|
|
618
|
-
});
|
|
619
|
-
}
|
|
620
|
-
return pruned;
|
|
621
|
-
});
|
|
622
|
-
}
|
|
623
|
-
/**
|
|
624
|
-
* Clears all stored tokens for all providers
|
|
625
|
-
*
|
|
626
|
-
* @throws TokenStoreError if deletion fails
|
|
627
|
-
*/
|
|
628
|
-
async clearAllTokens() {
|
|
629
|
-
return this._mutex.runExclusive(async () => {
|
|
630
|
-
// Clear all in-memory refresh state so re-adding accounts starts fresh
|
|
631
|
-
this.inFlightRefreshes.clear();
|
|
632
|
-
this.tokenRefreshers.clear();
|
|
633
|
-
await this.deleteStorageFile();
|
|
634
|
-
logger.info("All OAuth tokens cleared");
|
|
635
|
-
});
|
|
636
|
-
}
|
|
637
|
-
// ===========================================================================
|
|
638
|
-
// PRIVATE HELPER METHODS
|
|
639
|
-
// ===========================================================================
|
|
640
|
-
/**
|
|
641
|
-
* Loads the storage data from file
|
|
642
|
-
*/
|
|
643
|
-
async loadStorageData() {
|
|
644
|
-
try {
|
|
645
|
-
await access(this.storagePath);
|
|
646
|
-
}
|
|
647
|
-
catch {
|
|
648
|
-
// File doesn't exist, return empty storage
|
|
649
|
-
throw new TokenStoreError("Token storage file not found", "NOT_FOUND");
|
|
650
|
-
}
|
|
651
|
-
try {
|
|
652
|
-
const content = await readFile(this.storagePath, "utf-8");
|
|
653
|
-
let storageData;
|
|
654
|
-
if (this.encryptionEnabled) {
|
|
655
|
-
const decrypted = this.deobfuscate(content);
|
|
656
|
-
storageData = JSON.parse(decrypted);
|
|
657
|
-
}
|
|
658
|
-
else {
|
|
659
|
-
storageData = JSON.parse(content);
|
|
660
|
-
}
|
|
661
|
-
// Validate storage data structure
|
|
662
|
-
if (!storageData.providers || !storageData.version) {
|
|
663
|
-
throw new TokenStoreError("Invalid token storage format", "VALIDATION_ERROR");
|
|
664
|
-
}
|
|
665
|
-
return storageData;
|
|
666
|
-
}
|
|
667
|
-
catch (error) {
|
|
668
|
-
if (error instanceof TokenStoreError) {
|
|
669
|
-
throw error;
|
|
670
|
-
}
|
|
671
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
672
|
-
logger.error("Failed to read token storage", { error: errorMessage });
|
|
673
|
-
throw new TokenStoreError(`Failed to read token storage: ${errorMessage}`, "STORAGE_ERROR");
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
/**
|
|
677
|
-
* Saves storage data to file
|
|
678
|
-
*/
|
|
679
|
-
async saveStorageData(data) {
|
|
680
|
-
try {
|
|
681
|
-
const content = this.encryptionEnabled
|
|
682
|
-
? this.obfuscate(JSON.stringify(data))
|
|
683
|
-
: JSON.stringify(data, null, 2);
|
|
684
|
-
const tmpPath = `${this.storagePath}.tmp`;
|
|
685
|
-
await writeFile(tmpPath, content, "utf-8");
|
|
686
|
-
await chmod(tmpPath, TokenStore.FILE_PERMISSIONS);
|
|
687
|
-
await rename(tmpPath, this.storagePath);
|
|
688
|
-
}
|
|
689
|
-
catch (error) {
|
|
690
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
691
|
-
throw new TokenStoreError(`Failed to save token storage: ${errorMessage}`, "STORAGE_ERROR");
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
/**
|
|
695
|
-
* Deletes the storage file
|
|
696
|
-
*/
|
|
697
|
-
async deleteStorageFile() {
|
|
698
|
-
try {
|
|
699
|
-
await access(this.storagePath);
|
|
700
|
-
await unlink(this.storagePath);
|
|
701
|
-
}
|
|
702
|
-
catch (error) {
|
|
703
|
-
if (error.code === "ENOENT") {
|
|
704
|
-
// File doesn't exist, nothing to delete
|
|
705
|
-
return;
|
|
706
|
-
}
|
|
707
|
-
throw error;
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
/**
|
|
711
|
-
* Validates token structure
|
|
712
|
-
*/
|
|
713
|
-
validateTokens(tokens) {
|
|
714
|
-
if (!tokens.accessToken || typeof tokens.accessToken !== "string") {
|
|
715
|
-
throw new TokenStoreError("Invalid access token: must be a non-empty string", "VALIDATION_ERROR");
|
|
716
|
-
}
|
|
717
|
-
if (tokens.refreshToken !== undefined &&
|
|
718
|
-
typeof tokens.refreshToken !== "string") {
|
|
719
|
-
throw new TokenStoreError("Invalid refresh token: must be a string when provided", "VALIDATION_ERROR");
|
|
720
|
-
}
|
|
721
|
-
if (typeof tokens.expiresAt !== "number" || tokens.expiresAt <= 0) {
|
|
722
|
-
throw new TokenStoreError("Invalid expiresAt: must be a positive number", "VALIDATION_ERROR");
|
|
723
|
-
}
|
|
724
|
-
if (!tokens.tokenType || typeof tokens.tokenType !== "string") {
|
|
725
|
-
throw new TokenStoreError("Invalid token type: must be a non-empty string", "VALIDATION_ERROR");
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
/**
|
|
729
|
-
* Ensures the storage directory exists with proper permissions
|
|
730
|
-
*/
|
|
731
|
-
async ensureDirectory(dirPath) {
|
|
732
|
-
try {
|
|
733
|
-
await mkdir(dirPath, {
|
|
734
|
-
recursive: true,
|
|
735
|
-
mode: TokenStore.DIR_PERMISSIONS,
|
|
736
|
-
});
|
|
737
|
-
}
|
|
738
|
-
catch {
|
|
739
|
-
// Directory might already exist, try to set permissions
|
|
740
|
-
try {
|
|
741
|
-
await chmod(dirPath, TokenStore.DIR_PERMISSIONS);
|
|
742
|
-
}
|
|
743
|
-
catch {
|
|
744
|
-
// Ignore permission errors on existing directories
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
/**
|
|
749
|
-
* Derives an encoding key from machine-specific information
|
|
750
|
-
* This provides basic obfuscation - for production use, consider
|
|
751
|
-
* using proper encryption with a user-provided key or system keychain
|
|
752
|
-
*/
|
|
753
|
-
deriveEncryptionKey() {
|
|
754
|
-
const machineInfo = `${homedir()}-neurolink-token-store`;
|
|
755
|
-
return createHash("sha256").update(machineInfo).digest("hex");
|
|
756
|
-
}
|
|
757
|
-
/**
|
|
758
|
-
* Simple XOR-based obfuscation
|
|
759
|
-
* Note: This is NOT cryptographically secure, just basic obfuscation
|
|
760
|
-
* For production use, consider using node:crypto with proper encryption
|
|
761
|
-
*/
|
|
762
|
-
obfuscate(data) {
|
|
763
|
-
const key = this.encryptionKey;
|
|
764
|
-
let result = "";
|
|
765
|
-
for (let i = 0; i < data.length; i++) {
|
|
766
|
-
const charCode = data.charCodeAt(i) ^ key.charCodeAt(i % key.length);
|
|
767
|
-
result += String.fromCharCode(charCode);
|
|
768
|
-
}
|
|
769
|
-
// Encode as base64 for safe storage
|
|
770
|
-
return Buffer.from(result, "binary").toString("base64");
|
|
771
|
-
}
|
|
772
|
-
/**
|
|
773
|
-
* Reverses the XOR obfuscation
|
|
774
|
-
*/
|
|
775
|
-
deobfuscate(data) {
|
|
776
|
-
const key = this.encryptionKey;
|
|
777
|
-
// Decode from base64
|
|
778
|
-
const decoded = Buffer.from(data, "base64").toString("binary");
|
|
779
|
-
let result = "";
|
|
780
|
-
for (let i = 0; i < decoded.length; i++) {
|
|
781
|
-
const charCode = decoded.charCodeAt(i) ^ key.charCodeAt(i % key.length);
|
|
782
|
-
result += String.fromCharCode(charCode);
|
|
783
|
-
}
|
|
784
|
-
return result;
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
// =============================================================================
|
|
788
|
-
// SINGLETON INSTANCE
|
|
789
|
-
// =============================================================================
|
|
790
|
-
/**
|
|
791
|
-
* Default token store singleton instance
|
|
792
|
-
* Uses default configuration with encryption enabled
|
|
793
|
-
*/
|
|
794
|
-
export const tokenStore = new TokenStore();
|
|
795
|
-
/**
|
|
796
|
-
* Alias for backward compatibility
|
|
797
|
-
* @deprecated Use tokenStore instead
|
|
798
|
-
*/
|
|
799
|
-
export const defaultTokenStore = tokenStore;
|