@juspay/neurolink 9.30.0 → 9.31.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 +20 -0
- package/README.md +2 -3
- package/dist/adapters/providerImageAdapter.js +13 -22
- package/dist/adapters/video/videoAnalyzer.d.ts +4 -4
- package/dist/adapters/video/videoAnalyzer.js +3 -3
- package/dist/agent/directTools.d.ts +20 -289
- package/dist/agent/directTools.js +11 -10
- package/dist/auth/accountPool.d.ts +68 -0
- package/dist/auth/accountPool.js +178 -0
- package/dist/auth/anthropicOAuth.d.ts +15 -5
- package/dist/auth/anthropicOAuth.js +117 -57
- package/dist/auth/index.d.ts +7 -5
- package/dist/auth/index.js +6 -2
- package/dist/auth/tokenStore.d.ts +71 -27
- package/dist/auth/tokenStore.js +342 -64
- package/dist/cli/commands/auth.d.ts +39 -2
- package/dist/cli/commands/auth.js +585 -36
- package/dist/cli/commands/config.d.ts +47 -574
- package/dist/cli/commands/config.js +142 -24
- package/dist/cli/commands/docs.d.ts +1 -5
- package/dist/cli/commands/observability.d.ts +1 -17
- package/dist/cli/commands/ollama.js +1 -1
- package/dist/cli/commands/proxy.d.ts +20 -0
- package/dist/cli/commands/proxy.js +1254 -0
- package/dist/cli/commands/setup-anthropic.js +1 -1
- package/dist/cli/commands/setup-azure.js +1 -1
- package/dist/cli/commands/setup-bedrock.js +2 -2
- package/dist/cli/commands/setup-gcp.js +1 -1
- package/dist/cli/commands/setup-google-ai.js +1 -1
- package/dist/cli/commands/setup-huggingface.js +2 -2
- package/dist/cli/commands/setup-mistral.js +1 -1
- package/dist/cli/commands/setup-openai.js +1 -1
- package/dist/cli/commands/setup.js +3 -3
- package/dist/cli/commands/telemetry.d.ts +1 -22
- package/dist/cli/factories/authCommandFactory.d.ts +16 -11
- package/dist/cli/factories/authCommandFactory.js +96 -1
- package/dist/cli/factories/ollamaCommandFactory.js +1 -1
- package/dist/cli/factories/sagemakerCommandFactory.js +25 -6
- package/dist/cli/index.d.ts +0 -6
- package/dist/cli/index.js +5 -2
- package/dist/cli/loop/conversationSelector.js +7 -2
- package/dist/cli/parser.js +19 -1
- package/dist/cli/utils/envManager.js +2 -2
- package/dist/cli/utils/ollamaUtils.d.ts +1 -2
- package/dist/client/adapters/providerImageAdapter.js +588 -0
- package/dist/client/adapters/tts/googleTTSHandler.js +344 -0
- package/dist/client/adapters/video/directorPipeline.js +516 -0
- package/dist/client/adapters/video/ffmpegAdapter.js +206 -0
- package/dist/client/adapters/video/frameExtractor.js +143 -0
- package/dist/client/adapters/video/vertexVideoHandler.js +763 -0
- package/dist/client/adapters/video/videoAnalyzer.js +238 -0
- package/dist/client/adapters/video/videoMerger.js +171 -0
- package/dist/client/agent/directTools.js +840 -0
- package/dist/client/aiSdkAdapter.d.ts +196 -0
- package/dist/client/aiSdkAdapter.js +487 -0
- package/dist/client/auth/anthropicOAuth.js +974 -0
- package/dist/client/auth/tokenStore.js +799 -0
- package/dist/client/auth.d.ts +248 -0
- package/dist/client/auth.js +473 -0
- package/dist/client/client/aiSdkAdapter.js +487 -0
- package/dist/client/client/auth.js +473 -0
- package/dist/client/client/errors.js +552 -0
- package/dist/client/client/httpClient.js +837 -0
- package/dist/client/client/index.js +172 -0
- package/dist/client/client/interceptors.js +601 -0
- package/dist/client/client/reactHooks.js +1159 -0
- package/dist/client/client/sseClient.js +545 -0
- package/dist/client/client/streamingClient.js +917 -0
- package/dist/client/client/wsClient.js +369 -0
- package/dist/client/config/configManager.js +303 -0
- package/dist/client/config/conversationMemory.js +86 -0
- package/dist/client/config/taskClassificationConfig.js +148 -0
- package/dist/client/constants/contextWindows.js +295 -0
- package/dist/client/constants/enums.js +853 -0
- package/dist/client/constants/index.js +207 -0
- package/dist/client/constants/performance.js +389 -0
- package/dist/client/constants/retry.js +266 -0
- package/dist/client/constants/timeouts.js +182 -0
- package/dist/client/constants/tokens.js +380 -0
- package/dist/client/constants/videoErrors.js +46 -0
- package/dist/client/context/budgetChecker.js +98 -0
- package/dist/client/context/contextCompactor.js +205 -0
- package/dist/client/context/emergencyTruncation.js +88 -0
- package/dist/client/context/errorDetection.js +171 -0
- package/dist/client/context/errors.js +21 -0
- package/dist/client/context/fileTokenBudget.js +127 -0
- package/dist/client/context/prompts/summarizationPrompt.js +117 -0
- package/dist/client/context/stages/fileReadDeduplicator.js +66 -0
- package/dist/client/context/stages/slidingWindowTruncator.js +190 -0
- package/dist/client/context/stages/structuredSummarizer.js +99 -0
- package/dist/client/context/stages/toolOutputPruner.js +52 -0
- package/dist/client/context/summarizationEngine.js +136 -0
- package/dist/client/context/toolOutputLimits.js +78 -0
- package/dist/client/context/toolPairRepair.js +66 -0
- package/dist/client/core/analytics.js +88 -0
- package/dist/client/core/baseProvider.js +1385 -0
- package/dist/client/core/constants.js +140 -0
- package/dist/client/core/conversationMemoryFactory.js +141 -0
- package/dist/client/core/conversationMemoryInitializer.js +128 -0
- package/dist/client/core/conversationMemoryManager.js +344 -0
- package/dist/client/core/dynamicModels.js +358 -0
- package/dist/client/core/evaluation.js +309 -0
- package/dist/client/core/evaluationProviders.js +248 -0
- package/dist/client/core/factory.js +412 -0
- package/dist/client/core/infrastructure/baseError.js +22 -0
- package/dist/client/core/infrastructure/baseFactory.js +54 -0
- package/dist/client/core/infrastructure/baseRegistry.js +49 -0
- package/dist/client/core/infrastructure/index.js +5 -0
- package/dist/client/core/infrastructure/retry.js +20 -0
- package/dist/client/core/infrastructure/typedEventEmitter.js +23 -0
- package/dist/client/core/modelConfiguration.js +851 -0
- package/dist/client/core/modules/GenerationHandler.js +588 -0
- package/dist/client/core/modules/MessageBuilder.js +273 -0
- package/dist/client/core/modules/StreamHandler.js +185 -0
- package/dist/client/core/modules/TelemetryHandler.js +203 -0
- package/dist/client/core/modules/ToolsManager.js +499 -0
- package/dist/client/core/modules/Utilities.js +331 -0
- package/dist/client/core/redisConversationMemoryManager.js +1435 -0
- package/dist/client/core/streamAnalytics.js +131 -0
- package/dist/client/errors.d.ts +299 -0
- package/dist/client/errors.js +552 -0
- package/dist/client/evaluation/contextBuilder.js +134 -0
- package/dist/client/evaluation/index.js +61 -0
- package/dist/client/evaluation/prompts.js +73 -0
- package/dist/client/evaluation/ragasEvaluator.js +110 -0
- package/dist/client/evaluation/retryManager.js +78 -0
- package/dist/client/evaluation/scoring.js +61 -0
- package/dist/client/factories/providerFactory.js +166 -0
- package/dist/client/factories/providerRegistry.js +166 -0
- package/dist/client/features/ppt/constants.js +896 -0
- package/dist/client/features/ppt/contentPlanner.js +529 -0
- package/dist/client/features/ppt/presentationOrchestrator.js +236 -0
- package/dist/client/features/ppt/slideGenerator.js +532 -0
- package/dist/client/features/ppt/slideRenderers.js +2383 -0
- package/dist/client/features/ppt/slideTypeInference.js +405 -0
- package/dist/client/features/ppt/types.js +13 -0
- package/dist/client/features/ppt/utils.js +443 -0
- package/dist/client/files/fileReferenceRegistry.js +1543 -0
- package/dist/client/files/fileTools.js +450 -0
- package/dist/client/files/streamingReader.js +321 -0
- package/dist/client/files/types.js +23 -0
- package/dist/client/hitl/hitlErrors.js +54 -0
- package/dist/client/hitl/hitlManager.js +460 -0
- package/dist/client/httpClient.d.ts +297 -0
- package/dist/client/httpClient.js +837 -0
- package/dist/client/index.d.ts +111 -0
- package/dist/client/index.js +511 -0
- package/dist/client/interceptors.d.ts +283 -0
- package/dist/client/interceptors.js +601 -0
- package/dist/client/mcp/agentExposure.js +356 -0
- package/dist/client/mcp/auth/index.js +11 -0
- package/dist/client/mcp/auth/oauthClientProvider.js +325 -0
- package/dist/client/mcp/auth/tokenStorage.js +134 -0
- package/dist/client/mcp/batching/index.js +10 -0
- package/dist/client/mcp/batching/requestBatcher.js +441 -0
- package/dist/client/mcp/caching/index.js +10 -0
- package/dist/client/mcp/caching/toolCache.js +433 -0
- package/dist/client/mcp/elicitation/elicitationManager.js +376 -0
- package/dist/client/mcp/elicitation/index.js +11 -0
- package/dist/client/mcp/elicitation/types.js +10 -0
- package/dist/client/mcp/elicitationProtocol.js +375 -0
- package/dist/client/mcp/enhancedToolDiscovery.js +481 -0
- package/dist/client/mcp/externalServerManager.js +1478 -0
- package/dist/client/mcp/factory.js +161 -0
- package/dist/client/mcp/flexibleToolValidator.js +161 -0
- package/dist/client/mcp/httpRateLimiter.js +391 -0
- package/dist/client/mcp/httpRetryHandler.js +178 -0
- package/dist/client/mcp/index.js +74 -0
- package/dist/client/mcp/mcpCircuitBreaker.js +427 -0
- package/dist/client/mcp/mcpClientFactory.js +708 -0
- package/dist/client/mcp/mcpRegistryClient.js +488 -0
- package/dist/client/mcp/mcpServerBase.js +373 -0
- package/dist/client/mcp/multiServerManager.js +579 -0
- package/dist/client/mcp/registry.js +158 -0
- package/dist/client/mcp/routing/index.js +10 -0
- package/dist/client/mcp/routing/toolRouter.js +416 -0
- package/dist/client/mcp/serverCapabilities.js +502 -0
- package/dist/client/mcp/servers/agent/directToolsServer.js +150 -0
- package/dist/client/mcp/toolAnnotations.js +239 -0
- package/dist/client/mcp/toolConverter.js +258 -0
- package/dist/client/mcp/toolDiscoveryService.js +798 -0
- package/dist/client/mcp/toolIntegration.js +334 -0
- package/dist/client/mcp/toolRegistry.js +719 -0
- package/dist/client/memory/hippocampusInitializer.js +19 -0
- package/dist/client/memory/memoryRetrievalTools.js +166 -0
- package/dist/client/middleware/builtin/analytics.js +132 -0
- package/dist/client/middleware/builtin/autoEvaluation.js +203 -0
- package/dist/client/middleware/builtin/guardrails.js +109 -0
- package/dist/client/middleware/builtin/lifecycle.js +168 -0
- package/dist/client/middleware/factory.js +327 -0
- package/dist/client/middleware/registry.js +295 -0
- package/dist/client/middleware/utils/guardrailsUtils.js +396 -0
- package/dist/client/models/anthropicModels.js +527 -0
- package/dist/client/neurolink.js +8015 -0
- package/dist/client/observability/exporterRegistry.js +413 -0
- package/dist/client/observability/exporters/arizeExporter.js +138 -0
- package/dist/client/observability/exporters/baseExporter.js +190 -0
- package/dist/client/observability/exporters/braintrustExporter.js +154 -0
- package/dist/client/observability/exporters/datadogExporter.js +196 -0
- package/dist/client/observability/exporters/laminarExporter.js +302 -0
- package/dist/client/observability/exporters/langfuseExporter.js +209 -0
- package/dist/client/observability/exporters/langsmithExporter.js +143 -0
- package/dist/client/observability/exporters/otelExporter.js +164 -0
- package/dist/client/observability/exporters/posthogExporter.js +287 -0
- package/dist/client/observability/exporters/sentryExporter.js +165 -0
- package/dist/client/observability/index.js +31 -0
- package/dist/client/observability/metricsAggregator.js +556 -0
- package/dist/client/observability/otelBridge.js +131 -0
- package/dist/client/observability/retryPolicy.js +383 -0
- package/dist/client/observability/sampling/samplers.js +216 -0
- package/dist/client/observability/spanProcessor.js +303 -0
- package/dist/client/observability/tokenTracker.js +413 -0
- package/dist/client/observability/types/exporterTypes.js +5 -0
- package/dist/client/observability/types/index.js +4 -0
- package/dist/client/observability/types/spanTypes.js +92 -0
- package/dist/client/observability/utils/safeMetadata.js +25 -0
- package/dist/client/observability/utils/spanSerializer.js +292 -0
- package/dist/client/processors/archive/ArchiveProcessor.js +1308 -0
- package/dist/client/processors/base/BaseFileProcessor.js +614 -0
- package/dist/client/processors/base/types.js +82 -0
- package/dist/client/processors/config/fileTypes.js +520 -0
- package/dist/client/processors/config/index.js +92 -0
- package/dist/client/processors/config/languageMap.js +410 -0
- package/dist/client/processors/config/mimeTypes.js +363 -0
- package/dist/client/processors/config/sizeLimits.js +258 -0
- package/dist/client/processors/document/ExcelProcessor.js +590 -0
- package/dist/client/processors/document/OpenDocumentProcessor.js +212 -0
- package/dist/client/processors/document/PptxProcessor.js +157 -0
- package/dist/client/processors/document/RtfProcessor.js +361 -0
- package/dist/client/processors/document/WordProcessor.js +353 -0
- package/dist/client/processors/errors/FileErrorCode.js +255 -0
- package/dist/client/processors/errors/errorHelpers.js +386 -0
- package/dist/client/processors/errors/errorSerializer.js +507 -0
- package/dist/client/processors/errors/index.js +49 -0
- package/dist/client/processors/markup/SvgProcessor.js +240 -0
- package/dist/client/processors/media/AudioProcessor.js +707 -0
- package/dist/client/processors/media/VideoProcessor.js +1045 -0
- package/dist/client/providers/amazonBedrock.js +1512 -0
- package/dist/client/providers/amazonSagemaker.js +162 -0
- package/dist/client/providers/anthropic.js +831 -0
- package/dist/client/providers/azureOpenai.js +143 -0
- package/dist/client/providers/googleAiStudio.js +1200 -0
- package/dist/client/providers/googleNativeGemini3.js +543 -0
- package/dist/client/providers/googleVertex.js +2936 -0
- package/dist/client/providers/huggingFace.js +315 -0
- package/dist/client/providers/litellm.js +488 -0
- package/dist/client/providers/mistral.js +157 -0
- package/dist/client/providers/ollama.js +1579 -0
- package/dist/client/providers/openAI.js +627 -0
- package/dist/client/providers/openRouter.js +543 -0
- package/dist/client/providers/openaiCompatible.js +290 -0
- package/dist/client/providers/providerTypeUtils.js +46 -0
- package/dist/client/providers/sagemaker/adaptive-semaphore.js +215 -0
- package/dist/client/providers/sagemaker/client.js +472 -0
- package/dist/client/providers/sagemaker/config.js +317 -0
- package/dist/client/providers/sagemaker/detection.js +606 -0
- package/dist/client/providers/sagemaker/error-constants.js +227 -0
- package/dist/client/providers/sagemaker/errors.js +299 -0
- package/dist/client/providers/sagemaker/language-model.js +775 -0
- package/dist/client/providers/sagemaker/parsers.js +634 -0
- package/dist/client/providers/sagemaker/streaming.js +331 -0
- package/dist/client/providers/sagemaker/structured-parser.js +625 -0
- package/dist/client/proxy/accountQuota.js +162 -0
- package/dist/client/proxy/claudeFormat.js +595 -0
- package/dist/client/proxy/modelRouter.js +29 -0
- package/dist/client/proxy/oauthFetch.js +367 -0
- package/dist/client/proxy/proxyFetch.js +586 -0
- package/dist/client/proxy/requestLogger.js +207 -0
- package/dist/client/proxy/tokenRefresh.js +124 -0
- package/dist/client/proxy/usageStats.js +74 -0
- package/dist/client/proxy/utils/noProxyUtils.js +149 -0
- package/dist/client/rag/ChunkerFactory.js +320 -0
- package/dist/client/rag/ChunkerRegistry.js +421 -0
- package/dist/client/rag/chunkers/BaseChunker.js +143 -0
- package/dist/client/rag/chunkers/CharacterChunker.js +28 -0
- package/dist/client/rag/chunkers/HTMLChunker.js +38 -0
- package/dist/client/rag/chunkers/JSONChunker.js +68 -0
- package/dist/client/rag/chunkers/LaTeXChunker.js +63 -0
- package/dist/client/rag/chunkers/MarkdownChunker.js +306 -0
- package/dist/client/rag/chunkers/RecursiveChunker.js +139 -0
- package/dist/client/rag/chunkers/SemanticMarkdownChunker.js +138 -0
- package/dist/client/rag/chunkers/SentenceChunker.js +66 -0
- package/dist/client/rag/chunkers/TokenChunker.js +61 -0
- package/dist/client/rag/chunkers/index.js +15 -0
- package/dist/client/rag/chunking/characterChunker.js +142 -0
- package/dist/client/rag/chunking/chunkerRegistry.js +194 -0
- package/dist/client/rag/chunking/htmlChunker.js +247 -0
- package/dist/client/rag/chunking/index.js +17 -0
- package/dist/client/rag/chunking/jsonChunker.js +281 -0
- package/dist/client/rag/chunking/latexChunker.js +251 -0
- package/dist/client/rag/chunking/markdownChunker.js +373 -0
- package/dist/client/rag/chunking/recursiveChunker.js +148 -0
- package/dist/client/rag/chunking/semanticChunker.js +306 -0
- package/dist/client/rag/chunking/sentenceChunker.js +230 -0
- package/dist/client/rag/chunking/tokenChunker.js +183 -0
- package/dist/client/rag/document/MDocument.js +392 -0
- package/dist/client/rag/document/index.js +5 -0
- package/dist/client/rag/document/loaders.js +500 -0
- package/dist/client/rag/errors/RAGError.js +274 -0
- package/dist/client/rag/errors/index.js +6 -0
- package/dist/client/rag/graphRag/graphRAG.js +401 -0
- package/dist/client/rag/graphRag/index.js +4 -0
- package/dist/client/rag/index.js +141 -0
- package/dist/client/rag/metadata/MetadataExtractorFactory.js +418 -0
- package/dist/client/rag/metadata/MetadataExtractorRegistry.js +362 -0
- package/dist/client/rag/metadata/index.js +9 -0
- package/dist/client/rag/metadata/metadataExtractor.js +280 -0
- package/dist/client/rag/pipeline/RAGPipeline.js +436 -0
- package/dist/client/rag/pipeline/contextAssembly.js +341 -0
- package/dist/client/rag/pipeline/index.js +5 -0
- package/dist/client/rag/ragIntegration.js +321 -0
- package/dist/client/rag/reranker/RerankerFactory.js +430 -0
- package/dist/client/rag/reranker/RerankerRegistry.js +402 -0
- package/dist/client/rag/reranker/index.js +9 -0
- package/dist/client/rag/reranker/reranker.js +277 -0
- package/dist/client/rag/resilience/CircuitBreaker.js +431 -0
- package/dist/client/rag/resilience/RetryHandler.js +304 -0
- package/dist/client/rag/resilience/index.js +7 -0
- package/dist/client/rag/retrieval/hybridSearch.js +335 -0
- package/dist/client/rag/retrieval/index.js +5 -0
- package/dist/client/rag/retrieval/vectorQueryTool.js +307 -0
- package/dist/client/rag/types.js +8 -0
- package/dist/client/reactHooks.d.ts +239 -0
- package/dist/client/reactHooks.tsx +1483 -0
- package/dist/client/sdk/toolRegistration.js +377 -0
- package/dist/client/server/abstract/baseServerAdapter.js +575 -0
- package/dist/client/server/adapters/expressAdapter.js +486 -0
- package/dist/client/server/adapters/fastifyAdapter.js +472 -0
- package/dist/client/server/adapters/honoAdapter.js +632 -0
- package/dist/client/server/adapters/koaAdapter.js +510 -0
- package/dist/client/server/errors.js +486 -0
- package/dist/client/server/factory/serverAdapterFactory.js +160 -0
- package/dist/client/server/index.js +108 -0
- package/dist/client/server/middleware/abortSignal.js +111 -0
- package/dist/client/server/middleware/auth.js +388 -0
- package/dist/client/server/middleware/cache.js +359 -0
- package/dist/client/server/middleware/common.js +281 -0
- package/dist/client/server/middleware/deprecation.js +190 -0
- package/dist/client/server/middleware/mcpBodyAttachment.js +63 -0
- package/dist/client/server/middleware/rateLimit.js +227 -0
- package/dist/client/server/middleware/validation.js +388 -0
- package/dist/client/server/openapi/generator.js +398 -0
- package/dist/client/server/openapi/index.js +36 -0
- package/dist/client/server/openapi/schemas.js +695 -0
- package/dist/client/server/openapi/templates.js +374 -0
- package/dist/client/server/routes/agentRoutes.js +171 -0
- package/dist/client/server/routes/claudeProxyRoutes.js +1600 -0
- package/dist/client/server/routes/healthRoutes.js +187 -0
- package/dist/client/server/routes/index.js +57 -0
- package/dist/client/server/routes/mcpRoutes.js +342 -0
- package/dist/client/server/routes/memoryRoutes.js +350 -0
- package/dist/client/server/routes/openApiRoutes.js +126 -0
- package/dist/client/server/routes/toolRoutes.js +199 -0
- package/dist/client/server/streaming/dataStream.js +486 -0
- package/dist/client/server/streaming/index.js +11 -0
- package/dist/client/server/types.js +67 -0
- package/dist/client/server/utils/redaction.js +334 -0
- package/dist/client/server/utils/validation.js +243 -0
- package/dist/client/server/websocket/WebSocketHandler.js +383 -0
- package/dist/client/server/websocket/index.js +4 -0
- package/dist/client/services/server/ai/observability/instrumentation.js +808 -0
- package/dist/client/sseClient.d.ts +156 -0
- package/dist/client/sseClient.js +545 -0
- package/dist/client/streamingClient.d.ts +327 -0
- package/dist/client/streamingClient.js +917 -0
- package/dist/client/telemetry/attributes.js +100 -0
- package/dist/client/telemetry/index.js +26 -0
- package/dist/client/telemetry/telemetryService.js +308 -0
- package/dist/client/telemetry/tracers.js +17 -0
- package/dist/client/telemetry/withSpan.js +34 -0
- package/dist/client/types/actionTypes.js +6 -0
- package/dist/client/types/analytics.js +5 -0
- package/dist/client/types/authTypes.js +8 -0
- package/dist/client/types/circuitBreakerErrors.js +34 -0
- package/dist/client/types/cli.js +21 -0
- package/dist/client/types/clientTypes.js +10 -0
- package/dist/client/types/common.js +51 -0
- package/dist/client/types/configTypes.js +49 -0
- package/dist/client/types/content.js +19 -0
- package/dist/client/types/contextTypes.js +400 -0
- package/dist/client/types/conversation.js +47 -0
- package/dist/client/types/conversationMemoryInterface.js +6 -0
- package/dist/client/types/domainTypes.js +5 -0
- package/dist/client/types/errors.js +167 -0
- package/dist/client/types/evaluation.js +5 -0
- package/dist/client/types/evaluationProviders.js +5 -0
- package/dist/client/types/evaluationTypes.js +1 -0
- package/dist/client/types/externalMcp.js +6 -0
- package/dist/client/types/fileReferenceTypes.js +8 -0
- package/dist/client/types/fileTypes.js +4 -0
- package/dist/client/types/generateTypes.js +1 -0
- package/dist/client/types/guardrails.js +1 -0
- package/dist/client/types/hitlTypes.js +8 -0
- package/dist/client/types/index.js +57 -0
- package/dist/client/types/mcpTypes.js +5 -0
- package/dist/client/types/middlewareTypes.js +1 -0
- package/dist/client/types/modelTypes.js +30 -0
- package/dist/client/types/multimodal.js +135 -0
- package/dist/client/types/observability.js +6 -0
- package/dist/client/types/pptTypes.js +82 -0
- package/dist/client/types/providers.js +111 -0
- package/dist/client/types/proxyTypes.js +16 -0
- package/dist/client/types/ragTypes.js +7 -0
- package/dist/client/types/sdkTypes.js +8 -0
- package/dist/client/types/serviceTypes.js +5 -0
- package/dist/client/types/streamTypes.js +1 -0
- package/dist/client/types/subscriptionTypes.js +9 -0
- package/dist/client/types/taskClassificationTypes.js +5 -0
- package/dist/client/types/tools.js +24 -0
- package/dist/client/types/ttsTypes.js +57 -0
- package/dist/client/types/typeAliases.js +48 -0
- package/dist/client/types/utilities.js +4 -0
- package/dist/client/types/workflowTypes.js +30 -0
- package/dist/client/utils/async/withTimeout.js +98 -0
- package/dist/client/utils/asyncMutex.js +60 -0
- package/dist/client/utils/conversationMemory.js +431 -0
- package/dist/client/utils/csvProcessor.js +846 -0
- package/dist/client/utils/errorHandling.js +936 -0
- package/dist/client/utils/evaluationUtils.js +131 -0
- package/dist/client/utils/factoryProcessing.js +589 -0
- package/dist/client/utils/fileDetector.js +2161 -0
- package/dist/client/utils/imageCache.js +376 -0
- package/dist/client/utils/imageProcessor.js +704 -0
- package/dist/client/utils/logger.js +491 -0
- package/dist/client/utils/mcpDefaults.js +134 -0
- package/dist/client/utils/messageBuilder.js +1653 -0
- package/dist/client/utils/modelAliasResolver.js +54 -0
- package/dist/client/utils/modelDetection.js +80 -0
- package/dist/client/utils/modelRouter.js +292 -0
- package/dist/client/utils/multimodalOptionsBuilder.js +65 -0
- package/dist/client/utils/observabilityHelpers.js +47 -0
- package/dist/client/utils/parameterValidation.js +966 -0
- package/dist/client/utils/pdfProcessor.js +410 -0
- package/dist/client/utils/performance.js +222 -0
- package/dist/client/utils/pricing.js +340 -0
- package/dist/client/utils/promptRedaction.js +62 -0
- package/dist/client/utils/providerConfig.js +1009 -0
- package/dist/client/utils/providerHealth.js +1237 -0
- package/dist/client/utils/providerRetry.js +112 -0
- package/dist/client/utils/providerUtils.js +434 -0
- package/dist/client/utils/rateLimiter.js +200 -0
- package/dist/client/utils/redis.js +368 -0
- package/dist/client/utils/retryHandler.js +269 -0
- package/dist/client/utils/retryability.js +22 -0
- package/dist/client/utils/sanitizers/svg.js +481 -0
- package/dist/client/utils/schemaConversion.js +255 -0
- package/dist/client/utils/taskClassificationUtils.js +149 -0
- package/dist/client/utils/taskClassifier.js +94 -0
- package/dist/client/utils/thinkingConfig.js +104 -0
- package/dist/client/utils/timeout.js +359 -0
- package/dist/client/utils/tokenEstimation.js +142 -0
- package/dist/client/utils/tokenLimits.js +125 -0
- package/dist/client/utils/tokenUtils.js +239 -0
- package/dist/client/utils/toolUtils.js +75 -0
- package/dist/client/utils/transformationUtils.js +554 -0
- package/dist/client/utils/ttsProcessor.js +286 -0
- package/dist/client/utils/typeUtils.js +97 -0
- package/dist/client/utils/videoAnalysisProcessor.js +67 -0
- package/dist/client/workflow/config.js +398 -0
- package/dist/client/workflow/core/ensembleExecutor.js +407 -0
- package/dist/client/workflow/core/judgeScorer.js +544 -0
- package/dist/client/workflow/core/responseConditioner.js +225 -0
- package/dist/client/workflow/core/types/conditionerTypes.js +7 -0
- package/dist/client/workflow/core/types/ensembleTypes.js +7 -0
- package/dist/client/workflow/core/types/index.js +7 -0
- package/dist/client/workflow/core/types/judgeTypes.js +7 -0
- package/dist/client/workflow/core/types/layerTypes.js +7 -0
- package/dist/client/workflow/core/types/registryTypes.js +7 -0
- package/dist/client/workflow/core/workflowRegistry.js +304 -0
- package/dist/client/workflow/core/workflowRunner.js +586 -0
- package/dist/client/workflow/index.js +50 -0
- package/dist/client/workflow/types.js +9 -0
- package/dist/client/workflow/utils/types/index.js +7 -0
- package/dist/client/workflow/utils/workflowMetrics.js +311 -0
- package/dist/client/workflow/utils/workflowValidation.js +420 -0
- package/dist/client/workflow/workflows/adaptiveWorkflow.js +366 -0
- package/dist/client/workflow/workflows/consensusWorkflow.js +192 -0
- package/dist/client/workflow/workflows/fallbackWorkflow.js +225 -0
- package/dist/client/workflow/workflows/multiJudgeWorkflow.js +351 -0
- package/dist/client/wsClient.d.ts +130 -0
- package/dist/client/wsClient.js +369 -0
- package/dist/config/configManager.js +2 -2
- package/dist/constants/contextWindows.js +15 -13
- package/dist/constants/enums.d.ts +10 -16
- package/dist/constants/enums.js +12 -18
- package/dist/constants/index.d.ts +0 -10
- package/dist/constants/index.js +1 -1
- package/dist/constants/tokens.d.ts +29 -16
- package/dist/constants/tokens.js +23 -16
- package/dist/core/baseProvider.d.ts +5 -5
- package/dist/core/baseProvider.js +6 -6
- package/dist/core/constants.js +6 -1
- package/dist/core/dynamicModels.js +10 -6
- package/dist/core/evaluationProviders.js +1 -1
- package/dist/core/infrastructure/baseError.d.ts +1 -1
- package/dist/core/infrastructure/baseFactory.d.ts +1 -6
- package/dist/core/infrastructure/baseRegistry.d.ts +6 -5
- package/dist/core/infrastructure/index.d.ts +6 -4
- package/dist/core/infrastructure/index.js +2 -2
- package/dist/core/modelConfiguration.js +3 -1
- package/dist/core/modules/GenerationHandler.d.ts +3 -3
- package/dist/core/modules/GenerationHandler.js +49 -41
- package/dist/core/modules/MessageBuilder.d.ts +5 -5
- package/dist/core/modules/MessageBuilder.js +4 -6
- package/dist/core/modules/StreamHandler.js +26 -12
- package/dist/core/modules/TelemetryHandler.d.ts +4 -6
- package/dist/core/modules/TelemetryHandler.js +7 -6
- package/dist/core/modules/ToolsManager.d.ts +2 -12
- package/dist/core/modules/ToolsManager.js +20 -4
- package/dist/core/modules/Utilities.js +3 -1
- package/dist/core/redisConversationMemoryManager.js +3 -3
- package/dist/core/streamAnalytics.js +23 -9
- package/dist/evaluation/contextBuilder.d.ts +2 -2
- package/dist/evaluation/contextBuilder.js +2 -2
- package/dist/evaluation/index.d.ts +2 -2
- package/dist/evaluation/retryManager.js +1 -1
- package/dist/factories/providerFactory.js +2 -2
- package/dist/features/ppt/constants.js +1 -1
- package/dist/features/ppt/presentationOrchestrator.js +7 -3
- package/dist/features/ppt/slideGenerator.d.ts +2 -1
- package/dist/features/ppt/slideGenerator.js +6 -1
- package/dist/files/fileTools.d.ts +16 -247
- package/dist/files/fileTools.js +16 -15
- package/dist/index.d.ts +5 -3
- package/dist/index.js +20 -3
- package/dist/lib/adapters/providerImageAdapter.js +13 -22
- package/dist/lib/adapters/video/videoAnalyzer.d.ts +4 -4
- package/dist/lib/adapters/video/videoAnalyzer.js +3 -3
- package/dist/lib/agent/directTools.d.ts +20 -289
- package/dist/lib/agent/directTools.js +11 -10
- package/dist/lib/auth/accountPool.d.ts +68 -0
- package/dist/lib/auth/accountPool.js +179 -0
- package/dist/lib/auth/anthropicOAuth.d.ts +15 -5
- package/dist/lib/auth/anthropicOAuth.js +117 -57
- package/dist/lib/auth/index.d.ts +7 -5
- package/dist/lib/auth/index.js +6 -2
- package/dist/lib/auth/tokenStore.d.ts +71 -27
- package/dist/lib/auth/tokenStore.js +342 -64
- package/dist/lib/client/aiSdkAdapter.d.ts +196 -0
- package/dist/lib/client/aiSdkAdapter.js +488 -0
- package/dist/lib/client/auth.d.ts +248 -0
- package/dist/lib/client/auth.js +474 -0
- package/dist/lib/client/errors.d.ts +299 -0
- package/dist/lib/client/errors.js +553 -0
- package/dist/lib/client/httpClient.d.ts +297 -0
- package/dist/lib/client/httpClient.js +838 -0
- package/dist/lib/client/index.d.ts +111 -0
- package/dist/lib/client/index.js +173 -0
- package/dist/lib/client/interceptors.d.ts +283 -0
- package/dist/lib/client/interceptors.js +602 -0
- package/dist/lib/client/reactHooks.d.ts +239 -0
- package/dist/lib/client/reactHooks.js +1160 -0
- package/dist/lib/client/sseClient.d.ts +156 -0
- package/dist/lib/client/sseClient.js +546 -0
- package/dist/lib/client/streamingClient.d.ts +327 -0
- package/dist/lib/client/streamingClient.js +918 -0
- package/dist/lib/client/wsClient.d.ts +130 -0
- package/dist/lib/client/wsClient.js +370 -0
- package/dist/lib/config/configManager.js +2 -2
- package/dist/lib/constants/contextWindows.js +15 -13
- package/dist/lib/constants/enums.d.ts +10 -16
- package/dist/lib/constants/enums.js +12 -18
- package/dist/lib/constants/index.d.ts +0 -10
- package/dist/lib/constants/index.js +1 -1
- package/dist/lib/constants/tokens.d.ts +29 -16
- package/dist/lib/constants/tokens.js +23 -16
- package/dist/lib/core/baseProvider.d.ts +5 -5
- package/dist/lib/core/baseProvider.js +6 -6
- package/dist/lib/core/constants.js +6 -1
- package/dist/lib/core/dynamicModels.js +10 -6
- package/dist/lib/core/evaluationProviders.js +1 -1
- package/dist/lib/core/infrastructure/baseError.d.ts +1 -1
- package/dist/lib/core/infrastructure/baseFactory.d.ts +1 -6
- package/dist/lib/core/infrastructure/baseRegistry.d.ts +6 -5
- package/dist/lib/core/infrastructure/index.d.ts +6 -4
- package/dist/lib/core/infrastructure/index.js +2 -2
- package/dist/lib/core/modelConfiguration.js +3 -1
- package/dist/lib/core/modules/GenerationHandler.d.ts +3 -3
- package/dist/lib/core/modules/GenerationHandler.js +49 -41
- package/dist/lib/core/modules/MessageBuilder.d.ts +5 -5
- package/dist/lib/core/modules/MessageBuilder.js +4 -6
- package/dist/lib/core/modules/StreamHandler.js +26 -12
- package/dist/lib/core/modules/TelemetryHandler.d.ts +4 -6
- package/dist/lib/core/modules/TelemetryHandler.js +7 -6
- package/dist/lib/core/modules/ToolsManager.d.ts +2 -12
- package/dist/lib/core/modules/ToolsManager.js +20 -4
- package/dist/lib/core/modules/Utilities.js +3 -1
- package/dist/lib/core/redisConversationMemoryManager.js +3 -3
- package/dist/lib/core/streamAnalytics.js +23 -9
- package/dist/lib/evaluation/contextBuilder.d.ts +2 -2
- package/dist/lib/evaluation/contextBuilder.js +2 -2
- package/dist/lib/evaluation/index.d.ts +2 -2
- package/dist/lib/evaluation/retryManager.js +1 -1
- package/dist/lib/factories/providerFactory.js +2 -2
- package/dist/lib/features/ppt/constants.js +1 -1
- package/dist/lib/features/ppt/presentationOrchestrator.js +7 -3
- package/dist/lib/features/ppt/slideGenerator.d.ts +2 -1
- package/dist/lib/features/ppt/slideGenerator.js +6 -1
- package/dist/lib/files/fileTools.d.ts +16 -247
- package/dist/lib/files/fileTools.js +16 -15
- package/dist/lib/index.d.ts +5 -3
- package/dist/lib/index.js +20 -3
- package/dist/lib/mcp/batching/requestBatcher.js +1 -1
- package/dist/lib/mcp/externalServerManager.js +5 -2
- package/dist/lib/mcp/factory.js +1 -1
- package/dist/lib/mcp/index.d.ts +1 -1
- package/dist/lib/mcp/index.js +1 -1
- package/dist/lib/mcp/mcpCircuitBreaker.d.ts +1 -0
- package/dist/lib/mcp/mcpCircuitBreaker.js +30 -4
- package/dist/lib/mcp/mcpClientFactory.js +33 -4
- package/dist/lib/mcp/toolDiscoveryService.js +52 -5
- package/dist/lib/mcp/toolRegistry.js +7 -1
- package/dist/lib/memory/memoryRetrievalTools.d.ts +5 -89
- package/dist/lib/memory/memoryRetrievalTools.js +1 -1
- package/dist/lib/middleware/builtin/analytics.js +3 -0
- package/dist/lib/middleware/builtin/autoEvaluation.js +46 -24
- package/dist/lib/middleware/builtin/guardrails.js +4 -0
- package/dist/lib/middleware/builtin/lifecycle.js +10 -6
- package/dist/lib/middleware/factory.d.ts +3 -3
- package/dist/lib/middleware/factory.js +3 -2
- package/dist/lib/middleware/index.d.ts +1 -1
- package/dist/lib/middleware/registry.d.ts +2 -2
- package/dist/lib/middleware/registry.js +1 -0
- package/dist/lib/middleware/utils/guardrailsUtils.d.ts +5 -6
- package/dist/lib/middleware/utils/guardrailsUtils.js +15 -6
- package/dist/lib/neurolink.d.ts +9 -20
- package/dist/lib/neurolink.js +278 -186
- package/dist/lib/observability/retryPolicy.d.ts +2 -13
- package/dist/lib/observability/sampling/samplers.d.ts +2 -11
- package/dist/lib/observability/spanProcessor.d.ts +2 -14
- package/dist/lib/processors/base/BaseFileProcessor.js +1 -1
- package/dist/lib/processors/document/OpenDocumentProcessor.js +5 -3
- package/dist/lib/processors/media/VideoProcessor.js +157 -101
- package/dist/lib/providers/amazonBedrock.js +12 -5
- package/dist/lib/providers/amazonSagemaker.d.ts +5 -5
- package/dist/lib/providers/amazonSagemaker.js +6 -2
- package/dist/lib/providers/anthropic.d.ts +3 -3
- package/dist/lib/providers/anthropic.js +23 -192
- package/dist/lib/providers/anthropicBaseProvider.d.ts +4 -4
- package/dist/lib/providers/anthropicBaseProvider.js +24 -13
- package/dist/lib/providers/azureOpenai.d.ts +2 -2
- package/dist/lib/providers/azureOpenai.js +6 -6
- package/dist/lib/providers/googleAiStudio.d.ts +2 -2
- package/dist/lib/providers/googleAiStudio.js +15 -7
- package/dist/lib/providers/googleNativeGemini3.d.ts +3 -54
- package/dist/lib/providers/googleNativeGemini3.js +14 -10
- package/dist/lib/providers/googleVertex.d.ts +6 -6
- package/dist/lib/providers/googleVertex.js +32 -26
- package/dist/lib/providers/huggingFace.d.ts +4 -4
- package/dist/lib/providers/huggingFace.js +15 -5
- package/dist/lib/providers/litellm.d.ts +4 -4
- package/dist/lib/providers/litellm.js +54 -42
- package/dist/lib/providers/mistral.d.ts +2 -2
- package/dist/lib/providers/mistral.js +5 -4
- package/dist/lib/providers/ollama.d.ts +7 -4
- package/dist/lib/providers/ollama.js +30 -8
- package/dist/lib/providers/openAI.d.ts +2 -2
- package/dist/lib/providers/openAI.js +46 -21
- package/dist/lib/providers/openRouter.d.ts +4 -4
- package/dist/lib/providers/openRouter.js +63 -35
- package/dist/lib/providers/openaiCompatible.d.ts +2 -2
- package/dist/lib/providers/openaiCompatible.js +18 -9
- package/dist/lib/providers/providerTypeUtils.d.ts +28 -0
- package/dist/lib/providers/providerTypeUtils.js +47 -0
- package/dist/lib/providers/sagemaker/config.js +5 -5
- package/dist/lib/providers/sagemaker/language-model.d.ts +23 -13
- package/dist/lib/providers/sagemaker/language-model.js +20 -8
- package/dist/lib/proxy/accountQuota.d.ts +33 -0
- package/dist/lib/proxy/accountQuota.js +163 -0
- package/dist/lib/proxy/claudeFormat.d.ts +143 -0
- package/dist/lib/proxy/claudeFormat.js +596 -0
- package/dist/lib/proxy/cloaking/index.d.ts +44 -0
- package/dist/lib/proxy/cloaking/index.js +87 -0
- package/dist/lib/proxy/cloaking/plugins/headerScrubber.d.ts +9 -0
- package/dist/lib/proxy/cloaking/plugins/headerScrubber.js +87 -0
- package/dist/lib/proxy/cloaking/plugins/sessionIdentity.d.ts +15 -0
- package/dist/lib/proxy/cloaking/plugins/sessionIdentity.js +66 -0
- package/dist/lib/proxy/cloaking/plugins/systemPromptInjector.d.ts +11 -0
- package/dist/lib/proxy/cloaking/plugins/systemPromptInjector.js +84 -0
- package/dist/lib/proxy/cloaking/plugins/tlsFingerprint.d.ts +14 -0
- package/dist/lib/proxy/cloaking/plugins/tlsFingerprint.js +39 -0
- package/dist/lib/proxy/cloaking/plugins/wordObfuscator.d.ts +9 -0
- package/dist/lib/proxy/cloaking/plugins/wordObfuscator.js +122 -0
- package/dist/lib/proxy/cloaking/types.d.ts +1 -0
- package/dist/lib/proxy/cloaking/types.js +2 -0
- package/dist/lib/proxy/modelRouter.d.ts +10 -0
- package/dist/lib/proxy/modelRouter.js +30 -0
- package/dist/lib/proxy/oauthFetch.d.ts +36 -0
- package/dist/lib/proxy/oauthFetch.js +368 -0
- package/dist/lib/proxy/proxyConfig.d.ts +42 -0
- package/dist/lib/proxy/proxyConfig.js +500 -0
- package/dist/lib/proxy/proxyFetch.js +2 -1
- package/dist/lib/proxy/requestLogger.d.ts +50 -0
- package/dist/lib/proxy/requestLogger.js +208 -0
- package/dist/lib/proxy/tokenRefresh.d.ts +4 -0
- package/dist/lib/proxy/tokenRefresh.js +125 -0
- package/dist/lib/proxy/usageStats.d.ts +13 -0
- package/dist/lib/proxy/usageStats.js +75 -0
- package/dist/lib/rag/document/loaders.js +1 -1
- package/dist/lib/rag/pipeline/contextAssembly.d.ts +4 -7
- package/dist/lib/rag/ragIntegration.d.ts +2 -14
- package/dist/lib/rag/ragIntegration.js +1 -1
- package/dist/lib/rag/resilience/CircuitBreaker.d.ts +5 -44
- package/dist/lib/rag/resilience/RetryHandler.js +1 -1
- package/dist/lib/rag/retrieval/vectorQueryTool.d.ts +1 -9
- package/dist/lib/rag/retrieval/vectorQueryTool.js +1 -1
- package/dist/lib/sdk/toolRegistration.js +12 -1
- package/dist/lib/server/abstract/baseServerAdapter.js +2 -2
- package/dist/lib/server/adapters/honoAdapter.d.ts +6 -0
- package/dist/lib/server/adapters/honoAdapter.js +76 -10
- package/dist/lib/server/middleware/cache.js +3 -0
- package/dist/lib/server/routes/claudeProxyRoutes.d.ts +44 -0
- package/dist/lib/server/routes/claudeProxyRoutes.js +1601 -0
- package/dist/lib/server/routes/healthRoutes.js +18 -1
- package/dist/lib/server/routes/index.d.ts +7 -0
- package/dist/lib/server/routes/index.js +8 -0
- package/dist/lib/server/streaming/dataStream.d.ts +1 -5
- package/dist/lib/server/streaming/dataStream.js +3 -0
- package/dist/lib/server/utils/validation.d.ts +24 -124
- package/dist/lib/server/utils/validation.js +2 -2
- package/dist/lib/services/server/ai/observability/instrumentation.js +4 -0
- package/dist/lib/telemetry/attributes.d.ts +38 -0
- package/dist/lib/telemetry/attributes.js +40 -0
- package/dist/lib/telemetry/tracers.d.ts +1 -0
- package/dist/lib/telemetry/tracers.js +1 -0
- package/dist/lib/types/authTypes.d.ts +56 -0
- package/dist/lib/types/authTypes.js +9 -0
- package/dist/lib/types/circuitBreakerErrors.d.ts +30 -0
- package/dist/lib/types/circuitBreakerErrors.js +35 -0
- package/dist/lib/types/cli.d.ts +258 -0
- package/dist/lib/types/clientTypes.d.ts +1050 -0
- package/dist/lib/types/clientTypes.js +11 -0
- package/dist/lib/types/common.d.ts +123 -0
- package/dist/lib/types/configTypes.d.ts +49 -0
- package/dist/lib/types/configTypes.js +4 -0
- package/dist/lib/types/conversation.d.ts +0 -5
- package/dist/lib/types/evaluationTypes.d.ts +2 -2
- package/dist/lib/types/fileTypes.d.ts +47 -0
- package/dist/lib/types/generateTypes.d.ts +7 -3
- package/dist/lib/types/guardrails.d.ts +2 -2
- package/dist/lib/types/index.d.ts +4 -1
- package/dist/lib/types/index.js +5 -0
- package/dist/lib/types/middlewareTypes.d.ts +3 -3
- package/dist/lib/types/modelTypes.d.ts +7 -97
- package/dist/lib/types/modelTypes.js +3 -3
- package/dist/lib/types/observability.d.ts +37 -0
- package/dist/lib/types/providers.d.ts +107 -0
- package/dist/lib/types/proxyTypes.d.ts +536 -0
- package/dist/lib/types/proxyTypes.js +17 -0
- package/dist/lib/types/ragTypes.d.ts +49 -1
- package/dist/lib/types/streamTypes.d.ts +37 -13
- package/dist/lib/types/subscriptionTypes.d.ts +77 -0
- package/dist/lib/types/subscriptionTypes.js +2 -0
- package/dist/lib/types/tools.d.ts +45 -1
- package/dist/lib/types/typeAliases.d.ts +8 -0
- package/dist/lib/types/typeAliases.js +1 -0
- package/dist/lib/utils/async/retry.d.ts +4 -33
- package/dist/lib/utils/asyncMutex.d.ts +14 -0
- package/dist/lib/utils/asyncMutex.js +61 -0
- package/dist/lib/utils/errorHandling.d.ts +2 -1
- package/dist/lib/utils/errorHandling.js +14 -6
- package/dist/lib/utils/fileDetector.d.ts +13 -1
- package/dist/lib/utils/fileDetector.js +114 -32
- package/dist/lib/utils/imageProcessor.js +7 -7
- package/dist/lib/utils/json/safeParse.d.ts +1 -8
- package/dist/lib/utils/mcpDefaults.d.ts +1 -1
- package/dist/lib/utils/mcpDefaults.js +11 -2
- package/dist/lib/utils/messageBuilder.d.ts +5 -5
- package/dist/lib/utils/messageBuilder.js +106 -80
- package/dist/lib/utils/modelChoices.d.ts +1 -8
- package/dist/lib/utils/pdfProcessor.d.ts +1 -25
- package/dist/lib/utils/pdfProcessor.js +5 -4
- package/dist/lib/utils/pricing.js +28 -5
- package/dist/lib/utils/providerHealth.d.ts +1 -1
- package/dist/lib/utils/rateLimiter.d.ts +1 -15
- package/dist/lib/utils/redis.d.ts +1 -1
- package/dist/lib/utils/redis.js +3 -3
- package/dist/lib/utils/sanitizers/filename.d.ts +2 -22
- package/dist/lib/utils/sanitizers/index.d.ts +4 -2
- package/dist/lib/utils/sanitizers/svg.d.ts +1 -11
- package/dist/lib/utils/schemaConversion.js +4 -1
- package/dist/lib/utils/thinkingConfig.d.ts +1 -33
- package/dist/lib/utils/tokenUtils.d.ts +1 -39
- package/dist/lib/utils/videoAnalysisProcessor.d.ts +5 -5
- package/dist/lib/utils/videoAnalysisProcessor.js +2 -2
- package/dist/lib/workflow/config.d.ts +89 -1257
- package/dist/lib/workflow/utils/workflowValidation.js +1 -1
- package/dist/mcp/batching/requestBatcher.js +1 -1
- package/dist/mcp/externalServerManager.js +5 -2
- package/dist/mcp/factory.js +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/mcpCircuitBreaker.d.ts +1 -0
- package/dist/mcp/mcpCircuitBreaker.js +30 -4
- package/dist/mcp/mcpClientFactory.js +33 -4
- package/dist/mcp/toolDiscoveryService.js +52 -5
- package/dist/mcp/toolRegistry.js +7 -1
- package/dist/memory/memoryRetrievalTools.d.ts +5 -89
- package/dist/memory/memoryRetrievalTools.js +1 -1
- package/dist/middleware/builtin/analytics.js +3 -0
- package/dist/middleware/builtin/autoEvaluation.js +46 -24
- package/dist/middleware/builtin/guardrails.js +4 -0
- package/dist/middleware/builtin/lifecycle.js +10 -6
- package/dist/middleware/factory.d.ts +3 -3
- package/dist/middleware/factory.js +3 -2
- package/dist/middleware/index.d.ts +1 -1
- package/dist/middleware/registry.d.ts +2 -2
- package/dist/middleware/registry.js +1 -0
- package/dist/middleware/utils/guardrailsUtils.d.ts +5 -6
- package/dist/middleware/utils/guardrailsUtils.js +15 -6
- package/dist/neurolink.d.ts +9 -20
- package/dist/neurolink.js +278 -186
- package/dist/observability/retryPolicy.d.ts +2 -13
- package/dist/observability/sampling/samplers.d.ts +2 -11
- package/dist/observability/spanProcessor.d.ts +2 -14
- package/dist/processors/base/BaseFileProcessor.js +1 -1
- package/dist/processors/document/OpenDocumentProcessor.js +5 -3
- package/dist/processors/media/VideoProcessor.js +157 -101
- package/dist/providers/amazonBedrock.js +12 -5
- package/dist/providers/amazonSagemaker.d.ts +5 -5
- package/dist/providers/amazonSagemaker.js +6 -2
- package/dist/providers/anthropic.d.ts +3 -3
- package/dist/providers/anthropic.js +23 -192
- package/dist/providers/anthropicBaseProvider.d.ts +4 -4
- package/dist/providers/anthropicBaseProvider.js +24 -13
- package/dist/providers/azureOpenai.d.ts +2 -2
- package/dist/providers/azureOpenai.js +6 -6
- package/dist/providers/googleAiStudio.d.ts +2 -2
- package/dist/providers/googleAiStudio.js +15 -7
- package/dist/providers/googleNativeGemini3.d.ts +3 -54
- package/dist/providers/googleNativeGemini3.js +14 -10
- package/dist/providers/googleVertex.d.ts +6 -6
- package/dist/providers/googleVertex.js +32 -26
- package/dist/providers/huggingFace.d.ts +4 -4
- package/dist/providers/huggingFace.js +15 -5
- package/dist/providers/litellm.d.ts +4 -4
- package/dist/providers/litellm.js +54 -42
- package/dist/providers/mistral.d.ts +2 -2
- package/dist/providers/mistral.js +5 -4
- package/dist/providers/ollama.d.ts +7 -4
- package/dist/providers/ollama.js +30 -8
- package/dist/providers/openAI.d.ts +2 -2
- package/dist/providers/openAI.js +46 -21
- package/dist/providers/openRouter.d.ts +4 -4
- package/dist/providers/openRouter.js +63 -35
- package/dist/providers/openaiCompatible.d.ts +2 -2
- package/dist/providers/openaiCompatible.js +18 -9
- package/dist/providers/providerTypeUtils.d.ts +28 -0
- package/dist/providers/providerTypeUtils.js +46 -0
- package/dist/providers/sagemaker/config.js +5 -5
- package/dist/providers/sagemaker/language-model.d.ts +23 -13
- package/dist/providers/sagemaker/language-model.js +20 -8
- package/dist/proxy/accountQuota.d.ts +33 -0
- package/dist/proxy/accountQuota.js +162 -0
- package/dist/proxy/claudeFormat.d.ts +143 -0
- package/dist/proxy/claudeFormat.js +595 -0
- package/dist/proxy/cloaking/index.d.ts +44 -0
- package/dist/proxy/cloaking/index.js +86 -0
- package/dist/proxy/cloaking/plugins/headerScrubber.d.ts +9 -0
- package/dist/proxy/cloaking/plugins/headerScrubber.js +86 -0
- package/dist/proxy/cloaking/plugins/sessionIdentity.d.ts +15 -0
- package/dist/proxy/cloaking/plugins/sessionIdentity.js +65 -0
- package/dist/proxy/cloaking/plugins/systemPromptInjector.d.ts +11 -0
- package/dist/proxy/cloaking/plugins/systemPromptInjector.js +83 -0
- package/dist/proxy/cloaking/plugins/tlsFingerprint.d.ts +14 -0
- package/dist/proxy/cloaking/plugins/tlsFingerprint.js +38 -0
- package/dist/proxy/cloaking/plugins/wordObfuscator.d.ts +9 -0
- package/dist/proxy/cloaking/plugins/wordObfuscator.js +121 -0
- package/dist/proxy/cloaking/types.d.ts +1 -0
- package/dist/proxy/cloaking/types.js +1 -0
- package/dist/proxy/modelRouter.d.ts +10 -0
- package/dist/proxy/modelRouter.js +29 -0
- package/dist/proxy/oauthFetch.d.ts +36 -0
- package/dist/proxy/oauthFetch.js +367 -0
- package/dist/proxy/proxyConfig.d.ts +42 -0
- package/dist/proxy/proxyConfig.js +499 -0
- package/dist/proxy/proxyFetch.js +2 -1
- package/dist/proxy/requestLogger.d.ts +50 -0
- package/dist/proxy/requestLogger.js +207 -0
- package/dist/proxy/tokenRefresh.d.ts +4 -0
- package/dist/proxy/tokenRefresh.js +124 -0
- package/dist/proxy/usageStats.d.ts +13 -0
- package/dist/proxy/usageStats.js +74 -0
- package/dist/rag/document/loaders.js +1 -1
- package/dist/rag/pipeline/contextAssembly.d.ts +4 -7
- package/dist/rag/ragIntegration.d.ts +2 -14
- package/dist/rag/ragIntegration.js +1 -1
- package/dist/rag/resilience/CircuitBreaker.d.ts +5 -44
- package/dist/rag/resilience/RetryHandler.js +1 -1
- package/dist/rag/retrieval/vectorQueryTool.d.ts +1 -9
- package/dist/rag/retrieval/vectorQueryTool.js +1 -1
- package/dist/sdk/toolRegistration.js +12 -1
- package/dist/server/abstract/baseServerAdapter.js +2 -2
- package/dist/server/adapters/honoAdapter.d.ts +6 -0
- package/dist/server/adapters/honoAdapter.js +76 -10
- package/dist/server/middleware/cache.js +3 -0
- package/dist/server/routes/claudeProxyRoutes.d.ts +44 -0
- package/dist/server/routes/claudeProxyRoutes.js +1600 -0
- package/dist/server/routes/healthRoutes.js +18 -1
- package/dist/server/routes/index.d.ts +7 -0
- package/dist/server/routes/index.js +8 -0
- package/dist/server/streaming/dataStream.d.ts +1 -5
- package/dist/server/streaming/dataStream.js +3 -0
- package/dist/server/utils/validation.d.ts +24 -124
- package/dist/server/utils/validation.js +2 -2
- package/dist/services/server/ai/observability/instrumentation.js +4 -0
- package/dist/telemetry/attributes.d.ts +38 -0
- package/dist/telemetry/attributes.js +40 -0
- package/dist/telemetry/tracers.d.ts +1 -0
- package/dist/telemetry/tracers.js +1 -0
- package/dist/types/authTypes.d.ts +56 -0
- package/dist/types/authTypes.js +8 -0
- package/dist/types/circuitBreakerErrors.d.ts +30 -0
- package/dist/types/circuitBreakerErrors.js +34 -0
- package/dist/types/cli.d.ts +258 -0
- package/dist/types/clientTypes.d.ts +1050 -0
- package/dist/types/clientTypes.js +10 -0
- package/dist/types/common.d.ts +123 -0
- package/dist/types/configTypes.d.ts +49 -0
- package/dist/types/configTypes.js +4 -0
- package/dist/types/conversation.d.ts +0 -5
- package/dist/types/evaluationTypes.d.ts +2 -2
- package/dist/types/fileTypes.d.ts +47 -0
- package/dist/types/generateTypes.d.ts +7 -3
- package/dist/types/guardrails.d.ts +2 -2
- package/dist/types/index.d.ts +4 -1
- package/dist/types/index.js +5 -0
- package/dist/types/middlewareTypes.d.ts +3 -3
- package/dist/types/modelTypes.d.ts +7 -97
- package/dist/types/modelTypes.js +3 -3
- package/dist/types/observability.d.ts +37 -0
- package/dist/types/providers.d.ts +107 -0
- package/dist/types/proxyTypes.d.ts +536 -0
- package/dist/types/proxyTypes.js +16 -0
- package/dist/types/ragTypes.d.ts +49 -1
- package/dist/types/streamTypes.d.ts +37 -13
- package/dist/types/subscriptionTypes.d.ts +77 -0
- package/dist/types/subscriptionTypes.js +2 -0
- package/dist/types/tools.d.ts +45 -1
- package/dist/types/typeAliases.d.ts +8 -0
- package/dist/types/typeAliases.js +1 -0
- package/dist/utils/async/retry.d.ts +4 -33
- package/dist/utils/asyncMutex.d.ts +14 -0
- package/dist/utils/asyncMutex.js +60 -0
- package/dist/utils/errorHandling.d.ts +2 -1
- package/dist/utils/errorHandling.js +14 -6
- package/dist/utils/fileDetector.d.ts +13 -1
- package/dist/utils/fileDetector.js +114 -32
- package/dist/utils/imageProcessor.js +7 -7
- package/dist/utils/json/safeParse.d.ts +1 -8
- package/dist/utils/mcpDefaults.d.ts +1 -1
- package/dist/utils/mcpDefaults.js +11 -2
- package/dist/utils/messageBuilder.d.ts +5 -5
- package/dist/utils/messageBuilder.js +106 -80
- package/dist/utils/modelChoices.d.ts +1 -8
- package/dist/utils/pdfProcessor.d.ts +1 -25
- package/dist/utils/pdfProcessor.js +5 -4
- package/dist/utils/pricing.js +28 -5
- package/dist/utils/rateLimiter.d.ts +1 -15
- package/dist/utils/redis.d.ts +1 -1
- package/dist/utils/redis.js +3 -3
- package/dist/utils/sanitizers/filename.d.ts +2 -22
- package/dist/utils/sanitizers/index.d.ts +4 -2
- package/dist/utils/sanitizers/svg.d.ts +1 -11
- package/dist/utils/schemaConversion.js +4 -1
- package/dist/utils/thinkingConfig.d.ts +1 -33
- package/dist/utils/tokenUtils.d.ts +1 -39
- package/dist/utils/videoAnalysisProcessor.d.ts +5 -5
- package/dist/utils/videoAnalysisProcessor.js +2 -2
- package/dist/workflow/config.d.ts +89 -1257
- package/dist/workflow/utils/workflowValidation.js +1 -1
- package/docs-site/mcp-server/index.js +2 -3
- package/package.json +138 -105
- package/dist/lib/memory/mem0Initializer.d.ts +0 -46
- package/dist/lib/memory/mem0Initializer.js +0 -85
- package/dist/memory/mem0Initializer.d.ts +0 -46
- package/dist/memory/mem0Initializer.js +0 -84
|
@@ -0,0 +1,1254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proxy CLI Commands for NeuroLink
|
|
3
|
+
*
|
|
4
|
+
* Implements commands for managing the Claude multi-account proxy:
|
|
5
|
+
* - neurolink proxy start — Start the proxy server
|
|
6
|
+
* - neurolink proxy status — Show proxy status (accounts, sessions, routing)
|
|
7
|
+
*
|
|
8
|
+
* The proxy creates a NeuroLink instance and builds a Hono app that registers
|
|
9
|
+
* Claude-compatible proxy routes. All requests flow through ctx.neurolink
|
|
10
|
+
* (generate/stream), with an optional ModelRouter for model remapping.
|
|
11
|
+
*/
|
|
12
|
+
import { spawn } from "node:child_process";
|
|
13
|
+
import { homedir } from "node:os";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import chalk from "chalk";
|
|
16
|
+
import ora from "ora";
|
|
17
|
+
import { logger } from "../../lib/utils/logger.js";
|
|
18
|
+
import { formatUptime, isProcessRunning, StateFileManager, } from "../utils/serverUtils.js";
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// STATE MANAGEMENT
|
|
21
|
+
// =============================================================================
|
|
22
|
+
const proxyStateManager = new StateFileManager("proxy-state.json");
|
|
23
|
+
function saveProxyState(state) {
|
|
24
|
+
proxyStateManager.save(state);
|
|
25
|
+
}
|
|
26
|
+
function loadProxyState() {
|
|
27
|
+
return proxyStateManager.load();
|
|
28
|
+
}
|
|
29
|
+
function clearProxyState() {
|
|
30
|
+
proxyStateManager.clear();
|
|
31
|
+
}
|
|
32
|
+
const CLAUDE_SETTINGS_PATH = join(homedir(), ".claude", "settings.json");
|
|
33
|
+
const PLIST_LABEL = "com.neurolink.proxy";
|
|
34
|
+
const PLIST_DIR = join(homedir(), "Library", "LaunchAgents");
|
|
35
|
+
const PLIST_PATH = join(PLIST_DIR, `${PLIST_LABEL}.plist`);
|
|
36
|
+
function sleep(ms) {
|
|
37
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
38
|
+
}
|
|
39
|
+
function getProcessStatus(pid) {
|
|
40
|
+
try {
|
|
41
|
+
process.kill(pid, 0);
|
|
42
|
+
return "running";
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
const code = error.code;
|
|
46
|
+
if (code === "ESRCH") {
|
|
47
|
+
return "not_running";
|
|
48
|
+
}
|
|
49
|
+
if (code === "EPERM") {
|
|
50
|
+
return "unknown";
|
|
51
|
+
}
|
|
52
|
+
return "not_running";
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Check if the launchd service is loaded and actively managing the proxy.
|
|
57
|
+
* Returns true if launchctl reports the service as running.
|
|
58
|
+
*/
|
|
59
|
+
async function isLaunchdManaging() {
|
|
60
|
+
if (process.platform !== "darwin") {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const { execFileSync } = await import("node:child_process");
|
|
65
|
+
const uid = process.getuid?.() ?? 501;
|
|
66
|
+
const output = execFileSync("launchctl", ["print", `gui/${uid}/${PLIST_LABEL}`], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
67
|
+
return /state\s*=\s*running/.test(output);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Attempt to restart the proxy via launchd kickstart.
|
|
75
|
+
* Returns true if the proxy comes back healthy within timeoutMs.
|
|
76
|
+
*/
|
|
77
|
+
async function tryLaunchdRestart(host, port, timeoutMs = 15_000) {
|
|
78
|
+
if (process.platform !== "darwin") {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const { existsSync } = await import("fs");
|
|
83
|
+
if (!existsSync(PLIST_PATH)) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const { execFileSync } = await import("node:child_process");
|
|
92
|
+
const uid = process.getuid?.() ?? 501;
|
|
93
|
+
execFileSync("launchctl", ["kickstart", "-k", `gui/${uid}/${PLIST_LABEL}`], { stdio: "ignore", timeout: 5_000 });
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
const deadline = Date.now() + timeoutMs;
|
|
99
|
+
while (Date.now() < deadline) {
|
|
100
|
+
await sleep(1_000);
|
|
101
|
+
if (await isProxyHealthy(host, port, 2_000)) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
/** Keys we manage in Claude Code's settings.env */
|
|
108
|
+
const PROXY_MANAGED_KEYS = ["ANTHROPIC_BASE_URL", "ENABLE_TOOL_SEARCH"];
|
|
109
|
+
async function setClaudeProxySettings(baseUrl) {
|
|
110
|
+
const fs = await import("fs");
|
|
111
|
+
let settings = {};
|
|
112
|
+
try {
|
|
113
|
+
settings = JSON.parse(fs.readFileSync(CLAUDE_SETTINGS_PATH, "utf8"));
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// file missing/invalid — create fresh settings object
|
|
117
|
+
}
|
|
118
|
+
const env = (settings.env ?? {});
|
|
119
|
+
// Preserve original values so clearClaudeProxySettings can restore them.
|
|
120
|
+
// Only snapshot once — subsequent calls should not overwrite the snapshot.
|
|
121
|
+
const originals = (settings
|
|
122
|
+
.__proxy_original_env ?? {});
|
|
123
|
+
for (const key of PROXY_MANAGED_KEYS) {
|
|
124
|
+
if (!(key in originals)) {
|
|
125
|
+
originals[key] = key in env ? env[key] : null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
settings.__proxy_original_env = originals;
|
|
129
|
+
env.ANTHROPIC_BASE_URL = baseUrl;
|
|
130
|
+
env.ENABLE_TOOL_SEARCH = "true";
|
|
131
|
+
settings.env = env;
|
|
132
|
+
fs.writeFileSync(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2));
|
|
133
|
+
}
|
|
134
|
+
async function clearClaudeProxySettings(expectedBaseUrl) {
|
|
135
|
+
const fs = await import("fs");
|
|
136
|
+
let settings;
|
|
137
|
+
try {
|
|
138
|
+
settings = JSON.parse(fs.readFileSync(CLAUDE_SETTINGS_PATH, "utf8"));
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
const env = settings.env;
|
|
144
|
+
if (!env) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
if (expectedBaseUrl &&
|
|
148
|
+
typeof env.ANTHROPIC_BASE_URL === "string" &&
|
|
149
|
+
env.ANTHROPIC_BASE_URL !== expectedBaseUrl) {
|
|
150
|
+
// User switched to a different proxy URL; do not clobber.
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
const hadBaseUrl = typeof env.ANTHROPIC_BASE_URL === "string";
|
|
154
|
+
const hadToolSearch = env.ENABLE_TOOL_SEARCH === "true";
|
|
155
|
+
// Restore original values if they were saved, otherwise delete the keys
|
|
156
|
+
const originals = (settings
|
|
157
|
+
.__proxy_original_env ?? {});
|
|
158
|
+
for (const key of PROXY_MANAGED_KEYS) {
|
|
159
|
+
const original = originals[key];
|
|
160
|
+
if (original !== undefined && original !== null) {
|
|
161
|
+
// Restore the value that existed before the proxy was started
|
|
162
|
+
env[key] = original;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// Key did not exist before — remove it
|
|
166
|
+
delete env[key];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
delete settings.__proxy_original_env;
|
|
170
|
+
if (Object.keys(env).length === 0) {
|
|
171
|
+
delete settings.env;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
settings.env = env;
|
|
175
|
+
}
|
|
176
|
+
fs.writeFileSync(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2));
|
|
177
|
+
return hadBaseUrl || hadToolSearch;
|
|
178
|
+
}
|
|
179
|
+
async function isProxyHealthy(host, port, timeoutMs) {
|
|
180
|
+
try {
|
|
181
|
+
const response = await fetch(`http://${host}:${port}/health`, {
|
|
182
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
183
|
+
});
|
|
184
|
+
return response.ok;
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function spawnFailOpenGuard(host, port, parentPid) {
|
|
191
|
+
const entryScript = process.argv[1];
|
|
192
|
+
if (!entryScript) {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
const child = spawn(process.execPath, [
|
|
197
|
+
entryScript,
|
|
198
|
+
"proxy",
|
|
199
|
+
"guard",
|
|
200
|
+
"--host",
|
|
201
|
+
host,
|
|
202
|
+
"--port",
|
|
203
|
+
String(port),
|
|
204
|
+
"--parent-pid",
|
|
205
|
+
String(parentPid),
|
|
206
|
+
"--quiet",
|
|
207
|
+
], {
|
|
208
|
+
detached: true,
|
|
209
|
+
stdio: "ignore",
|
|
210
|
+
});
|
|
211
|
+
child.unref();
|
|
212
|
+
return child.pid;
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
logger.debug(`[proxy] failed to start fail-open guard: ${error instanceof Error ? error.message : String(error)}`);
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// =============================================================================
|
|
220
|
+
// STARTUP BANNER
|
|
221
|
+
// =============================================================================
|
|
222
|
+
function printProxyBanner(url, strategy) {
|
|
223
|
+
logger.always("");
|
|
224
|
+
logger.always(chalk.bold.cyan("NeuroLink Claude Proxy"));
|
|
225
|
+
logger.always(chalk.gray("=".repeat(50)));
|
|
226
|
+
logger.always("");
|
|
227
|
+
logger.always(` ${chalk.bold("URL:")} ${chalk.cyan(url)}`);
|
|
228
|
+
logger.always(` ${chalk.bold("Strategy:")} ${chalk.cyan(strategy)}`);
|
|
229
|
+
logger.always(` ${chalk.bold("PID:")} ${chalk.cyan(process.pid)}`);
|
|
230
|
+
logger.always("");
|
|
231
|
+
logger.always(chalk.bold("Endpoints:"));
|
|
232
|
+
logger.always(` ${chalk.blue("POST")} /v1/messages — Proxy to Anthropic`);
|
|
233
|
+
logger.always(` ${chalk.green("GET")} /health — Health check`);
|
|
234
|
+
logger.always(` ${chalk.green("GET")} /status — Detailed status`);
|
|
235
|
+
logger.always("");
|
|
236
|
+
logger.always(chalk.bold("Set in Claude Code:"));
|
|
237
|
+
logger.always(` ${chalk.cyan(`ANTHROPIC_BASE_URL=${url}`)}`);
|
|
238
|
+
logger.always("");
|
|
239
|
+
logger.always(chalk.gray("Press Ctrl+C to stop the proxy"));
|
|
240
|
+
logger.always("");
|
|
241
|
+
}
|
|
242
|
+
export function mapClaudeErrorTypeToStatus(errorType) {
|
|
243
|
+
switch (errorType) {
|
|
244
|
+
case "invalid_request_error":
|
|
245
|
+
return 400;
|
|
246
|
+
case "authentication_error":
|
|
247
|
+
return 401;
|
|
248
|
+
case "permission_error":
|
|
249
|
+
return 403;
|
|
250
|
+
case "not_found_error":
|
|
251
|
+
return 404;
|
|
252
|
+
case "request_too_large":
|
|
253
|
+
return 413;
|
|
254
|
+
case "rate_limit_error":
|
|
255
|
+
return 429;
|
|
256
|
+
case "overloaded_error":
|
|
257
|
+
return 529;
|
|
258
|
+
case "api_error":
|
|
259
|
+
default:
|
|
260
|
+
return 502;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// =============================================================================
|
|
264
|
+
// PROXY START COMMAND
|
|
265
|
+
// =============================================================================
|
|
266
|
+
export const proxyStartCommand = {
|
|
267
|
+
command: "start",
|
|
268
|
+
describe: "Start the Claude multi-account proxy server",
|
|
269
|
+
builder: (yargs) => {
|
|
270
|
+
return yargs
|
|
271
|
+
.option("port", {
|
|
272
|
+
type: "number",
|
|
273
|
+
alias: "p",
|
|
274
|
+
default: 55669,
|
|
275
|
+
description: "Port to listen on",
|
|
276
|
+
})
|
|
277
|
+
.option("host", {
|
|
278
|
+
type: "string",
|
|
279
|
+
alias: "H",
|
|
280
|
+
default: "127.0.0.1",
|
|
281
|
+
description: "Host to bind to",
|
|
282
|
+
})
|
|
283
|
+
.option("strategy", {
|
|
284
|
+
type: "string",
|
|
285
|
+
alias: "s",
|
|
286
|
+
choices: ["round-robin", "fill-first"],
|
|
287
|
+
description: "Account selection strategy for routing requests (default: round-robin)",
|
|
288
|
+
})
|
|
289
|
+
.option("health-interval", {
|
|
290
|
+
type: "number",
|
|
291
|
+
alias: "healthInterval",
|
|
292
|
+
default: 30,
|
|
293
|
+
description: "Health check interval in seconds",
|
|
294
|
+
})
|
|
295
|
+
.option("quiet", {
|
|
296
|
+
type: "boolean",
|
|
297
|
+
alias: "q",
|
|
298
|
+
default: false,
|
|
299
|
+
description: "Suppress non-essential output",
|
|
300
|
+
})
|
|
301
|
+
.option("debug", {
|
|
302
|
+
type: "boolean",
|
|
303
|
+
alias: "d",
|
|
304
|
+
default: false,
|
|
305
|
+
description: "Enable debug output",
|
|
306
|
+
})
|
|
307
|
+
.option("config", {
|
|
308
|
+
type: "string",
|
|
309
|
+
alias: "c",
|
|
310
|
+
description: "Path to proxy config file (YAML/JSON)",
|
|
311
|
+
defaultDescription: "~/.neurolink/proxy-config.yaml",
|
|
312
|
+
})
|
|
313
|
+
.example("neurolink proxy start", "Start proxy on default port 55669 with round-robin strategy")
|
|
314
|
+
.example("neurolink proxy start -p 8080 -s round-robin", "Start proxy on port 8080 with round-robin")
|
|
315
|
+
.example("neurolink proxy start --health-interval 60", "Start proxy with 60-second health checks");
|
|
316
|
+
},
|
|
317
|
+
handler: async (argv) => {
|
|
318
|
+
const spinner = argv.quiet ? null : ora("Starting Claude proxy...").start();
|
|
319
|
+
try {
|
|
320
|
+
// Guard: proxy already running
|
|
321
|
+
const existingState = loadProxyState();
|
|
322
|
+
if (existingState && isProcessRunning(existingState.pid)) {
|
|
323
|
+
if (spinner) {
|
|
324
|
+
spinner.fail(chalk.red(`Proxy already running on port ${existingState.port} (PID: ${existingState.pid})`));
|
|
325
|
+
}
|
|
326
|
+
logger.always(chalk.yellow("Stop it first or use 'neurolink proxy status' to inspect"));
|
|
327
|
+
process.exit(1);
|
|
328
|
+
}
|
|
329
|
+
// Guard: launchd is managing the service — don't start manually
|
|
330
|
+
if (await isLaunchdManaging()) {
|
|
331
|
+
if (spinner) {
|
|
332
|
+
spinner.fail(chalk.red("Proxy is managed by launchd. Manual start would cause port conflicts."));
|
|
333
|
+
}
|
|
334
|
+
logger.always(chalk.yellow("Use 'neurolink proxy uninstall' to remove the service first, " +
|
|
335
|
+
"or 'launchctl kickstart gui/$(id -u)/com.neurolink.proxy' to restart."));
|
|
336
|
+
process.exit(1);
|
|
337
|
+
}
|
|
338
|
+
// -----------------------------------------------------------------
|
|
339
|
+
// 1. Create NeuroLink instance — reads all env vars automatically
|
|
340
|
+
// -----------------------------------------------------------------
|
|
341
|
+
// Skip MCP initialization for proxy — tools come from Claude Code, not MCP servers
|
|
342
|
+
process.env.NEUROLINK_SKIP_MCP = "true";
|
|
343
|
+
const { NeuroLink } = await import("../../lib/neurolink.js");
|
|
344
|
+
const neurolink = new NeuroLink();
|
|
345
|
+
// Initialize request logger and usage stats
|
|
346
|
+
const { initRequestLogger, cleanupLogs } = await import("../../lib/proxy/requestLogger.js");
|
|
347
|
+
const { getStats: _getStats, resetStats: _resetStats } = await import("../../lib/proxy/usageStats.js");
|
|
348
|
+
initRequestLogger(true);
|
|
349
|
+
cleanupLogs(7, 500); // Delete logs older than 7 days or if total exceeds 500 MB
|
|
350
|
+
// -----------------------------------------------------------------
|
|
351
|
+
// 2. Load proxy config file (if --config or default exists)
|
|
352
|
+
// -----------------------------------------------------------------
|
|
353
|
+
const configPath = argv.config ?? join(homedir(), ".neurolink", "proxy-config.yaml");
|
|
354
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
355
|
+
let proxyConfig = null;
|
|
356
|
+
try {
|
|
357
|
+
const { loadProxyConfig } = await import("../../lib/proxy/proxyConfig.js");
|
|
358
|
+
proxyConfig = await loadProxyConfig(configPath);
|
|
359
|
+
if (spinner) {
|
|
360
|
+
spinner.text = `Loaded proxy config from ${configPath}`;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
catch (configError) {
|
|
364
|
+
if (argv.config) {
|
|
365
|
+
if (spinner) {
|
|
366
|
+
spinner.fail(chalk.red(`Failed to load proxy config: ${configPath}`));
|
|
367
|
+
}
|
|
368
|
+
process.exit(1);
|
|
369
|
+
}
|
|
370
|
+
// Only silently ignore file-not-found for the default config path.
|
|
371
|
+
// Log a warning for other errors (parse failures, permission issues, etc.)
|
|
372
|
+
const isNotFound = configError instanceof Error &&
|
|
373
|
+
"code" in configError &&
|
|
374
|
+
configError.code === "ENOENT";
|
|
375
|
+
if (!isNotFound) {
|
|
376
|
+
logger.warn(`[proxy] Ignoring default config ${configPath}: ${configError instanceof Error ? configError.message : String(configError)}`);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
// -----------------------------------------------------------------
|
|
380
|
+
// 3. Create ModelRouter from config (if routing configured)
|
|
381
|
+
// -----------------------------------------------------------------
|
|
382
|
+
const strategy = argv.strategy ?? proxyConfig?.routing?.strategy ?? "round-robin";
|
|
383
|
+
let modelRouter;
|
|
384
|
+
if (proxyConfig?.routing) {
|
|
385
|
+
const { ModelRouter } = await import("../../lib/proxy/modelRouter.js");
|
|
386
|
+
modelRouter = new ModelRouter({
|
|
387
|
+
strategy: strategy,
|
|
388
|
+
modelMappings: proxyConfig.routing.modelMappings ?? [],
|
|
389
|
+
fallbackChain: proxyConfig.routing.fallbackChain ?? [],
|
|
390
|
+
passthroughModels: proxyConfig.routing.passthroughModels,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
if (spinner) {
|
|
394
|
+
spinner.text = "Configuring server...";
|
|
395
|
+
}
|
|
396
|
+
// -----------------------------------------------------------------
|
|
397
|
+
// 4. Build Hono app with Claude proxy routes and NeuroLink context
|
|
398
|
+
// -----------------------------------------------------------------
|
|
399
|
+
const { createClaudeProxyRoutes } = await import("../../lib/server/routes/claudeProxyRoutes.js");
|
|
400
|
+
const { Hono } = await import("hono");
|
|
401
|
+
const { serve } = await import("@hono/node-server");
|
|
402
|
+
const app = new Hono();
|
|
403
|
+
app.onError((err, c) => {
|
|
404
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
405
|
+
logger.always(`[proxy] unhandled error: ${errMsg}`);
|
|
406
|
+
if (err instanceof Error && err.stack) {
|
|
407
|
+
logger.debug(`[proxy] stack: ${err.stack}`);
|
|
408
|
+
}
|
|
409
|
+
return c.json({
|
|
410
|
+
type: "error",
|
|
411
|
+
error: {
|
|
412
|
+
type: "api_error",
|
|
413
|
+
message: `Proxy internal error: ${errMsg}`,
|
|
414
|
+
},
|
|
415
|
+
}, 502);
|
|
416
|
+
});
|
|
417
|
+
const routeGroup = createClaudeProxyRoutes(modelRouter, "", strategy);
|
|
418
|
+
// Register proxy routes — inject NeuroLink into ServerContext
|
|
419
|
+
for (const route of routeGroup.routes) {
|
|
420
|
+
const method = route.method.toLowerCase();
|
|
421
|
+
app[method](route.path, async (c) => {
|
|
422
|
+
const emptyBody = {};
|
|
423
|
+
const body = method === "post"
|
|
424
|
+
? await c.req.json().catch(() => emptyBody)
|
|
425
|
+
: undefined;
|
|
426
|
+
// Log incoming request
|
|
427
|
+
const model = body?.model ?? "-";
|
|
428
|
+
const stream = body?.stream
|
|
429
|
+
? "stream"
|
|
430
|
+
: "non-stream";
|
|
431
|
+
const bodyRec = body;
|
|
432
|
+
const toolCount = Array.isArray(bodyRec?.tools)
|
|
433
|
+
? bodyRec.tools.length
|
|
434
|
+
: 0;
|
|
435
|
+
logger.always(`[proxy] ${c.req.method} ${c.req.path} → model=${model} ${stream} tools=${toolCount}`);
|
|
436
|
+
// Build ServerContext with the real NeuroLink instance
|
|
437
|
+
const ctx = {
|
|
438
|
+
requestId: crypto.randomUUID(),
|
|
439
|
+
method: c.req.method,
|
|
440
|
+
path: c.req.path,
|
|
441
|
+
headers: Object.fromEntries(c.req.raw.headers.entries()),
|
|
442
|
+
query: Object.fromEntries(new URL(c.req.url).searchParams.entries()),
|
|
443
|
+
params: c.req.param(),
|
|
444
|
+
body,
|
|
445
|
+
neurolink, // NeuroLink instance for generate/stream
|
|
446
|
+
toolRegistry: neurolink.getToolRegistry(),
|
|
447
|
+
timestamp: Date.now(),
|
|
448
|
+
metadata: {},
|
|
449
|
+
};
|
|
450
|
+
const result = await route.handler(ctx);
|
|
451
|
+
// Handle raw Response objects (passthrough streaming from upstream)
|
|
452
|
+
if (result instanceof Response) {
|
|
453
|
+
return result;
|
|
454
|
+
}
|
|
455
|
+
// Handle streaming response (async iterable)
|
|
456
|
+
if (result &&
|
|
457
|
+
typeof result === "object" &&
|
|
458
|
+
Symbol.asyncIterator in Object(result)) {
|
|
459
|
+
const iterator = result[Symbol.asyncIterator]();
|
|
460
|
+
let cancelled = false;
|
|
461
|
+
const stream = new ReadableStream({
|
|
462
|
+
async start(controller) {
|
|
463
|
+
try {
|
|
464
|
+
while (!cancelled) {
|
|
465
|
+
const { value, done } = await iterator.next();
|
|
466
|
+
if (done) {
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
controller.enqueue(new TextEncoder().encode(value));
|
|
470
|
+
}
|
|
471
|
+
controller.close();
|
|
472
|
+
}
|
|
473
|
+
catch (streamErr) {
|
|
474
|
+
if (cancelled) {
|
|
475
|
+
// Client disconnected — just close
|
|
476
|
+
controller.close();
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
// Emit an SSE error frame so the client gets a meaningful
|
|
480
|
+
// error instead of a silent EOF / connection drop.
|
|
481
|
+
const errMsg = streamErr instanceof Error
|
|
482
|
+
? streamErr.message
|
|
483
|
+
: String(streamErr);
|
|
484
|
+
const errorEvent = `event: error\ndata: ${JSON.stringify({ type: "error", error: { type: "api_error", message: `Stream interrupted: ${errMsg}` } })}\n\n`;
|
|
485
|
+
try {
|
|
486
|
+
controller.enqueue(new TextEncoder().encode(errorEvent));
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
// Controller already errored — ignore
|
|
490
|
+
}
|
|
491
|
+
controller.close();
|
|
492
|
+
}
|
|
493
|
+
},
|
|
494
|
+
async cancel() {
|
|
495
|
+
cancelled = true;
|
|
496
|
+
await iterator.return?.();
|
|
497
|
+
},
|
|
498
|
+
});
|
|
499
|
+
return new Response(stream, {
|
|
500
|
+
headers: {
|
|
501
|
+
"Content-Type": "text/event-stream",
|
|
502
|
+
"Cache-Control": "no-cache",
|
|
503
|
+
Connection: "keep-alive",
|
|
504
|
+
},
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
// Handle error responses with httpStatus field
|
|
508
|
+
if (result &&
|
|
509
|
+
typeof result === "object" &&
|
|
510
|
+
"httpStatus" in result) {
|
|
511
|
+
const httpResult = result;
|
|
512
|
+
const status = httpResult.httpStatus ?? 200;
|
|
513
|
+
delete httpResult.httpStatus;
|
|
514
|
+
return c.json(result, status);
|
|
515
|
+
}
|
|
516
|
+
// Handle Anthropic-style error responses
|
|
517
|
+
if (result &&
|
|
518
|
+
typeof result === "object" &&
|
|
519
|
+
"type" in result &&
|
|
520
|
+
result.type === "error") {
|
|
521
|
+
const errorResult = result;
|
|
522
|
+
const status = mapClaudeErrorTypeToStatus(errorResult.error?.type);
|
|
523
|
+
return c.json(result, status);
|
|
524
|
+
}
|
|
525
|
+
return c.json(result ?? {});
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
// Health endpoint
|
|
529
|
+
app.get("/health", (c) => c.json({
|
|
530
|
+
status: "ok",
|
|
531
|
+
strategy,
|
|
532
|
+
uptime: process.uptime(),
|
|
533
|
+
}));
|
|
534
|
+
// Status endpoint (detailed)
|
|
535
|
+
app.get("/status", async (c) => {
|
|
536
|
+
const { getStats } = await import("../../lib/proxy/usageStats.js");
|
|
537
|
+
const stats = getStats();
|
|
538
|
+
return c.json({
|
|
539
|
+
status: "running",
|
|
540
|
+
pid: process.pid,
|
|
541
|
+
port,
|
|
542
|
+
host,
|
|
543
|
+
strategy,
|
|
544
|
+
uptime: process.uptime(),
|
|
545
|
+
stats: {
|
|
546
|
+
totalRequests: stats.totalRequests,
|
|
547
|
+
totalSuccess: stats.totalSuccess,
|
|
548
|
+
totalErrors: stats.totalErrors,
|
|
549
|
+
totalRateLimits: stats.totalRateLimits,
|
|
550
|
+
accounts: Object.values(stats.accounts).map((a) => ({
|
|
551
|
+
label: a.label,
|
|
552
|
+
type: a.type,
|
|
553
|
+
requests: a.requestCount,
|
|
554
|
+
success: a.successCount,
|
|
555
|
+
errors: a.errorCount,
|
|
556
|
+
rateLimits: a.rateLimitCount,
|
|
557
|
+
backoffLevel: a.currentBackoffLevel,
|
|
558
|
+
cooling: a.coolingUntil ? a.coolingUntil > Date.now() : false,
|
|
559
|
+
})),
|
|
560
|
+
},
|
|
561
|
+
config: proxyConfig ? { hasRouting: !!proxyConfig.routing } : null,
|
|
562
|
+
});
|
|
563
|
+
});
|
|
564
|
+
// -----------------------------------------------------------------
|
|
565
|
+
// 5. Start listening
|
|
566
|
+
// -----------------------------------------------------------------
|
|
567
|
+
const port = argv.port ?? 55669;
|
|
568
|
+
const host = argv.host ?? "127.0.0.1";
|
|
569
|
+
if (spinner) {
|
|
570
|
+
spinner.text = `Starting proxy on ${host}:${port}...`;
|
|
571
|
+
}
|
|
572
|
+
const server = serve({
|
|
573
|
+
fetch: app.fetch,
|
|
574
|
+
port,
|
|
575
|
+
hostname: host,
|
|
576
|
+
});
|
|
577
|
+
const guardPid = spawnFailOpenGuard(host, port, process.pid);
|
|
578
|
+
// Extract fallback chain from proxy config (if available)
|
|
579
|
+
const fallbackChain = proxyConfig?.routing?.fallbackChain?.map((e) => ({
|
|
580
|
+
provider: e.provider,
|
|
581
|
+
model: e.model,
|
|
582
|
+
}));
|
|
583
|
+
// Persist state (including fallback chain for `proxy status`)
|
|
584
|
+
const state = {
|
|
585
|
+
pid: process.pid,
|
|
586
|
+
port,
|
|
587
|
+
host,
|
|
588
|
+
strategy,
|
|
589
|
+
startTime: new Date().toISOString(),
|
|
590
|
+
fallbackChain,
|
|
591
|
+
guardPid,
|
|
592
|
+
managedBy: "manual",
|
|
593
|
+
};
|
|
594
|
+
saveProxyState(state);
|
|
595
|
+
if (spinner) {
|
|
596
|
+
spinner.succeed(chalk.green("Claude proxy started successfully"));
|
|
597
|
+
}
|
|
598
|
+
const normalizedHost = host === "0.0.0.0" ? "localhost" : host;
|
|
599
|
+
const url = `http://${normalizedHost}:${port}`;
|
|
600
|
+
printProxyBanner(url, strategy);
|
|
601
|
+
// Auto-configure Claude Code — use the normalized URL (localhost, not 0.0.0.0)
|
|
602
|
+
try {
|
|
603
|
+
await setClaudeProxySettings(url);
|
|
604
|
+
logger.always(chalk.green(" ✓ Auto-configured Claude Code settings"));
|
|
605
|
+
logger.always(chalk.dim(" Restart Claude Code to connect through proxy"));
|
|
606
|
+
}
|
|
607
|
+
catch (e) {
|
|
608
|
+
logger.debug("[proxy] Failed to auto-configure Claude Code: " +
|
|
609
|
+
(e instanceof Error ? e.message : String(e)));
|
|
610
|
+
}
|
|
611
|
+
// -----------------------------------------------------------------
|
|
612
|
+
// 6. Background token refresh (every 30 seconds)
|
|
613
|
+
// -----------------------------------------------------------------
|
|
614
|
+
const { needsRefresh, refreshToken, persistTokens } = await import("../../lib/proxy/tokenRefresh.js");
|
|
615
|
+
const { tokenStore } = await import("../../lib/auth/tokenStore.js");
|
|
616
|
+
const refreshInterval = setInterval(async () => {
|
|
617
|
+
// Refresh token-pool accounts
|
|
618
|
+
try {
|
|
619
|
+
const allKeys = await tokenStore.listProviders();
|
|
620
|
+
const anthropicKeys = allKeys.filter((k) => k.startsWith("anthropic:"));
|
|
621
|
+
for (const key of anthropicKeys) {
|
|
622
|
+
try {
|
|
623
|
+
const tokens = await tokenStore.loadTokens(key);
|
|
624
|
+
if (!tokens) {
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
const account = {
|
|
628
|
+
label: key,
|
|
629
|
+
token: tokens.accessToken,
|
|
630
|
+
refreshToken: tokens.refreshToken,
|
|
631
|
+
expiresAt: tokens.expiresAt,
|
|
632
|
+
};
|
|
633
|
+
if (needsRefresh(account)) {
|
|
634
|
+
const result = await refreshToken(account);
|
|
635
|
+
if (result.success) {
|
|
636
|
+
await persistTokens({ providerKey: key }, account);
|
|
637
|
+
logger.debug(`[proxy] background token refresh succeeded for ${key}`);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
catch {
|
|
642
|
+
/* non-fatal per-account */
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
catch {
|
|
647
|
+
/* non-fatal */
|
|
648
|
+
}
|
|
649
|
+
// Refresh legacy credentials file
|
|
650
|
+
try {
|
|
651
|
+
const credPath = join(homedir(), ".neurolink", "anthropic-credentials.json");
|
|
652
|
+
const { readFileSync } = await import("fs");
|
|
653
|
+
const creds = JSON.parse(readFileSync(credPath, "utf8"));
|
|
654
|
+
if (creds.oauth) {
|
|
655
|
+
const account = {
|
|
656
|
+
label: "background",
|
|
657
|
+
token: creds.oauth.accessToken,
|
|
658
|
+
refreshToken: creds.oauth.refreshToken,
|
|
659
|
+
expiresAt: creds.oauth.expiresAt,
|
|
660
|
+
};
|
|
661
|
+
if (needsRefresh(account)) {
|
|
662
|
+
const result = await refreshToken(account);
|
|
663
|
+
if (result.success) {
|
|
664
|
+
await persistTokens(credPath, account);
|
|
665
|
+
logger.debug("[proxy] background token refresh succeeded");
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
catch {
|
|
671
|
+
/* non-fatal */
|
|
672
|
+
}
|
|
673
|
+
}, 30_000);
|
|
674
|
+
// Hourly log cleanup
|
|
675
|
+
const logCleanupInterval = setInterval(() => {
|
|
676
|
+
cleanupLogs(7, 500);
|
|
677
|
+
}, 60 * 60 * 1000);
|
|
678
|
+
// -----------------------------------------------------------------
|
|
679
|
+
// 7. Graceful shutdown
|
|
680
|
+
// -----------------------------------------------------------------
|
|
681
|
+
const shutdown = async (signal) => {
|
|
682
|
+
clearInterval(refreshInterval);
|
|
683
|
+
clearInterval(logCleanupInterval);
|
|
684
|
+
logger.always(`\nShutting down proxy (${signal})...`);
|
|
685
|
+
// Only clear Claude settings on user-initiated stop (SIGINT).
|
|
686
|
+
// On SIGTERM (launchd restart cycle), leave settings intact so
|
|
687
|
+
// the restarted proxy picks up seamlessly.
|
|
688
|
+
if (signal === "SIGINT") {
|
|
689
|
+
try {
|
|
690
|
+
const shutdownHost = host === "0.0.0.0" ? "localhost" : host;
|
|
691
|
+
await clearClaudeProxySettings(`http://${shutdownHost}:${port}`);
|
|
692
|
+
}
|
|
693
|
+
catch {
|
|
694
|
+
/* non-fatal */
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
try {
|
|
698
|
+
if (server &&
|
|
699
|
+
typeof server.close === "function") {
|
|
700
|
+
server.close();
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
catch {
|
|
704
|
+
// Best-effort close
|
|
705
|
+
}
|
|
706
|
+
clearProxyState();
|
|
707
|
+
// SIGINT = user pressed Ctrl+C → exit 0 (launchd won't restart)
|
|
708
|
+
// SIGTERM = launchd/system stop → exit 1 (launchd WILL restart)
|
|
709
|
+
process.exit(signal === "SIGINT" ? 0 : 1);
|
|
710
|
+
};
|
|
711
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
712
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
713
|
+
}
|
|
714
|
+
catch (error) {
|
|
715
|
+
if (spinner) {
|
|
716
|
+
spinner.fail(chalk.red("Failed to start proxy"));
|
|
717
|
+
}
|
|
718
|
+
logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
719
|
+
if (argv.debug && error instanceof Error && error.stack) {
|
|
720
|
+
logger.error(chalk.gray(error.stack));
|
|
721
|
+
}
|
|
722
|
+
process.exit(1);
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
};
|
|
726
|
+
function printStatusStats(stats) {
|
|
727
|
+
console.info(`\n Stats:`);
|
|
728
|
+
console.info(` Requests: ${stats.totalRequests} total, ${stats.totalSuccess} success, ${stats.totalErrors} errors`);
|
|
729
|
+
console.info(` Rate limits: ${stats.totalRateLimits}`);
|
|
730
|
+
if (stats.accounts?.length) {
|
|
731
|
+
console.info(`\n Accounts:`);
|
|
732
|
+
for (const a of stats.accounts) {
|
|
733
|
+
const acctStatus = a.cooling
|
|
734
|
+
? chalk.red("cooling")
|
|
735
|
+
: chalk.green("active");
|
|
736
|
+
console.info(` ${a.label.padEnd(20)} ${a.type.padEnd(8)} ${String(a.requests).padEnd(6)} reqs ${acctStatus}`);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
// =============================================================================
|
|
741
|
+
// PROXY STATUS COMMAND
|
|
742
|
+
// =============================================================================
|
|
743
|
+
export const proxyStatusCommand = {
|
|
744
|
+
command: "status",
|
|
745
|
+
describe: "Show Claude proxy status",
|
|
746
|
+
builder: (yargs) => {
|
|
747
|
+
return yargs
|
|
748
|
+
.option("format", {
|
|
749
|
+
type: "string",
|
|
750
|
+
choices: ["text", "json"],
|
|
751
|
+
default: "text",
|
|
752
|
+
description: "Output format",
|
|
753
|
+
})
|
|
754
|
+
.option("quiet", {
|
|
755
|
+
type: "boolean",
|
|
756
|
+
alias: "q",
|
|
757
|
+
default: false,
|
|
758
|
+
description: "Suppress non-essential output",
|
|
759
|
+
})
|
|
760
|
+
.example("neurolink proxy status", "Show proxy status")
|
|
761
|
+
.example("neurolink proxy status --format json", "Show proxy status as JSON");
|
|
762
|
+
},
|
|
763
|
+
handler: async (argv) => {
|
|
764
|
+
try {
|
|
765
|
+
const state = loadProxyState();
|
|
766
|
+
const status = {
|
|
767
|
+
running: false,
|
|
768
|
+
pid: null,
|
|
769
|
+
port: null,
|
|
770
|
+
host: null,
|
|
771
|
+
strategy: null,
|
|
772
|
+
uptime: null,
|
|
773
|
+
startTime: null,
|
|
774
|
+
url: null,
|
|
775
|
+
fallbackChain: null,
|
|
776
|
+
};
|
|
777
|
+
if (state && isProcessRunning(state.pid)) {
|
|
778
|
+
status.running = true;
|
|
779
|
+
status.pid = state.pid;
|
|
780
|
+
status.port = state.port;
|
|
781
|
+
status.host = state.host;
|
|
782
|
+
status.strategy = state.strategy;
|
|
783
|
+
status.startTime = state.startTime;
|
|
784
|
+
status.uptime = Date.now() - new Date(state.startTime).getTime();
|
|
785
|
+
status.url = `http://${state.host === "0.0.0.0" ? "localhost" : state.host}:${state.port}`;
|
|
786
|
+
status.fallbackChain = state.fallbackChain ?? null;
|
|
787
|
+
}
|
|
788
|
+
if (argv.format === "json") {
|
|
789
|
+
logger.always(JSON.stringify(status, null, 2));
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
// Text format
|
|
793
|
+
logger.always("");
|
|
794
|
+
logger.always(chalk.bold.cyan("NeuroLink Claude Proxy Status"));
|
|
795
|
+
logger.always(chalk.gray("=".repeat(50)));
|
|
796
|
+
logger.always("");
|
|
797
|
+
if (status.running) {
|
|
798
|
+
logger.always(` ${chalk.bold("Status:")} ${chalk.green("RUNNING")}`);
|
|
799
|
+
logger.always(` ${chalk.bold("PID:")} ${chalk.cyan(status.pid)}`);
|
|
800
|
+
logger.always(` ${chalk.bold("URL:")} ${chalk.cyan(status.url)}`);
|
|
801
|
+
logger.always(` ${chalk.bold("Strategy:")} ${chalk.cyan(status.strategy)}`);
|
|
802
|
+
logger.always(` ${chalk.bold("Started:")} ${chalk.cyan(status.startTime)}`);
|
|
803
|
+
logger.always(` ${chalk.bold("Uptime:")} ${chalk.cyan(formatUptime(status.uptime ?? 0))}`);
|
|
804
|
+
// Display fallback chain if configured
|
|
805
|
+
if (status.fallbackChain && status.fallbackChain.length > 0) {
|
|
806
|
+
logger.always("");
|
|
807
|
+
logger.always(chalk.bold(" Fallback Chain:"));
|
|
808
|
+
for (let i = 0; i < status.fallbackChain.length; i++) {
|
|
809
|
+
const entry = status.fallbackChain[i];
|
|
810
|
+
const prefix = i === status.fallbackChain.length - 1 ? "└─" : "├─";
|
|
811
|
+
logger.always(` ${chalk.gray(prefix)} ${chalk.cyan(entry.provider)}/${chalk.cyan(entry.model)}`);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
// Try to fetch live status from the running proxy
|
|
815
|
+
try {
|
|
816
|
+
const response = await fetch(`${status.url}/health`);
|
|
817
|
+
if (response.ok) {
|
|
818
|
+
const liveStatus = (await response.json());
|
|
819
|
+
logger.always("");
|
|
820
|
+
logger.always(` ${chalk.bold("Live:")} ${chalk.green(liveStatus.status)}`);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
catch {
|
|
824
|
+
// Live status fetch failed — show only persisted state
|
|
825
|
+
logger.always("");
|
|
826
|
+
logger.always(chalk.gray(" (Could not reach proxy for live status)"));
|
|
827
|
+
}
|
|
828
|
+
// Try to get detailed stats
|
|
829
|
+
try {
|
|
830
|
+
const liveUrl = status.url;
|
|
831
|
+
const statusResp = await fetch(`${liveUrl}/status`);
|
|
832
|
+
if (statusResp.ok) {
|
|
833
|
+
const statusData = (await statusResp.json());
|
|
834
|
+
if (statusData.stats) {
|
|
835
|
+
printStatusStats(statusData.stats);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
catch {
|
|
840
|
+
/* non-fatal */
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
else {
|
|
844
|
+
logger.always(` ${chalk.bold("Status:")} ${chalk.yellow("NOT RUNNING")}`);
|
|
845
|
+
logger.always("");
|
|
846
|
+
logger.always(chalk.gray(" Start the proxy with: neurolink proxy start"));
|
|
847
|
+
}
|
|
848
|
+
logger.always("");
|
|
849
|
+
}
|
|
850
|
+
catch (error) {
|
|
851
|
+
logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
852
|
+
process.exit(1);
|
|
853
|
+
}
|
|
854
|
+
},
|
|
855
|
+
};
|
|
856
|
+
// =============================================================================
|
|
857
|
+
// PROXY FAIL-OPEN GUARD COMMAND (HIDDEN)
|
|
858
|
+
// =============================================================================
|
|
859
|
+
export const proxyGuardCommand = {
|
|
860
|
+
command: "guard",
|
|
861
|
+
describe: false,
|
|
862
|
+
builder: (yargs) => {
|
|
863
|
+
return yargs
|
|
864
|
+
.option("host", {
|
|
865
|
+
type: "string",
|
|
866
|
+
default: "127.0.0.1",
|
|
867
|
+
})
|
|
868
|
+
.option("port", {
|
|
869
|
+
type: "number",
|
|
870
|
+
default: 55669,
|
|
871
|
+
})
|
|
872
|
+
.option("parent-pid", {
|
|
873
|
+
type: "number",
|
|
874
|
+
alias: "parentPid",
|
|
875
|
+
})
|
|
876
|
+
.option("max-wait-ms", {
|
|
877
|
+
type: "number",
|
|
878
|
+
alias: "maxWaitMs",
|
|
879
|
+
default: 0,
|
|
880
|
+
})
|
|
881
|
+
.option("failure-threshold", {
|
|
882
|
+
type: "number",
|
|
883
|
+
alias: "failureThreshold",
|
|
884
|
+
default: 5,
|
|
885
|
+
})
|
|
886
|
+
.option("poll-interval-ms", {
|
|
887
|
+
type: "number",
|
|
888
|
+
alias: "pollIntervalMs",
|
|
889
|
+
default: 1_000,
|
|
890
|
+
})
|
|
891
|
+
.option("quiet", {
|
|
892
|
+
type: "boolean",
|
|
893
|
+
default: true,
|
|
894
|
+
});
|
|
895
|
+
},
|
|
896
|
+
handler: async (argv) => {
|
|
897
|
+
const host = argv.host ?? "127.0.0.1";
|
|
898
|
+
const port = argv.port ?? 55669;
|
|
899
|
+
const parentPid = Number(argv.parentPid);
|
|
900
|
+
const maxWaitMsArg = Number(argv.maxWaitMs ?? 0);
|
|
901
|
+
const maxWaitMs = Number.isFinite(maxWaitMsArg) && maxWaitMsArg > 0
|
|
902
|
+
? Math.max(1_000, maxWaitMsArg)
|
|
903
|
+
: 0;
|
|
904
|
+
const failureThreshold = Math.max(1, Number(argv.failureThreshold ?? 5));
|
|
905
|
+
const pollIntervalMs = Math.max(250, Number(argv.pollIntervalMs ?? 1_000));
|
|
906
|
+
if (!Number.isFinite(parentPid) || parentPid <= 0) {
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
const startedAt = Date.now();
|
|
910
|
+
let parentStatus = getProcessStatus(parentPid);
|
|
911
|
+
let consecutiveUnhealthy = 0;
|
|
912
|
+
// Keep monitoring for as long as the parent can affect Claude settings.
|
|
913
|
+
while (true) {
|
|
914
|
+
const healthy = await isProxyHealthy(host, port, 1_500);
|
|
915
|
+
if (healthy) {
|
|
916
|
+
consecutiveUnhealthy = 0;
|
|
917
|
+
}
|
|
918
|
+
else {
|
|
919
|
+
consecutiveUnhealthy += 1;
|
|
920
|
+
}
|
|
921
|
+
if (parentStatus === "not_running") {
|
|
922
|
+
// Parent is gone. If endpoint is still healthy, another proxy took over.
|
|
923
|
+
if (healthy) {
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
break;
|
|
927
|
+
}
|
|
928
|
+
if (!healthy && consecutiveUnhealthy >= failureThreshold) {
|
|
929
|
+
// Parent still exists but endpoint is repeatedly unhealthy.
|
|
930
|
+
break;
|
|
931
|
+
}
|
|
932
|
+
if (maxWaitMs > 0 && Date.now() - startedAt >= maxWaitMs) {
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
await sleep(pollIntervalMs);
|
|
936
|
+
parentStatus = getProcessStatus(parentPid);
|
|
937
|
+
}
|
|
938
|
+
const guardHost = host === "0.0.0.0" ? "localhost" : host;
|
|
939
|
+
const expectedBaseUrl = `http://${guardHost}:${port}`;
|
|
940
|
+
// Attempt restart via launchd before falling back to cleanup
|
|
941
|
+
const restarted = await tryLaunchdRestart(guardHost, port);
|
|
942
|
+
if (restarted) {
|
|
943
|
+
if (!argv.quiet) {
|
|
944
|
+
logger.always(`[proxy] fail-open guard restarted proxy via launchd`);
|
|
945
|
+
}
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
// Restart failed or launchd not installed — clean up Claude settings
|
|
949
|
+
const cleared = await clearClaudeProxySettings(expectedBaseUrl);
|
|
950
|
+
const state = loadProxyState();
|
|
951
|
+
if (state &&
|
|
952
|
+
state.host === host &&
|
|
953
|
+
state.port === port &&
|
|
954
|
+
!isProcessRunning(state.pid)) {
|
|
955
|
+
clearProxyState();
|
|
956
|
+
}
|
|
957
|
+
if (cleared && !argv.quiet) {
|
|
958
|
+
logger.always(`[proxy] fail-open guard removed stale ${expectedBaseUrl} from Claude settings`);
|
|
959
|
+
}
|
|
960
|
+
},
|
|
961
|
+
};
|
|
962
|
+
// =============================================================================
|
|
963
|
+
// PROXY SETUP COMMAND
|
|
964
|
+
// =============================================================================
|
|
965
|
+
export const proxySetupCommand = {
|
|
966
|
+
command: "setup",
|
|
967
|
+
describe: "One-command setup: login + install proxy as persistent service + configure Claude Code",
|
|
968
|
+
builder: (yargs) => {
|
|
969
|
+
return yargs
|
|
970
|
+
.option("port", {
|
|
971
|
+
type: "number",
|
|
972
|
+
alias: "p",
|
|
973
|
+
default: 55669,
|
|
974
|
+
description: "Proxy port",
|
|
975
|
+
})
|
|
976
|
+
.option("method", {
|
|
977
|
+
type: "string",
|
|
978
|
+
default: "oauth",
|
|
979
|
+
choices: ["oauth", "api-key"],
|
|
980
|
+
description: "Auth method",
|
|
981
|
+
})
|
|
982
|
+
.option("no-service", {
|
|
983
|
+
type: "boolean",
|
|
984
|
+
default: false,
|
|
985
|
+
description: "Skip service installation and start proxy in foreground instead",
|
|
986
|
+
})
|
|
987
|
+
.example("neurolink proxy setup", "Full setup with defaults")
|
|
988
|
+
.example("neurolink proxy setup -p 9000", "Setup on custom port")
|
|
989
|
+
.example("neurolink proxy setup --no-service", "Setup without installing as service");
|
|
990
|
+
},
|
|
991
|
+
handler: async (argv) => {
|
|
992
|
+
console.info("\n" + chalk.bold("NeuroLink Proxy Setup\n"));
|
|
993
|
+
const port = argv.port ?? 55669;
|
|
994
|
+
const noService = argv["no-service"];
|
|
995
|
+
// Step 1: Check existing accounts
|
|
996
|
+
console.info(chalk.blue("Step 1:") + " Checking accounts...");
|
|
997
|
+
const { tokenStore } = await import("../../lib/auth/tokenStore.js");
|
|
998
|
+
const allKeys = await tokenStore.listProviders();
|
|
999
|
+
const anthropicKeys = allKeys.filter((k) => k.startsWith("anthropic:") || k === "anthropic");
|
|
1000
|
+
const validKeys = [];
|
|
1001
|
+
for (const key of anthropicKeys) {
|
|
1002
|
+
const tokens = await tokenStore.loadTokens(key);
|
|
1003
|
+
if (tokens && (!tokens.expiresAt || tokens.expiresAt > Date.now())) {
|
|
1004
|
+
validKeys.push(key);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
// Also check legacy credentials file
|
|
1008
|
+
try {
|
|
1009
|
+
const fs = await import("fs");
|
|
1010
|
+
const credPath = join(homedir(), ".neurolink", "anthropic-credentials.json");
|
|
1011
|
+
const creds = JSON.parse(fs.readFileSync(credPath, "utf8"));
|
|
1012
|
+
if (creds.oauth?.accessToken && creds.oauth?.expiresAt > Date.now()) {
|
|
1013
|
+
validKeys.push("legacy-anthropic");
|
|
1014
|
+
console.info(chalk.green(" ✓ Found valid OAuth account"));
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
catch {
|
|
1018
|
+
/* no file */
|
|
1019
|
+
}
|
|
1020
|
+
if (validKeys.length > 0) {
|
|
1021
|
+
console.info(chalk.green(` ✓ Found ${validKeys.length} valid account(s)`));
|
|
1022
|
+
}
|
|
1023
|
+
else {
|
|
1024
|
+
// Step 2: Login
|
|
1025
|
+
console.info(chalk.yellow(" No valid accounts found. Starting login..."));
|
|
1026
|
+
console.info(chalk.blue("\nStep 2:") + " Authenticating...");
|
|
1027
|
+
const { handleLogin } = await import("./auth.js");
|
|
1028
|
+
await handleLogin({
|
|
1029
|
+
provider: "anthropic",
|
|
1030
|
+
method: argv.method,
|
|
1031
|
+
});
|
|
1032
|
+
console.info(chalk.green(" ✓ Authentication complete"));
|
|
1033
|
+
}
|
|
1034
|
+
// Step 3: Install as persistent service (macOS) or start foreground
|
|
1035
|
+
const stepNum = validKeys.length > 0 ? 2 : 3;
|
|
1036
|
+
if (!noService && process.platform === "darwin") {
|
|
1037
|
+
console.info(chalk.blue(`\nStep ${stepNum}:`) +
|
|
1038
|
+
" Installing proxy as persistent service...");
|
|
1039
|
+
await proxyInstallCommand.handler({
|
|
1040
|
+
...argv,
|
|
1041
|
+
port,
|
|
1042
|
+
host: "127.0.0.1",
|
|
1043
|
+
});
|
|
1044
|
+
// Step 4: Configure Claude Code settings
|
|
1045
|
+
const nextStep = stepNum + 1;
|
|
1046
|
+
console.info(chalk.blue(`\nStep ${nextStep}:`) + " Configuring Claude Code...");
|
|
1047
|
+
const url = `http://127.0.0.1:${port}`;
|
|
1048
|
+
try {
|
|
1049
|
+
await setClaudeProxySettings(url);
|
|
1050
|
+
console.info(chalk.green(" ✓ Claude Code configured"));
|
|
1051
|
+
}
|
|
1052
|
+
catch (e) {
|
|
1053
|
+
console.info(chalk.yellow(` ⚠ Could not auto-configure: ${e instanceof Error ? e.message : String(e)}`));
|
|
1054
|
+
console.info(chalk.yellow(` Set manually: ANTHROPIC_BASE_URL=${url}`));
|
|
1055
|
+
}
|
|
1056
|
+
// Done!
|
|
1057
|
+
console.info("");
|
|
1058
|
+
console.info(chalk.bold.green("Setup complete!"));
|
|
1059
|
+
console.info(` Proxy running as daemon on ${chalk.cyan(url)}`);
|
|
1060
|
+
console.info(` Auto-restarts on crash (5s throttle) and on login`);
|
|
1061
|
+
console.info("");
|
|
1062
|
+
console.info(chalk.gray(" Status: neurolink proxy status"));
|
|
1063
|
+
console.info(chalk.gray(" Logs: ~/.neurolink/logs/proxy-launchd-*.log"));
|
|
1064
|
+
console.info(chalk.gray(" Uninstall: neurolink proxy uninstall"));
|
|
1065
|
+
console.info("");
|
|
1066
|
+
}
|
|
1067
|
+
else {
|
|
1068
|
+
// Foreground mode (--no-service or non-macOS)
|
|
1069
|
+
if (noService) {
|
|
1070
|
+
console.info(chalk.blue(`\nStep ${stepNum}:`) + " Starting proxy in foreground...");
|
|
1071
|
+
}
|
|
1072
|
+
else {
|
|
1073
|
+
console.info(chalk.blue(`\nStep ${stepNum}:`) + " Starting proxy...");
|
|
1074
|
+
console.info(chalk.yellow(" Note: No daemon support on this platform. Proxy runs in foreground."));
|
|
1075
|
+
}
|
|
1076
|
+
// Delegate to proxy start handler — blocks until Ctrl+C
|
|
1077
|
+
await proxyStartCommand.handler({
|
|
1078
|
+
...argv,
|
|
1079
|
+
quiet: false,
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
},
|
|
1083
|
+
};
|
|
1084
|
+
// =============================================================================
|
|
1085
|
+
// PROXY INSTALL / UNINSTALL — launchd service (macOS)
|
|
1086
|
+
// =============================================================================
|
|
1087
|
+
function buildPlist(port, host) {
|
|
1088
|
+
const nodeExec = process.execPath;
|
|
1089
|
+
const entryScript = process.argv[1] ?? join(__dirname, "..", "index.js");
|
|
1090
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
1091
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
1092
|
+
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
1093
|
+
<plist version="1.0">
|
|
1094
|
+
<dict>
|
|
1095
|
+
<key>Label</key>
|
|
1096
|
+
<string>${PLIST_LABEL}</string>
|
|
1097
|
+
|
|
1098
|
+
<key>ProgramArguments</key>
|
|
1099
|
+
<array>
|
|
1100
|
+
<string>${nodeExec}</string>
|
|
1101
|
+
<string>${entryScript}</string>
|
|
1102
|
+
<string>proxy</string>
|
|
1103
|
+
<string>start</string>
|
|
1104
|
+
<string>--port</string>
|
|
1105
|
+
<string>${port}</string>
|
|
1106
|
+
<string>--host</string>
|
|
1107
|
+
<string>${host}</string>
|
|
1108
|
+
<string>--quiet</string>
|
|
1109
|
+
</array>
|
|
1110
|
+
|
|
1111
|
+
<key>RunAtLoad</key>
|
|
1112
|
+
<true/>
|
|
1113
|
+
|
|
1114
|
+
<key>KeepAlive</key>
|
|
1115
|
+
<dict>
|
|
1116
|
+
<key>SuccessfulExit</key>
|
|
1117
|
+
<false/>
|
|
1118
|
+
</dict>
|
|
1119
|
+
|
|
1120
|
+
<key>ThrottleInterval</key>
|
|
1121
|
+
<integer>5</integer>
|
|
1122
|
+
|
|
1123
|
+
<key>StandardOutPath</key>
|
|
1124
|
+
<string>${join(homedir(), ".neurolink", "logs", "proxy-launchd-stdout.log")}</string>
|
|
1125
|
+
|
|
1126
|
+
<key>StandardErrorPath</key>
|
|
1127
|
+
<string>${join(homedir(), ".neurolink", "logs", "proxy-launchd-stderr.log")}</string>
|
|
1128
|
+
|
|
1129
|
+
<key>EnvironmentVariables</key>
|
|
1130
|
+
<dict>
|
|
1131
|
+
<key>PATH</key>
|
|
1132
|
+
<string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
|
|
1133
|
+
<key>HOME</key>
|
|
1134
|
+
<string>${homedir()}</string>
|
|
1135
|
+
</dict>
|
|
1136
|
+
</dict>
|
|
1137
|
+
</plist>`;
|
|
1138
|
+
}
|
|
1139
|
+
export const proxyInstallCommand = {
|
|
1140
|
+
command: "install",
|
|
1141
|
+
describe: "Install proxy as a persistent background service (auto-restarts on crash/reboot)",
|
|
1142
|
+
builder: (yargs) => {
|
|
1143
|
+
return yargs
|
|
1144
|
+
.option("port", {
|
|
1145
|
+
type: "number",
|
|
1146
|
+
alias: "p",
|
|
1147
|
+
default: 55669,
|
|
1148
|
+
description: "Proxy port",
|
|
1149
|
+
})
|
|
1150
|
+
.option("host", {
|
|
1151
|
+
type: "string",
|
|
1152
|
+
default: "127.0.0.1",
|
|
1153
|
+
description: "Proxy host",
|
|
1154
|
+
})
|
|
1155
|
+
.example("neurolink proxy install", "Install with defaults (port 55669)")
|
|
1156
|
+
.example("neurolink proxy install -p 9000", "Install on custom port");
|
|
1157
|
+
},
|
|
1158
|
+
handler: async (argv) => {
|
|
1159
|
+
const port = argv.port ?? 55669;
|
|
1160
|
+
const host = argv.host ?? "127.0.0.1";
|
|
1161
|
+
if (process.platform !== "darwin") {
|
|
1162
|
+
console.info(chalk.red("proxy install is currently macOS-only (uses launchd)."));
|
|
1163
|
+
console.info(chalk.yellow("On Linux, use systemd. On Windows, use Task Scheduler."));
|
|
1164
|
+
process.exit(1);
|
|
1165
|
+
}
|
|
1166
|
+
const { writeFileSync, mkdirSync, existsSync } = await import("fs");
|
|
1167
|
+
const logsDir = join(homedir(), ".neurolink", "logs");
|
|
1168
|
+
if (!existsSync(logsDir)) {
|
|
1169
|
+
mkdirSync(logsDir, { recursive: true });
|
|
1170
|
+
}
|
|
1171
|
+
if (!existsSync(PLIST_DIR)) {
|
|
1172
|
+
mkdirSync(PLIST_DIR, { recursive: true });
|
|
1173
|
+
}
|
|
1174
|
+
const plist = buildPlist(port, host);
|
|
1175
|
+
writeFileSync(PLIST_PATH, plist, "utf-8");
|
|
1176
|
+
console.info(chalk.green(`✓ Plist written to ${PLIST_PATH}`));
|
|
1177
|
+
try {
|
|
1178
|
+
const { execFileSync } = await import("node:child_process");
|
|
1179
|
+
execFileSync("launchctl", ["unload", PLIST_PATH], {
|
|
1180
|
+
stdio: "ignore",
|
|
1181
|
+
});
|
|
1182
|
+
}
|
|
1183
|
+
catch {
|
|
1184
|
+
/* not loaded yet */
|
|
1185
|
+
}
|
|
1186
|
+
try {
|
|
1187
|
+
const { execFileSync } = await import("node:child_process");
|
|
1188
|
+
execFileSync("launchctl", ["load", PLIST_PATH]);
|
|
1189
|
+
console.info(chalk.green(`✓ Service loaded and started`));
|
|
1190
|
+
}
|
|
1191
|
+
catch (e) {
|
|
1192
|
+
console.info(chalk.red(`Failed to load service: ${e}`));
|
|
1193
|
+
process.exit(1);
|
|
1194
|
+
}
|
|
1195
|
+
// Wait briefly for launchd to start the process, then persist state
|
|
1196
|
+
await new Promise((resolve) => setTimeout(resolve, 2_000));
|
|
1197
|
+
try {
|
|
1198
|
+
const { execFileSync } = await import("node:child_process");
|
|
1199
|
+
const uid = process.getuid?.() ?? 501;
|
|
1200
|
+
const output = execFileSync("launchctl", ["print", `gui/${uid}/${PLIST_LABEL}`], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
1201
|
+
const pidMatch = output.match(/pid\s*=\s*(\d+)/);
|
|
1202
|
+
if (pidMatch) {
|
|
1203
|
+
saveProxyState({
|
|
1204
|
+
pid: Number(pidMatch[1]),
|
|
1205
|
+
port,
|
|
1206
|
+
host,
|
|
1207
|
+
strategy: "round-robin",
|
|
1208
|
+
startTime: new Date().toISOString(),
|
|
1209
|
+
managedBy: "launchd",
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
catch {
|
|
1214
|
+
/* non-fatal — state will be written by the proxy process itself */
|
|
1215
|
+
}
|
|
1216
|
+
console.info("");
|
|
1217
|
+
console.info(chalk.bold("Proxy is now a persistent service:"));
|
|
1218
|
+
console.info(` • Auto-starts on login`);
|
|
1219
|
+
console.info(` • Auto-restarts on crash (5s throttle)`);
|
|
1220
|
+
console.info(` • Listening on http://${host}:${port}`);
|
|
1221
|
+
console.info(` • Logs: ~/.neurolink/logs/proxy-launchd-*.log`);
|
|
1222
|
+
console.info("");
|
|
1223
|
+
console.info(chalk.gray(` Manage: launchctl start/stop ${PLIST_LABEL}`));
|
|
1224
|
+
console.info(chalk.gray(` Remove: neurolink proxy uninstall`));
|
|
1225
|
+
},
|
|
1226
|
+
};
|
|
1227
|
+
export const proxyUninstallCommand = {
|
|
1228
|
+
command: "uninstall",
|
|
1229
|
+
describe: "Remove proxy background service",
|
|
1230
|
+
builder: (yargs) => yargs,
|
|
1231
|
+
handler: async () => {
|
|
1232
|
+
if (process.platform !== "darwin") {
|
|
1233
|
+
console.info(chalk.red("proxy uninstall is currently macOS-only."));
|
|
1234
|
+
process.exit(1);
|
|
1235
|
+
}
|
|
1236
|
+
const { existsSync, unlinkSync } = await import("fs");
|
|
1237
|
+
if (!existsSync(PLIST_PATH)) {
|
|
1238
|
+
console.info(chalk.yellow("No proxy service installed."));
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
try {
|
|
1242
|
+
const { execFileSync } = await import("node:child_process");
|
|
1243
|
+
execFileSync("launchctl", ["unload", PLIST_PATH]);
|
|
1244
|
+
console.info(chalk.green(`✓ Service stopped`));
|
|
1245
|
+
}
|
|
1246
|
+
catch {
|
|
1247
|
+
/* may not be loaded */
|
|
1248
|
+
}
|
|
1249
|
+
unlinkSync(PLIST_PATH);
|
|
1250
|
+
console.info(chalk.green(`✓ Plist removed from ${PLIST_PATH}`));
|
|
1251
|
+
console.info(chalk.green(`✓ Proxy service uninstalled`));
|
|
1252
|
+
},
|
|
1253
|
+
};
|
|
1254
|
+
//# sourceMappingURL=proxy.js.map
|