@juspay/neurolink 9.15.0 ā 9.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/adapters/video/videoAnalyzer.d.ts +1 -1
- package/dist/adapters/video/videoAnalyzer.js +10 -8
- package/dist/cli/commands/setup-anthropic.js +1 -14
- package/dist/cli/commands/setup-azure.js +1 -12
- package/dist/cli/commands/setup-bedrock.js +1 -9
- package/dist/cli/commands/setup-google-ai.js +1 -12
- package/dist/cli/commands/setup-openai.js +1 -14
- package/dist/cli/commands/workflow.d.ts +27 -0
- package/dist/cli/commands/workflow.js +216 -0
- package/dist/cli/factories/commandFactory.js +79 -20
- package/dist/cli/index.js +0 -1
- package/dist/cli/parser.js +4 -1
- package/dist/cli/utils/maskCredential.d.ts +11 -0
- package/dist/cli/utils/maskCredential.js +23 -0
- package/dist/constants/contextWindows.js +107 -16
- package/dist/constants/enums.d.ts +99 -15
- package/dist/constants/enums.js +152 -22
- package/dist/context/budgetChecker.js +1 -1
- package/dist/context/contextCompactor.js +31 -4
- package/dist/context/emergencyTruncation.d.ts +21 -0
- package/dist/context/emergencyTruncation.js +88 -0
- package/dist/context/errorDetection.d.ts +16 -0
- package/dist/context/errorDetection.js +48 -1
- package/dist/context/errors.d.ts +19 -0
- package/dist/context/errors.js +21 -0
- package/dist/context/stages/slidingWindowTruncator.d.ts +6 -0
- package/dist/context/stages/slidingWindowTruncator.js +159 -24
- package/dist/core/baseProvider.js +306 -200
- package/dist/core/conversationMemoryManager.js +104 -61
- package/dist/core/evaluationProviders.js +16 -33
- package/dist/core/factory.js +237 -164
- package/dist/core/modules/GenerationHandler.js +175 -116
- package/dist/core/modules/MessageBuilder.js +222 -170
- package/dist/core/modules/StreamHandler.d.ts +1 -0
- package/dist/core/modules/StreamHandler.js +95 -27
- package/dist/core/modules/TelemetryHandler.d.ts +10 -1
- package/dist/core/modules/TelemetryHandler.js +25 -7
- package/dist/core/modules/ToolsManager.js +115 -191
- package/dist/core/redisConversationMemoryManager.js +418 -282
- package/dist/factories/providerRegistry.d.ts +5 -0
- package/dist/factories/providerRegistry.js +20 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -2
- package/dist/lib/adapters/video/videoAnalyzer.d.ts +1 -1
- package/dist/lib/adapters/video/videoAnalyzer.js +10 -8
- package/dist/lib/constants/contextWindows.js +107 -16
- package/dist/lib/constants/enums.d.ts +99 -15
- package/dist/lib/constants/enums.js +152 -22
- package/dist/lib/context/budgetChecker.js +1 -1
- package/dist/lib/context/contextCompactor.js +31 -4
- package/dist/lib/context/emergencyTruncation.d.ts +21 -0
- package/dist/lib/context/emergencyTruncation.js +89 -0
- package/dist/lib/context/errorDetection.d.ts +16 -0
- package/dist/lib/context/errorDetection.js +48 -1
- package/dist/lib/context/errors.d.ts +19 -0
- package/dist/lib/context/errors.js +22 -0
- package/dist/lib/context/stages/slidingWindowTruncator.d.ts +6 -0
- package/dist/lib/context/stages/slidingWindowTruncator.js +159 -24
- package/dist/lib/core/baseProvider.js +306 -200
- package/dist/lib/core/conversationMemoryManager.js +104 -61
- package/dist/lib/core/evaluationProviders.js +16 -33
- package/dist/lib/core/factory.js +237 -164
- package/dist/lib/core/modules/GenerationHandler.js +175 -116
- package/dist/lib/core/modules/MessageBuilder.js +222 -170
- package/dist/lib/core/modules/StreamHandler.d.ts +1 -0
- package/dist/lib/core/modules/StreamHandler.js +95 -27
- package/dist/lib/core/modules/TelemetryHandler.d.ts +10 -1
- package/dist/lib/core/modules/TelemetryHandler.js +25 -7
- package/dist/lib/core/modules/ToolsManager.js +115 -191
- package/dist/lib/core/redisConversationMemoryManager.js +418 -282
- package/dist/lib/factories/providerRegistry.d.ts +5 -0
- package/dist/lib/factories/providerRegistry.js +20 -2
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.js +4 -2
- package/dist/lib/mcp/externalServerManager.js +66 -0
- package/dist/lib/mcp/mcpCircuitBreaker.js +24 -0
- package/dist/lib/mcp/mcpClientFactory.js +16 -0
- package/dist/lib/mcp/toolDiscoveryService.js +32 -6
- package/dist/lib/mcp/toolRegistry.js +193 -123
- package/dist/lib/neurolink.d.ts +6 -0
- package/dist/lib/neurolink.js +1162 -646
- package/dist/lib/providers/amazonBedrock.d.ts +1 -1
- package/dist/lib/providers/amazonBedrock.js +521 -319
- package/dist/lib/providers/anthropic.js +73 -17
- package/dist/lib/providers/anthropicBaseProvider.js +77 -17
- package/dist/lib/providers/googleAiStudio.d.ts +1 -1
- package/dist/lib/providers/googleAiStudio.js +292 -227
- package/dist/lib/providers/googleVertex.d.ts +36 -1
- package/dist/lib/providers/googleVertex.js +553 -260
- package/dist/lib/providers/ollama.js +329 -278
- package/dist/lib/providers/openAI.js +77 -19
- package/dist/lib/providers/sagemaker/parsers.js +3 -3
- package/dist/lib/providers/sagemaker/streaming.js +3 -3
- package/dist/lib/proxy/proxyFetch.js +81 -48
- package/dist/lib/rag/ChunkerFactory.js +1 -1
- package/dist/lib/rag/chunkers/MarkdownChunker.d.ts +22 -0
- package/dist/lib/rag/chunkers/MarkdownChunker.js +213 -9
- package/dist/lib/rag/chunking/markdownChunker.d.ts +16 -0
- package/dist/lib/rag/chunking/markdownChunker.js +174 -2
- package/dist/lib/rag/pipeline/contextAssembly.js +2 -1
- package/dist/lib/rag/ragIntegration.d.ts +18 -1
- package/dist/lib/rag/ragIntegration.js +94 -14
- package/dist/lib/rag/retrieval/vectorQueryTool.js +21 -4
- package/dist/lib/server/abstract/baseServerAdapter.js +4 -1
- package/dist/lib/server/adapters/fastifyAdapter.js +35 -30
- package/dist/lib/services/server/ai/observability/instrumentation.d.ts +32 -0
- package/dist/lib/services/server/ai/observability/instrumentation.js +39 -0
- package/dist/lib/telemetry/attributes.d.ts +52 -0
- package/dist/lib/telemetry/attributes.js +61 -0
- package/dist/lib/telemetry/index.d.ts +3 -0
- package/dist/lib/telemetry/index.js +3 -0
- package/dist/lib/telemetry/telemetryService.d.ts +6 -0
- package/dist/lib/telemetry/telemetryService.js +6 -0
- package/dist/lib/telemetry/tracers.d.ts +15 -0
- package/dist/lib/telemetry/tracers.js +17 -0
- package/dist/lib/telemetry/withSpan.d.ts +9 -0
- package/dist/lib/telemetry/withSpan.js +35 -0
- package/dist/lib/types/contextTypes.d.ts +10 -0
- package/dist/lib/types/streamTypes.d.ts +14 -0
- package/dist/lib/utils/conversationMemory.js +121 -82
- package/dist/lib/utils/logger.d.ts +5 -0
- package/dist/lib/utils/logger.js +50 -2
- package/dist/lib/utils/messageBuilder.js +22 -42
- package/dist/lib/utils/modelDetection.js +3 -3
- package/dist/lib/utils/providerRetry.d.ts +41 -0
- package/dist/lib/utils/providerRetry.js +114 -0
- package/dist/lib/utils/retryability.d.ts +14 -0
- package/dist/lib/utils/retryability.js +23 -0
- package/dist/lib/utils/sanitizers/svg.js +4 -5
- package/dist/lib/utils/tokenEstimation.d.ts +11 -1
- package/dist/lib/utils/tokenEstimation.js +19 -4
- package/dist/lib/utils/videoAnalysisProcessor.js +7 -3
- package/dist/mcp/externalServerManager.js +66 -0
- package/dist/mcp/mcpCircuitBreaker.js +24 -0
- package/dist/mcp/mcpClientFactory.js +16 -0
- package/dist/mcp/toolDiscoveryService.js +32 -6
- package/dist/mcp/toolRegistry.js +193 -123
- package/dist/neurolink.d.ts +6 -0
- package/dist/neurolink.js +1162 -646
- package/dist/providers/amazonBedrock.d.ts +1 -1
- package/dist/providers/amazonBedrock.js +521 -319
- package/dist/providers/anthropic.js +73 -17
- package/dist/providers/anthropicBaseProvider.js +77 -17
- package/dist/providers/googleAiStudio.d.ts +1 -1
- package/dist/providers/googleAiStudio.js +292 -227
- package/dist/providers/googleVertex.d.ts +36 -1
- package/dist/providers/googleVertex.js +553 -260
- package/dist/providers/ollama.js +329 -278
- package/dist/providers/openAI.js +77 -19
- package/dist/providers/sagemaker/parsers.js +3 -3
- package/dist/providers/sagemaker/streaming.js +3 -3
- package/dist/proxy/proxyFetch.js +81 -48
- package/dist/rag/ChunkerFactory.js +1 -1
- package/dist/rag/chunkers/MarkdownChunker.d.ts +22 -0
- package/dist/rag/chunkers/MarkdownChunker.js +213 -9
- package/dist/rag/chunking/markdownChunker.d.ts +16 -0
- package/dist/rag/chunking/markdownChunker.js +174 -2
- package/dist/rag/pipeline/contextAssembly.js +2 -1
- package/dist/rag/ragIntegration.d.ts +18 -1
- package/dist/rag/ragIntegration.js +94 -14
- package/dist/rag/retrieval/vectorQueryTool.js +21 -4
- package/dist/server/abstract/baseServerAdapter.js +4 -1
- package/dist/server/adapters/fastifyAdapter.js +35 -30
- package/dist/services/server/ai/observability/instrumentation.d.ts +32 -0
- package/dist/services/server/ai/observability/instrumentation.js +39 -0
- package/dist/telemetry/attributes.d.ts +52 -0
- package/dist/telemetry/attributes.js +60 -0
- package/dist/telemetry/index.d.ts +3 -0
- package/dist/telemetry/index.js +3 -0
- package/dist/telemetry/telemetryService.d.ts +6 -0
- package/dist/telemetry/telemetryService.js +6 -0
- package/dist/telemetry/tracers.d.ts +15 -0
- package/dist/telemetry/tracers.js +16 -0
- package/dist/telemetry/withSpan.d.ts +9 -0
- package/dist/telemetry/withSpan.js +34 -0
- package/dist/types/contextTypes.d.ts +10 -0
- package/dist/types/streamTypes.d.ts +14 -0
- package/dist/utils/conversationMemory.js +121 -82
- package/dist/utils/logger.d.ts +5 -0
- package/dist/utils/logger.js +50 -2
- package/dist/utils/messageBuilder.js +22 -42
- package/dist/utils/modelDetection.js +3 -3
- package/dist/utils/providerRetry.d.ts +41 -0
- package/dist/utils/providerRetry.js +113 -0
- package/dist/utils/retryability.d.ts +14 -0
- package/dist/utils/retryability.js +22 -0
- package/dist/utils/sanitizers/svg.js +4 -5
- package/dist/utils/tokenEstimation.d.ts +11 -1
- package/dist/utils/tokenEstimation.js +19 -4
- package/dist/utils/videoAnalysisProcessor.js +7 -3
- package/dist/workflow/config.d.ts +26 -26
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [9.16.0](https://github.com/juspay/neurolink/compare/v9.15.0...v9.16.0) (2026-03-02)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- **(sdk):** add models, observability, RAG enhancements, landing overhaul, and 45 review fixes ([eb79a1f](https://github.com/juspay/neurolink/commit/eb79a1f51dfd789da49130b6a05fa40ed38fd668))
|
|
6
|
+
|
|
1
7
|
## [9.15.0](https://github.com/juspay/neurolink/compare/v9.14.0...v9.15.0) (2026-03-01)
|
|
2
8
|
|
|
3
9
|
### Features
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Video Analysis Handler
|
|
3
3
|
*
|
|
4
|
-
* Provides video analysis using Google's Gemini 2.
|
|
4
|
+
* Provides video analysis using Google's Gemini 2.5 Flash model.
|
|
5
5
|
* Supports both Vertex AI and Gemini API providers.
|
|
6
6
|
*
|
|
7
7
|
* @module adapters/video/geminiVideoAnalyzer
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Video Analysis Handler
|
|
3
3
|
*
|
|
4
|
-
* Provides video analysis using Google's Gemini 2.
|
|
4
|
+
* Provides video analysis using Google's Gemini 2.5 Flash model.
|
|
5
5
|
* Supports both Vertex AI and Gemini API providers.
|
|
6
6
|
*
|
|
7
7
|
* @module adapters/video/geminiVideoAnalyzer
|
|
@@ -13,7 +13,7 @@ import { NeuroLinkError, ErrorFactory } from "../../utils/errorHandling.js";
|
|
|
13
13
|
// ---------------------------------------------------------------------------
|
|
14
14
|
// Shared config
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
|
-
const DEFAULT_MODEL = "gemini-2.
|
|
16
|
+
const DEFAULT_MODEL = "gemini-2.5-flash";
|
|
17
17
|
const DEFAULT_LOCATION = "us-central1";
|
|
18
18
|
/**
|
|
19
19
|
* Extract content items from user messages
|
|
@@ -223,14 +223,16 @@ async function getVertexConfig() {
|
|
|
223
223
|
}
|
|
224
224
|
export async function analyzeVideo(messages, options = {}) {
|
|
225
225
|
const provider = options.provider || AIProviderName.AUTO;
|
|
226
|
-
// Vertex ā only when
|
|
227
|
-
if (provider === AIProviderName.VERTEX ||
|
|
226
|
+
// Vertex ā only when Vertex credentials are configured
|
|
227
|
+
if (provider === AIProviderName.VERTEX ||
|
|
228
|
+
(provider === AIProviderName.AUTO &&
|
|
229
|
+
(process.env.GOOGLE_VERTEX_PROJECT || process.env.GOOGLE_CLOUD_PROJECT))) {
|
|
228
230
|
return analyzeVideoWithVertexAI(messages, options);
|
|
229
231
|
}
|
|
230
|
-
// Gemini API ā when
|
|
231
|
-
if (provider === AIProviderName.GOOGLE_AI
|
|
232
|
+
// Gemini API ā when Google AI API key is available
|
|
233
|
+
if (provider === AIProviderName.GOOGLE_AI ||
|
|
234
|
+
(provider === AIProviderName.AUTO && process.env.GOOGLE_AI_API_KEY)) {
|
|
232
235
|
return analyzeVideoWithGeminiAPI(messages, options);
|
|
233
236
|
}
|
|
234
|
-
throw
|
|
235
|
-
"Set GOOGLE_VERTEX_PROJECT for Vertex AI or GOOGLE_AI_API_KEY for Gemini API.");
|
|
237
|
+
throw ErrorFactory.invalidConfiguration("video analysis provider", "No valid provider configuration found. Set GOOGLE_VERTEX_PROJECT for Vertex AI or GOOGLE_AI_API_KEY for Gemini API.");
|
|
236
238
|
}
|
|
@@ -16,6 +16,7 @@ import ora from "ora";
|
|
|
16
16
|
import { logger } from "../../lib/utils/logger.js";
|
|
17
17
|
import { getTopModelChoices } from "../../lib/utils/modelChoices.js";
|
|
18
18
|
import { AIProviderName } from "../../lib/types/index.js";
|
|
19
|
+
import { maskCredential } from "../utils/maskCredential.js";
|
|
19
20
|
export async function handleAnthropicSetup(argv) {
|
|
20
21
|
try {
|
|
21
22
|
const options = {
|
|
@@ -365,20 +366,6 @@ async function updateEnvFile(config) {
|
|
|
365
366
|
throw error;
|
|
366
367
|
}
|
|
367
368
|
}
|
|
368
|
-
/**
|
|
369
|
-
* Mask API key for display
|
|
370
|
-
*/
|
|
371
|
-
function maskCredential(credential) {
|
|
372
|
-
if (!credential || credential.length < 8) {
|
|
373
|
-
return "****";
|
|
374
|
-
}
|
|
375
|
-
const knownPrefixes = ["sk-ant-"];
|
|
376
|
-
const prefix = knownPrefixes.find((p) => credential.startsWith(p)) ??
|
|
377
|
-
credential.slice(0, 3);
|
|
378
|
-
const end = credential.slice(-4);
|
|
379
|
-
const stars = "*".repeat(Math.max(4, credential.length - prefix.length - 4));
|
|
380
|
-
return `${prefix}${stars}${end}`;
|
|
381
|
-
}
|
|
382
369
|
/**
|
|
383
370
|
* Show usage example
|
|
384
371
|
*/
|
|
@@ -16,6 +16,7 @@ import { logger } from "../../lib/utils/logger.js";
|
|
|
16
16
|
import { updateEnvFile as updateEnvFileShared, displayEnvUpdateSummary, } from "../utils/envManager.js";
|
|
17
17
|
import { getTopModelChoices } from "../../lib/utils/modelChoices.js";
|
|
18
18
|
import { AIProviderName } from "../../lib/types/index.js";
|
|
19
|
+
import { maskCredential } from "../utils/maskCredential.js";
|
|
19
20
|
export async function handleAzureSetup(argv) {
|
|
20
21
|
try {
|
|
21
22
|
const options = {
|
|
@@ -372,18 +373,6 @@ async function updateEnvFileWithConfig(config) {
|
|
|
372
373
|
throw error;
|
|
373
374
|
}
|
|
374
375
|
}
|
|
375
|
-
/**
|
|
376
|
-
* Mask API key for display
|
|
377
|
-
*/
|
|
378
|
-
function maskCredential(credential) {
|
|
379
|
-
if (!credential || credential.length < 8) {
|
|
380
|
-
return "****";
|
|
381
|
-
}
|
|
382
|
-
const start = credential.slice(0, 4);
|
|
383
|
-
const end = credential.slice(-4);
|
|
384
|
-
const middle = "*".repeat(Math.max(4, credential.length - 8));
|
|
385
|
-
return `${start}${middle}${end}`;
|
|
386
|
-
}
|
|
387
376
|
/**
|
|
388
377
|
* Show usage example
|
|
389
378
|
*/
|
|
@@ -15,6 +15,7 @@ import { logger } from "../../lib/utils/logger.js";
|
|
|
15
15
|
import { updateEnvFile as envUpdate } from "../utils/envManager.js";
|
|
16
16
|
import { getTopModelChoices } from "../../lib/utils/modelChoices.js";
|
|
17
17
|
import { AIProviderName } from "../../lib/types/index.js";
|
|
18
|
+
import { maskCredential } from "../utils/maskCredential.js";
|
|
18
19
|
export async function handleBedrockSetup(argv) {
|
|
19
20
|
try {
|
|
20
21
|
const options = {
|
|
@@ -453,13 +454,4 @@ function displayUsageExample() {
|
|
|
453
454
|
logger.always(chalk.green("š You can now use AWS Bedrock with the NeuroLink CLI:"));
|
|
454
455
|
logger.always(chalk.cyan(" pnpm cli generate 'Hello from Bedrock!' --provider bedrock"));
|
|
455
456
|
}
|
|
456
|
-
function maskCredential(credential) {
|
|
457
|
-
if (!credential || credential.length < 8) {
|
|
458
|
-
return "****";
|
|
459
|
-
}
|
|
460
|
-
const start = credential.slice(0, 4);
|
|
461
|
-
const end = credential.slice(-4);
|
|
462
|
-
const middle = "*".repeat(Math.max(4, credential.length - 8));
|
|
463
|
-
return `${start}${middle}${end}`;
|
|
464
|
-
}
|
|
465
457
|
//# sourceMappingURL=setup-bedrock.js.map
|
|
@@ -17,6 +17,7 @@ import { GoogleAIModels } from "../../lib/constants/enums.js";
|
|
|
17
17
|
import { updateEnvFile as updateEnvFileManager, displayEnvUpdateSummary, } from "../utils/envManager.js";
|
|
18
18
|
import { getTopModelChoices } from "../../lib/utils/modelChoices.js";
|
|
19
19
|
import { AIProviderName } from "../../lib/types/index.js";
|
|
20
|
+
import { maskCredential } from "../utils/maskCredential.js";
|
|
20
21
|
/**
|
|
21
22
|
* Get the runtime default model that matches the provider implementation
|
|
22
23
|
*/
|
|
@@ -326,18 +327,6 @@ async function updateEnvFile(config) {
|
|
|
326
327
|
throw error;
|
|
327
328
|
}
|
|
328
329
|
}
|
|
329
|
-
/**
|
|
330
|
-
* Mask API key for display
|
|
331
|
-
*/
|
|
332
|
-
function maskCredential(credential) {
|
|
333
|
-
if (!credential || credential.length < 8) {
|
|
334
|
-
return "****";
|
|
335
|
-
}
|
|
336
|
-
const start = credential.slice(0, 7); // Show 'AIza' plus a few chars
|
|
337
|
-
const end = credential.slice(-4);
|
|
338
|
-
const middle = "*".repeat(Math.max(4, credential.length - 11));
|
|
339
|
-
return `${start}${middle}${end}`;
|
|
340
|
-
}
|
|
341
330
|
/**
|
|
342
331
|
* Show usage example
|
|
343
332
|
*/
|
|
@@ -16,6 +16,7 @@ import ora from "ora";
|
|
|
16
16
|
import { logger } from "../../lib/utils/logger.js";
|
|
17
17
|
import { getTopModelChoices } from "../../lib/utils/modelChoices.js";
|
|
18
18
|
import { AIProviderName } from "../../lib/types/index.js";
|
|
19
|
+
import { maskCredential } from "../utils/maskCredential.js";
|
|
19
20
|
export async function handleOpenAISetup(argv) {
|
|
20
21
|
try {
|
|
21
22
|
const options = {
|
|
@@ -358,20 +359,6 @@ async function updateEnvFile(config) {
|
|
|
358
359
|
throw error;
|
|
359
360
|
}
|
|
360
361
|
}
|
|
361
|
-
/**
|
|
362
|
-
* Mask API key for display
|
|
363
|
-
*/
|
|
364
|
-
function maskCredential(credential) {
|
|
365
|
-
if (!credential || credential.length < 8) {
|
|
366
|
-
return "****";
|
|
367
|
-
}
|
|
368
|
-
const knownPrefixes = ["sk-"];
|
|
369
|
-
const prefix = knownPrefixes.find((p) => credential.startsWith(p)) ??
|
|
370
|
-
credential.slice(0, 3);
|
|
371
|
-
const end = credential.slice(-4);
|
|
372
|
-
const stars = "*".repeat(Math.max(4, credential.length - prefix.length - 4));
|
|
373
|
-
return `${prefix}${stars}${end}`;
|
|
374
|
-
}
|
|
375
362
|
/**
|
|
376
363
|
* Show usage example
|
|
377
364
|
*/
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow CLI Commands for NeuroLink
|
|
3
|
+
*
|
|
4
|
+
* Implements commands for workflow management and execution:
|
|
5
|
+
* - neurolink workflow list - List available predefined workflows
|
|
6
|
+
* - neurolink workflow info <name> - Show details of a workflow
|
|
7
|
+
* - neurolink workflow execute <name> <prompt> - Execute a workflow
|
|
8
|
+
*/
|
|
9
|
+
import type { CommandModule } from "yargs";
|
|
10
|
+
/**
|
|
11
|
+
* Workflow CLI command factory
|
|
12
|
+
*/
|
|
13
|
+
export declare class WorkflowCommandFactory {
|
|
14
|
+
static createWorkflowCommands(): CommandModule;
|
|
15
|
+
/**
|
|
16
|
+
* List all predefined workflows
|
|
17
|
+
*/
|
|
18
|
+
private static executeList;
|
|
19
|
+
/**
|
|
20
|
+
* Show details of a specific workflow
|
|
21
|
+
*/
|
|
22
|
+
private static executeInfo;
|
|
23
|
+
/**
|
|
24
|
+
* Execute a workflow
|
|
25
|
+
*/
|
|
26
|
+
private static executeWorkflow;
|
|
27
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow CLI Commands for NeuroLink
|
|
3
|
+
*
|
|
4
|
+
* Implements commands for workflow management and execution:
|
|
5
|
+
* - neurolink workflow list - List available predefined workflows
|
|
6
|
+
* - neurolink workflow info <name> - Show details of a workflow
|
|
7
|
+
* - neurolink workflow execute <name> <prompt> - Execute a workflow
|
|
8
|
+
*/
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import ora from "ora";
|
|
11
|
+
/**
|
|
12
|
+
* All predefined workflow configs keyed by their id.
|
|
13
|
+
* Loaded lazily via dynamic import to avoid circular deps.
|
|
14
|
+
*/
|
|
15
|
+
async function loadPredefinedWorkflows() {
|
|
16
|
+
const [consensus, fallback, adaptive, multiJudge] = await Promise.all([
|
|
17
|
+
import("../../lib/workflow/workflows/consensusWorkflow.js"),
|
|
18
|
+
import("../../lib/workflow/workflows/fallbackWorkflow.js"),
|
|
19
|
+
import("../../lib/workflow/workflows/adaptiveWorkflow.js"),
|
|
20
|
+
import("../../lib/workflow/workflows/multiJudgeWorkflow.js"),
|
|
21
|
+
]);
|
|
22
|
+
const configs = [
|
|
23
|
+
consensus.CONSENSUS_3_WORKFLOW,
|
|
24
|
+
consensus.CONSENSUS_3_FAST_WORKFLOW,
|
|
25
|
+
fallback.FAST_FALLBACK_WORKFLOW,
|
|
26
|
+
fallback.AGGRESSIVE_FALLBACK_WORKFLOW,
|
|
27
|
+
adaptive.QUALITY_MAX_WORKFLOW,
|
|
28
|
+
adaptive.SPEED_FIRST_WORKFLOW,
|
|
29
|
+
adaptive.BALANCED_ADAPTIVE_WORKFLOW,
|
|
30
|
+
multiJudge.MULTI_JUDGE_5_WORKFLOW,
|
|
31
|
+
multiJudge.MULTI_JUDGE_3_WORKFLOW,
|
|
32
|
+
];
|
|
33
|
+
const map = {};
|
|
34
|
+
for (const cfg of configs) {
|
|
35
|
+
map[cfg.id] = cfg;
|
|
36
|
+
}
|
|
37
|
+
return map;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Workflow CLI command factory
|
|
41
|
+
*/
|
|
42
|
+
export class WorkflowCommandFactory {
|
|
43
|
+
static createWorkflowCommands() {
|
|
44
|
+
return {
|
|
45
|
+
command: "workflow <subcommand>",
|
|
46
|
+
describe: "Manage and execute AI workflows",
|
|
47
|
+
builder: (yargs) => {
|
|
48
|
+
return yargs
|
|
49
|
+
.command("list", "List available predefined workflows", (y) => y, async () => {
|
|
50
|
+
await WorkflowCommandFactory.executeList();
|
|
51
|
+
})
|
|
52
|
+
.command("info <name>", "Show details of a workflow", (y) => y.positional("name", {
|
|
53
|
+
type: "string",
|
|
54
|
+
description: "Workflow name/id",
|
|
55
|
+
demandOption: true,
|
|
56
|
+
}), async (argv) => {
|
|
57
|
+
await WorkflowCommandFactory.executeInfo(argv);
|
|
58
|
+
})
|
|
59
|
+
.command("execute <name> <prompt>", "Execute a workflow with a prompt", (y) => y
|
|
60
|
+
.positional("name", {
|
|
61
|
+
type: "string",
|
|
62
|
+
description: "Workflow name/id",
|
|
63
|
+
demandOption: true,
|
|
64
|
+
})
|
|
65
|
+
.positional("prompt", {
|
|
66
|
+
type: "string",
|
|
67
|
+
description: "Prompt to send to the workflow",
|
|
68
|
+
demandOption: true,
|
|
69
|
+
})
|
|
70
|
+
.option("provider", {
|
|
71
|
+
type: "string",
|
|
72
|
+
description: "Override AI provider",
|
|
73
|
+
})
|
|
74
|
+
.option("model", {
|
|
75
|
+
type: "string",
|
|
76
|
+
description: "Override model name",
|
|
77
|
+
})
|
|
78
|
+
.option("timeout", {
|
|
79
|
+
type: "number",
|
|
80
|
+
description: "Execution timeout in milliseconds",
|
|
81
|
+
})
|
|
82
|
+
.option("verbose", {
|
|
83
|
+
type: "boolean",
|
|
84
|
+
description: "Enable verbose output",
|
|
85
|
+
default: false,
|
|
86
|
+
}), async (argv) => {
|
|
87
|
+
await WorkflowCommandFactory.executeWorkflow(argv);
|
|
88
|
+
})
|
|
89
|
+
.demandCommand(1, "Please specify a workflow subcommand");
|
|
90
|
+
},
|
|
91
|
+
handler: () => { },
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* List all predefined workflows
|
|
96
|
+
*/
|
|
97
|
+
static async executeList() {
|
|
98
|
+
const workflows = await loadPredefinedWorkflows();
|
|
99
|
+
const configs = Object.values(workflows);
|
|
100
|
+
console.info(chalk.bold("\nAvailable Workflows:\n"));
|
|
101
|
+
for (const cfg of configs) {
|
|
102
|
+
const tags = cfg.tags?.join(", ") || "";
|
|
103
|
+
console.info(` ${chalk.cyan(cfg.id.padEnd(24))} ${chalk.white(cfg.name)}`);
|
|
104
|
+
console.info(` ${"".padEnd(24)} ${chalk.gray(cfg.description || "")}`);
|
|
105
|
+
if (tags) {
|
|
106
|
+
console.info(` ${"".padEnd(24)} ${chalk.gray(`Tags: ${tags}`)}`);
|
|
107
|
+
}
|
|
108
|
+
console.info();
|
|
109
|
+
}
|
|
110
|
+
console.info(chalk.gray(`Total: ${configs.length} workflows`));
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Show details of a specific workflow
|
|
114
|
+
*/
|
|
115
|
+
static async executeInfo(argv) {
|
|
116
|
+
const workflows = await loadPredefinedWorkflows();
|
|
117
|
+
const cfg = workflows[argv.name];
|
|
118
|
+
if (!cfg) {
|
|
119
|
+
console.error(chalk.red(`Workflow "${argv.name}" not found.`));
|
|
120
|
+
console.info(chalk.gray(`Available: ${Object.keys(workflows).join(", ")}`));
|
|
121
|
+
process.exitCode = 1;
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
console.info(chalk.bold(`\nWorkflow: ${cfg.name}\n`));
|
|
125
|
+
console.info(` ID: ${cfg.id}`);
|
|
126
|
+
console.info(` Type: ${cfg.type}`);
|
|
127
|
+
console.info(` Version: ${cfg.version || "n/a"}`);
|
|
128
|
+
console.info(` Description: ${cfg.description || "n/a"}`);
|
|
129
|
+
if (cfg.models && cfg.models.length > 0) {
|
|
130
|
+
console.info(`\n Models:`);
|
|
131
|
+
for (const m of cfg.models) {
|
|
132
|
+
console.info(` - ${chalk.cyan(m.label || m.model)} (${m.provider})`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (cfg.modelGroups && cfg.modelGroups.length > 0) {
|
|
136
|
+
console.info(`\n Model Groups:`);
|
|
137
|
+
for (const group of cfg.modelGroups) {
|
|
138
|
+
console.info(` ${chalk.cyan(group.id)}:`);
|
|
139
|
+
for (const m of group.models) {
|
|
140
|
+
console.info(` - ${m.label || m.model} (${m.provider})`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (cfg.judge) {
|
|
145
|
+
console.info(`\n Judge: ${cfg.judge.model} (${cfg.judge.provider})`);
|
|
146
|
+
if (cfg.judge.criteria) {
|
|
147
|
+
console.info(` Criteria: ${cfg.judge.criteria.join(", ")}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (cfg.execution) {
|
|
151
|
+
console.info(`\n Execution:`);
|
|
152
|
+
if (cfg.execution.timeout) {
|
|
153
|
+
console.info(` Timeout: ${cfg.execution.timeout}ms`);
|
|
154
|
+
}
|
|
155
|
+
if (cfg.execution.parallelism) {
|
|
156
|
+
console.info(` Parallelism: ${cfg.execution.parallelism}`);
|
|
157
|
+
}
|
|
158
|
+
if (cfg.execution.minResponses) {
|
|
159
|
+
console.info(` Min Responses: ${cfg.execution.minResponses}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (cfg.tags && cfg.tags.length > 0) {
|
|
163
|
+
console.info(`\n Tags: ${cfg.tags.join(", ")}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Execute a workflow
|
|
168
|
+
*/
|
|
169
|
+
static async executeWorkflow(argv) {
|
|
170
|
+
const workflows = await loadPredefinedWorkflows();
|
|
171
|
+
let cfg = workflows[argv.name];
|
|
172
|
+
if (!cfg) {
|
|
173
|
+
console.error(chalk.red(`Workflow "${argv.name}" not found.`));
|
|
174
|
+
console.info(chalk.gray(`Available: ${Object.keys(workflows).join(", ")}`));
|
|
175
|
+
process.exitCode = 1;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
// Apply provider/model overrides if specified
|
|
179
|
+
if (argv.provider || argv.model) {
|
|
180
|
+
cfg = {
|
|
181
|
+
...cfg,
|
|
182
|
+
models: cfg.models?.map((m) => ({
|
|
183
|
+
...m,
|
|
184
|
+
provider: argv.provider || m.provider,
|
|
185
|
+
model: argv.model || m.model,
|
|
186
|
+
})),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
const spinner = ora("Executing workflow...").start();
|
|
190
|
+
try {
|
|
191
|
+
const { runWorkflow } = await import("../../lib/workflow/core/workflowRunner.js");
|
|
192
|
+
const result = await runWorkflow(cfg, {
|
|
193
|
+
prompt: argv.prompt,
|
|
194
|
+
timeout: argv.timeout,
|
|
195
|
+
verbose: argv.verbose,
|
|
196
|
+
});
|
|
197
|
+
spinner.stop();
|
|
198
|
+
if (result.content) {
|
|
199
|
+
console.info(result.content);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
console.info(chalk.yellow("Workflow completed but produced no content."));
|
|
203
|
+
if (result.reasoning) {
|
|
204
|
+
console.info(chalk.gray(`Reasoning: ${result.reasoning}`));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
spinner.stop();
|
|
210
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
211
|
+
console.error(chalk.red(`Workflow execution failed: ${msg}`));
|
|
212
|
+
process.exitCode = 1;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=workflow.js.map
|
|
@@ -335,7 +335,7 @@ export class CLICommandFactory {
|
|
|
335
335
|
},
|
|
336
336
|
thinkingLevel: {
|
|
337
337
|
type: "string",
|
|
338
|
-
description: "Thinking level for Gemini 3
|
|
338
|
+
description: "Thinking level for extended reasoning (Anthropic Claude, Gemini 2.5+, Gemini 3): minimal, low, medium, high",
|
|
339
339
|
choices: ["minimal", "low", "medium", "high"],
|
|
340
340
|
},
|
|
341
341
|
region: {
|
|
@@ -609,17 +609,10 @@ export class CLICommandFactory {
|
|
|
609
609
|
try {
|
|
610
610
|
// Use custom path or default
|
|
611
611
|
let imagePath;
|
|
612
|
-
const cwd = process.cwd();
|
|
613
612
|
if (options.imageOutput) {
|
|
614
|
-
imagePath = options.imageOutput;
|
|
615
|
-
// Validate path is within current working directory for security
|
|
616
|
-
const resolvedPath = path.resolve(imagePath);
|
|
617
|
-
if (!resolvedPath.startsWith(cwd + path.sep) &&
|
|
618
|
-
resolvedPath !== cwd) {
|
|
619
|
-
throw new Error(`Image output path must be within current directory: ${cwd}`);
|
|
620
|
-
}
|
|
613
|
+
imagePath = path.resolve(options.imageOutput);
|
|
621
614
|
// Create parent directory if needed (cross-platform)
|
|
622
|
-
const dir = path.dirname(
|
|
615
|
+
const dir = path.dirname(imagePath);
|
|
623
616
|
if (dir && dir !== "." && !fs.existsSync(dir)) {
|
|
624
617
|
fs.mkdirSync(dir, { recursive: true });
|
|
625
618
|
}
|
|
@@ -1648,6 +1641,20 @@ export class CLICommandFactory {
|
|
|
1648
1641
|
topK: argv.ragTopK,
|
|
1649
1642
|
}
|
|
1650
1643
|
: undefined,
|
|
1644
|
+
// TTS configuration
|
|
1645
|
+
tts: enhancedOptions.tts
|
|
1646
|
+
? {
|
|
1647
|
+
enabled: true,
|
|
1648
|
+
useAiResponse: true,
|
|
1649
|
+
voice: enhancedOptions.ttsVoice,
|
|
1650
|
+
format: enhancedOptions.ttsFormat ||
|
|
1651
|
+
undefined,
|
|
1652
|
+
speed: enhancedOptions.ttsSpeed,
|
|
1653
|
+
quality: enhancedOptions.ttsQuality,
|
|
1654
|
+
output: enhancedOptions.ttsOutput,
|
|
1655
|
+
play: enhancedOptions.ttsPlay,
|
|
1656
|
+
}
|
|
1657
|
+
: undefined,
|
|
1651
1658
|
});
|
|
1652
1659
|
if (spinner) {
|
|
1653
1660
|
if (isVideoMode) {
|
|
@@ -1865,16 +1872,59 @@ export class CLICommandFactory {
|
|
|
1865
1872
|
topK: argv.ragTopK,
|
|
1866
1873
|
}
|
|
1867
1874
|
: undefined,
|
|
1875
|
+
// TTS configuration
|
|
1876
|
+
tts: enhancedOptions.tts
|
|
1877
|
+
? {
|
|
1878
|
+
enabled: true,
|
|
1879
|
+
useAiResponse: true,
|
|
1880
|
+
voice: enhancedOptions.ttsVoice,
|
|
1881
|
+
format: enhancedOptions.ttsFormat ||
|
|
1882
|
+
undefined,
|
|
1883
|
+
speed: enhancedOptions.ttsSpeed,
|
|
1884
|
+
quality: enhancedOptions.ttsQuality,
|
|
1885
|
+
output: enhancedOptions.ttsOutput,
|
|
1886
|
+
play: enhancedOptions.ttsPlay,
|
|
1887
|
+
}
|
|
1888
|
+
: undefined,
|
|
1868
1889
|
});
|
|
1869
|
-
const
|
|
1870
|
-
await CLICommandFactory.displayStreamResults(stream,
|
|
1871
|
-
|
|
1890
|
+
const streamResult = await CLICommandFactory.processStreamWithTimeout(stream, options);
|
|
1891
|
+
await CLICommandFactory.displayStreamResults(stream, streamResult.content, options);
|
|
1892
|
+
// Handle image output from stream (image models emit image events)
|
|
1893
|
+
if (streamResult.imageBase64) {
|
|
1894
|
+
try {
|
|
1895
|
+
let imagePath;
|
|
1896
|
+
if (options.imageOutput) {
|
|
1897
|
+
imagePath = path.resolve(options.imageOutput);
|
|
1898
|
+
const dir = path.dirname(imagePath);
|
|
1899
|
+
if (dir && dir !== "." && !fs.existsSync(dir)) {
|
|
1900
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
else {
|
|
1904
|
+
const imageDir = "generated-images";
|
|
1905
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
1906
|
+
imagePath = path.join(imageDir, `image-${timestamp}.png`);
|
|
1907
|
+
if (!fs.existsSync(imageDir)) {
|
|
1908
|
+
fs.mkdirSync(imageDir, { recursive: true });
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
const imageBuffer = Buffer.from(streamResult.imageBase64, "base64");
|
|
1912
|
+
fs.writeFileSync(imagePath, imageBuffer);
|
|
1913
|
+
logger.always(`\nšø Generated image saved to: ${imagePath}`);
|
|
1914
|
+
logger.always(` Image size: ${(imageBuffer.length / 1024).toFixed(2)} KB`);
|
|
1915
|
+
}
|
|
1916
|
+
catch (error) {
|
|
1917
|
+
handleError(error, "Failed to save streamed image");
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
return streamResult.content;
|
|
1872
1921
|
}
|
|
1873
1922
|
/**
|
|
1874
1923
|
* Process stream with timeout handling
|
|
1875
1924
|
*/
|
|
1876
1925
|
static async processStreamWithTimeout(stream, options) {
|
|
1877
1926
|
let fullContent = "";
|
|
1927
|
+
let lastImageBase64;
|
|
1878
1928
|
let contentReceived = false;
|
|
1879
1929
|
const abortController = new AbortController();
|
|
1880
1930
|
// Create timeout promise for stream consumption (default: 30 seconds, respects user-provided timeout)
|
|
@@ -1934,10 +1984,20 @@ export class CLICommandFactory {
|
|
|
1934
1984
|
const isAudio = (o) => !!o &&
|
|
1935
1985
|
typeof o === "object" &&
|
|
1936
1986
|
o.type === "audio";
|
|
1937
|
-
const isImage = (o) =>
|
|
1938
|
-
typeof o
|
|
1939
|
-
|
|
1940
|
-
|
|
1987
|
+
const isImage = (o) => {
|
|
1988
|
+
if (!o || typeof o !== "object") {
|
|
1989
|
+
return false;
|
|
1990
|
+
}
|
|
1991
|
+
const record = o;
|
|
1992
|
+
if (record.type !== "image") {
|
|
1993
|
+
return false;
|
|
1994
|
+
}
|
|
1995
|
+
if (!record.imageOutput || typeof record.imageOutput !== "object") {
|
|
1996
|
+
return false;
|
|
1997
|
+
}
|
|
1998
|
+
return (typeof record.imageOutput.base64 ===
|
|
1999
|
+
"string");
|
|
2000
|
+
};
|
|
1941
2001
|
if (isText(evt)) {
|
|
1942
2002
|
process.stdout.write(evt.content);
|
|
1943
2003
|
fullContent += evt.content;
|
|
@@ -1948,8 +2008,7 @@ export class CLICommandFactory {
|
|
|
1948
2008
|
}
|
|
1949
2009
|
}
|
|
1950
2010
|
else if (isImage(evt)) {
|
|
1951
|
-
|
|
1952
|
-
// This handler ensures they're not silently dropped
|
|
2011
|
+
lastImageBase64 = evt.imageOutput.base64;
|
|
1953
2012
|
if (options.debug && !options.quiet) {
|
|
1954
2013
|
process.stdout.write("[image-received]");
|
|
1955
2014
|
}
|
|
@@ -1967,7 +2026,7 @@ export class CLICommandFactory {
|
|
|
1967
2026
|
if (!options.quiet) {
|
|
1968
2027
|
process.stdout.write("\n");
|
|
1969
2028
|
}
|
|
1970
|
-
return fullContent;
|
|
2029
|
+
return { content: fullContent, imageBase64: lastImageBase64 };
|
|
1971
2030
|
}
|
|
1972
2031
|
/**
|
|
1973
2032
|
* Display analytics and evaluation results
|
package/dist/cli/index.js
CHANGED
|
@@ -26,7 +26,6 @@ catch {
|
|
|
26
26
|
// Environment variables should be set externally in production
|
|
27
27
|
}
|
|
28
28
|
// Enhanced CLI with Professional UX
|
|
29
|
-
// Note: Workflow functionality is accessed via generate/stream commands with --workflow-config option
|
|
30
29
|
const cli = initializeCliParser();
|
|
31
30
|
// Execute CLI
|
|
32
31
|
(async () => {
|
package/dist/cli/parser.js
CHANGED
|
@@ -12,6 +12,7 @@ import { ServeCommandFactory } from "./commands/serve.js";
|
|
|
12
12
|
import { ragCommand } from "./commands/rag.js";
|
|
13
13
|
import { DocsCommandFactory } from "./commands/docs.js";
|
|
14
14
|
import { AuthCommandFactory } from "./factories/authCommandFactory.js";
|
|
15
|
+
import { WorkflowCommandFactory } from "./commands/workflow.js";
|
|
15
16
|
// Enhanced CLI with Professional UX
|
|
16
17
|
export function initializeCliParser() {
|
|
17
18
|
return (yargs(hideBin(process.argv))
|
|
@@ -178,6 +179,8 @@ export function initializeCliParser() {
|
|
|
178
179
|
// Docs MCP Server Command
|
|
179
180
|
.command(DocsCommandFactory.createDocsCommand())
|
|
180
181
|
// Auth Commands - Using AuthCommandFactory
|
|
181
|
-
.command(AuthCommandFactory.createAuthCommands())
|
|
182
|
+
.command(AuthCommandFactory.createAuthCommands())
|
|
183
|
+
// Workflow Commands
|
|
184
|
+
.command(WorkflowCommandFactory.createWorkflowCommands())); // Close the main return statement
|
|
182
185
|
}
|
|
183
186
|
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified credential masking utility for CLI setup commands.
|
|
3
|
+
*
|
|
4
|
+
* Preserves known provider prefixes (sk-, sk-ant-, AIza, AKIA) so
|
|
5
|
+
* users can identify which key is configured, while hiding the secret
|
|
6
|
+
* portion with asterisks.
|
|
7
|
+
*
|
|
8
|
+
* @param credential - Raw API key or secret
|
|
9
|
+
* @returns Masked string, e.g. "sk-****abcd"
|
|
10
|
+
*/
|
|
11
|
+
export declare function maskCredential(credential: string): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified credential masking utility for CLI setup commands.
|
|
3
|
+
*
|
|
4
|
+
* Preserves known provider prefixes (sk-, sk-ant-, AIza, AKIA) so
|
|
5
|
+
* users can identify which key is configured, while hiding the secret
|
|
6
|
+
* portion with asterisks.
|
|
7
|
+
*
|
|
8
|
+
* @param credential - Raw API key or secret
|
|
9
|
+
* @returns Masked string, e.g. "sk-****abcd"
|
|
10
|
+
*/
|
|
11
|
+
export function maskCredential(credential) {
|
|
12
|
+
if (!credential || credential.length <= 8) {
|
|
13
|
+
return "****";
|
|
14
|
+
}
|
|
15
|
+
// Provider-specific prefixes ordered longest-first so "sk-ant-" wins over "sk-"
|
|
16
|
+
const knownPrefixes = ["sk-ant-", "sk-", "AIza", "AKIA"];
|
|
17
|
+
const prefix = knownPrefixes.find((p) => credential.startsWith(p)) ??
|
|
18
|
+
credential.slice(0, 4);
|
|
19
|
+
const end = credential.slice(-4);
|
|
20
|
+
const stars = "*".repeat(Math.max(4, credential.length - prefix.length - 4));
|
|
21
|
+
return `${prefix}${stars}${end}`;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=maskCredential.js.map
|