@juspay/neurolink 10.12.8 → 11.0.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 +32 -0
- package/dist/browser/neurolink.min.js +399 -401
- package/dist/cli/commands/setup.d.ts +16 -1
- package/dist/cli/commands/setup.js +141 -3
- package/dist/core/baseProvider.js +3 -3
- package/dist/core/dynamicModels.d.ts +1 -1
- package/dist/core/dynamicModels.js +1 -23
- package/dist/core/modelConfiguration.d.ts +1 -70
- package/dist/core/modelConfiguration.js +0 -303
- package/dist/core/modules/GenerationHandler.js +38 -16
- package/dist/core/modules/structuredOutputPolicy.d.ts +2 -2
- package/dist/core/modules/structuredOutputPolicy.js +2 -2
- package/dist/factories/providerFactory.d.ts +15 -0
- package/dist/factories/providerFactory.js +27 -39
- package/dist/factories/providerRegistry.js +2 -2
- package/dist/lib/core/baseProvider.js +3 -3
- package/dist/lib/core/dynamicModels.d.ts +1 -1
- package/dist/lib/core/dynamicModels.js +1 -23
- package/dist/lib/core/modelConfiguration.d.ts +1 -70
- package/dist/lib/core/modelConfiguration.js +0 -303
- package/dist/lib/core/modules/GenerationHandler.js +38 -16
- package/dist/lib/core/modules/structuredOutputPolicy.d.ts +2 -2
- package/dist/lib/core/modules/structuredOutputPolicy.js +2 -2
- package/dist/lib/factories/providerFactory.d.ts +15 -0
- package/dist/lib/factories/providerFactory.js +27 -39
- package/dist/lib/factories/providerRegistry.js +2 -2
- package/dist/lib/models/anthropicModels.d.ts +0 -7
- package/dist/lib/models/anthropicModels.js +0 -9
- package/dist/lib/neurolink.d.ts +15 -0
- package/dist/lib/neurolink.js +77 -44
- package/dist/lib/providers/anthropic/client.js +17 -1
- package/dist/lib/providers/anthropic/constants.d.ts +0 -1
- package/dist/lib/providers/anthropic/constants.js +0 -2
- package/dist/lib/providers/anthropic/index.d.ts +0 -1
- package/dist/lib/providers/anthropic/index.js +0 -1
- package/dist/lib/providers/googleAiStudio/index.d.ts +0 -1
- package/dist/lib/providers/googleAiStudio/index.js +0 -1
- package/dist/lib/providers/googleNativeGemini3/index.d.ts +0 -1
- package/dist/lib/providers/googleNativeGemini3/index.js +0 -1
- package/dist/lib/providers/googleVertex/client.d.ts +0 -51
- package/dist/lib/providers/googleVertex/client.js +0 -678
- package/dist/lib/providers/huggingFace/client.d.ts +1 -1
- package/dist/lib/providers/huggingFace/client.js +1 -1
- package/dist/lib/providers/huggingFace/index.d.ts +0 -1
- package/dist/lib/providers/huggingFace/index.js +0 -1
- package/dist/lib/providers/jina.d.ts +0 -1
- package/dist/lib/providers/jina.js +0 -1
- package/dist/lib/providers/litellm/index.d.ts +0 -2
- package/dist/lib/providers/litellm/index.js +0 -2
- package/dist/lib/providers/llamaCpp.d.ts +1 -0
- package/dist/lib/providers/llamaCpp.js +3 -0
- package/dist/lib/providers/lmStudio.js +3 -23
- package/dist/lib/providers/nvidiaNim/index.d.ts +0 -1
- package/dist/lib/providers/nvidiaNim/index.js +0 -1
- package/dist/lib/providers/ollama/client.js +1 -23
- package/dist/lib/providers/ollama/index.d.ts +0 -1
- package/dist/lib/providers/ollama/index.js +0 -1
- package/dist/lib/providers/openAI/index.d.ts +0 -2
- package/dist/lib/providers/openAI/index.js +0 -2
- package/dist/lib/providers/openRouter/utils.d.ts +0 -2
- package/dist/lib/providers/openRouter/utils.js +0 -12
- package/dist/lib/providers/openaiChatCompletionsBase.d.ts +9 -0
- package/dist/lib/providers/openaiChatCompletionsBase.js +33 -0
- package/dist/lib/providers/perplexity.d.ts +2 -1
- package/dist/lib/providers/perplexity.js +2 -1
- package/dist/lib/providers/replicate.d.ts +0 -1
- package/dist/lib/providers/replicate.js +22 -9
- package/dist/lib/providers/voyage.d.ts +0 -1
- package/dist/lib/providers/voyage.js +0 -1
- package/dist/lib/types/index.d.ts +0 -1
- package/dist/lib/types/index.js +0 -1
- package/dist/lib/types/providers.d.ts +2 -11
- package/dist/lib/types/utilities.d.ts +29 -0
- package/dist/lib/utils/json/coerce.d.ts +21 -1
- package/dist/lib/utils/json/coerce.js +148 -11
- package/dist/lib/utils/providerConfig.d.ts +0 -8
- package/dist/lib/utils/providerConfig.js +0 -37
- package/dist/lib/utils/providerUtils.js +1 -25
- package/dist/models/anthropicModels.d.ts +0 -7
- package/dist/models/anthropicModels.js +0 -9
- package/dist/neurolink.d.ts +15 -0
- package/dist/neurolink.js +77 -44
- package/dist/providers/anthropic/client.js +17 -1
- package/dist/providers/anthropic/constants.d.ts +0 -1
- package/dist/providers/anthropic/constants.js +0 -2
- package/dist/providers/anthropic/index.d.ts +0 -1
- package/dist/providers/anthropic/index.js +0 -1
- package/dist/providers/googleAiStudio/index.d.ts +0 -1
- package/dist/providers/googleAiStudio/index.js +0 -1
- package/dist/providers/googleNativeGemini3/index.d.ts +0 -1
- package/dist/providers/googleNativeGemini3/index.js +0 -1
- package/dist/providers/googleVertex/client.d.ts +0 -51
- package/dist/providers/googleVertex/client.js +0 -678
- package/dist/providers/huggingFace/client.d.ts +1 -1
- package/dist/providers/huggingFace/client.js +1 -1
- package/dist/providers/huggingFace/index.d.ts +0 -1
- package/dist/providers/huggingFace/index.js +0 -1
- package/dist/providers/jina.d.ts +0 -1
- package/dist/providers/jina.js +0 -1
- package/dist/providers/litellm/index.d.ts +0 -2
- package/dist/providers/litellm/index.js +0 -2
- package/dist/providers/llamaCpp.d.ts +1 -0
- package/dist/providers/llamaCpp.js +3 -0
- package/dist/providers/lmStudio.js +3 -23
- package/dist/providers/nvidiaNim/index.d.ts +0 -1
- package/dist/providers/nvidiaNim/index.js +0 -1
- package/dist/providers/ollama/client.js +1 -23
- package/dist/providers/ollama/index.d.ts +0 -1
- package/dist/providers/ollama/index.js +0 -1
- package/dist/providers/openAI/index.d.ts +0 -2
- package/dist/providers/openAI/index.js +0 -2
- package/dist/providers/openRouter/utils.d.ts +0 -2
- package/dist/providers/openRouter/utils.js +0 -12
- package/dist/providers/openaiChatCompletionsBase.d.ts +9 -0
- package/dist/providers/openaiChatCompletionsBase.js +33 -0
- package/dist/providers/perplexity.d.ts +2 -1
- package/dist/providers/perplexity.js +2 -1
- package/dist/providers/replicate.d.ts +0 -1
- package/dist/providers/replicate.js +22 -9
- package/dist/providers/voyage.d.ts +0 -1
- package/dist/providers/voyage.js +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.js +0 -1
- package/dist/types/providers.d.ts +2 -11
- package/dist/types/utilities.d.ts +29 -0
- package/dist/utils/json/coerce.d.ts +21 -1
- package/dist/utils/json/coerce.js +148 -11
- package/dist/utils/providerConfig.d.ts +0 -8
- package/dist/utils/providerConfig.js +0 -37
- package/dist/utils/providerUtils.js +1 -25
- package/package.json +8 -6
- package/dist/lib/providers/anthropic/utils.d.ts +0 -7
- package/dist/lib/providers/anthropic/utils.js +0 -150
- package/dist/lib/providers/googleAiStudio/utils.d.ts +0 -2
- package/dist/lib/providers/googleAiStudio/utils.js +0 -19
- package/dist/lib/providers/googleNativeGemini3/constants.d.ts +0 -1
- package/dist/lib/providers/googleNativeGemini3/constants.js +0 -2
- package/dist/lib/providers/huggingFace/utils.d.ts +0 -2
- package/dist/lib/providers/huggingFace/utils.js +0 -8
- package/dist/lib/providers/index.d.ts +0 -33
- package/dist/lib/providers/index.js +0 -34
- package/dist/lib/providers/litellm/constants.d.ts +0 -1
- package/dist/lib/providers/litellm/constants.js +0 -3
- package/dist/lib/providers/litellm/utils.d.ts +0 -5
- package/dist/lib/providers/litellm/utils.js +0 -11
- package/dist/lib/providers/nvidiaNim/utils.d.ts +0 -9
- package/dist/lib/providers/nvidiaNim/utils.js +0 -101
- package/dist/lib/providers/ollama/utils.d.ts +0 -8
- package/dist/lib/providers/ollama/utils.js +0 -43
- package/dist/lib/providers/openAI/constants.d.ts +0 -1
- package/dist/lib/providers/openAI/constants.js +0 -3
- package/dist/lib/providers/openAI/utils.d.ts +0 -2
- package/dist/lib/providers/openAI/utils.js +0 -8
- package/dist/lib/types/universalProviderOptions.d.ts +0 -89
- package/dist/lib/types/universalProviderOptions.js +0 -55
- package/dist/providers/anthropic/utils.d.ts +0 -7
- package/dist/providers/anthropic/utils.js +0 -149
- package/dist/providers/googleAiStudio/utils.d.ts +0 -2
- package/dist/providers/googleAiStudio/utils.js +0 -18
- package/dist/providers/googleNativeGemini3/constants.d.ts +0 -1
- package/dist/providers/googleNativeGemini3/constants.js +0 -1
- package/dist/providers/huggingFace/utils.d.ts +0 -2
- package/dist/providers/huggingFace/utils.js +0 -7
- package/dist/providers/index.d.ts +0 -33
- package/dist/providers/index.js +0 -33
- package/dist/providers/litellm/constants.d.ts +0 -1
- package/dist/providers/litellm/constants.js +0 -2
- package/dist/providers/litellm/utils.d.ts +0 -5
- package/dist/providers/litellm/utils.js +0 -10
- package/dist/providers/nvidiaNim/utils.d.ts +0 -9
- package/dist/providers/nvidiaNim/utils.js +0 -100
- package/dist/providers/ollama/utils.d.ts +0 -8
- package/dist/providers/ollama/utils.js +0 -42
- package/dist/providers/openAI/constants.d.ts +0 -1
- package/dist/providers/openAI/constants.js +0 -2
- package/dist/providers/openAI/utils.d.ts +0 -2
- package/dist/providers/openAI/utils.js +0 -7
- package/dist/types/universalProviderOptions.d.ts +0 -89
- package/dist/types/universalProviderOptions.js +0 -54
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
* This addresses GitHub Copilot review comment about making model-specific logic configuration-based.
|
|
6
6
|
*/
|
|
7
7
|
import { logger } from "../utils/logger.js";
|
|
8
|
-
import fs from "fs";
|
|
9
|
-
import path from "path";
|
|
10
8
|
/**
|
|
11
9
|
* Model name constants - extracted from hardcoded values for better maintainability
|
|
12
10
|
* These constants can be overridden by environment variables
|
|
@@ -503,280 +501,6 @@ export class ModelConfigurationManager {
|
|
|
503
501
|
getAllConfigurations() {
|
|
504
502
|
return new Map(this.configurations);
|
|
505
503
|
}
|
|
506
|
-
/**
|
|
507
|
-
* Update provider configuration (runtime updates)
|
|
508
|
-
*/
|
|
509
|
-
updateProviderConfiguration(provider, config) {
|
|
510
|
-
this.configurations.set(provider, config);
|
|
511
|
-
this.lastUpdated = Date.now();
|
|
512
|
-
this.configSource = "dynamic";
|
|
513
|
-
logger.debug(`Updated configuration for provider: ${provider}`);
|
|
514
|
-
}
|
|
515
|
-
/**
|
|
516
|
-
* Parse YAML content with basic support
|
|
517
|
-
* For full YAML support, would need a proper YAML library
|
|
518
|
-
*/
|
|
519
|
-
parseYAMLContent(configContent) {
|
|
520
|
-
// Basic YAML parsing for simple configurations
|
|
521
|
-
try {
|
|
522
|
-
return JSON.parse(configContent);
|
|
523
|
-
}
|
|
524
|
-
catch {
|
|
525
|
-
return this.convertSimpleYAMLToJSON(configContent);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
/**
|
|
529
|
-
* Convert simple YAML to JSON object
|
|
530
|
-
* Handles basic key-value pairs only
|
|
531
|
-
*/
|
|
532
|
-
convertSimpleYAMLToJSON(configContent) {
|
|
533
|
-
const yamlLines = configContent.split("\n");
|
|
534
|
-
const jsonObj = {};
|
|
535
|
-
for (const line of yamlLines) {
|
|
536
|
-
const processedLine = this.processYAMLLine(line);
|
|
537
|
-
if (processedLine) {
|
|
538
|
-
jsonObj[processedLine.key] = processedLine.value;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
return jsonObj;
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* Process a single YAML line
|
|
545
|
-
* Returns key-value pair if valid, null otherwise
|
|
546
|
-
*/
|
|
547
|
-
processYAMLLine(line) {
|
|
548
|
-
const trimmedLine = line.trim();
|
|
549
|
-
if (!trimmedLine || trimmedLine.startsWith("#")) {
|
|
550
|
-
return null;
|
|
551
|
-
}
|
|
552
|
-
const colonIndex = trimmedLine.indexOf(":");
|
|
553
|
-
if (colonIndex <= 0) {
|
|
554
|
-
return null;
|
|
555
|
-
}
|
|
556
|
-
const key = trimmedLine.substring(0, colonIndex).trim();
|
|
557
|
-
const value = trimmedLine.substring(colonIndex + 1).trim();
|
|
558
|
-
return {
|
|
559
|
-
key,
|
|
560
|
-
value: this.convertYAMLValue(value),
|
|
561
|
-
};
|
|
562
|
-
}
|
|
563
|
-
/**
|
|
564
|
-
* Convert YAML value to appropriate JavaScript type
|
|
565
|
-
*/
|
|
566
|
-
convertYAMLValue(value) {
|
|
567
|
-
if (value === "true") {
|
|
568
|
-
return true;
|
|
569
|
-
}
|
|
570
|
-
if (value === "false") {
|
|
571
|
-
return false;
|
|
572
|
-
}
|
|
573
|
-
if (!isNaN(Number(value))) {
|
|
574
|
-
return Number(value);
|
|
575
|
-
}
|
|
576
|
-
return value.replace(/['"]/g, "");
|
|
577
|
-
}
|
|
578
|
-
/**
|
|
579
|
-
* Load configurations from external source
|
|
580
|
-
*/
|
|
581
|
-
loadConfigurationsFromFile(configPath) {
|
|
582
|
-
try {
|
|
583
|
-
// Check if file exists
|
|
584
|
-
if (!fs.existsSync(configPath)) {
|
|
585
|
-
throw new Error(`Configuration file not found: ${configPath}`);
|
|
586
|
-
}
|
|
587
|
-
// Read and parse configuration file
|
|
588
|
-
const configContent = fs.readFileSync(configPath, "utf8");
|
|
589
|
-
const fileExtension = path.extname(configPath).toLowerCase();
|
|
590
|
-
let configData;
|
|
591
|
-
if (fileExtension === ".json") {
|
|
592
|
-
configData = JSON.parse(configContent);
|
|
593
|
-
}
|
|
594
|
-
else if (fileExtension === ".yaml" || fileExtension === ".yml") {
|
|
595
|
-
configData = this.parseYAMLContent(configContent);
|
|
596
|
-
}
|
|
597
|
-
else {
|
|
598
|
-
throw new Error(`Unsupported configuration file format: ${fileExtension}. Supported formats: .json, .yaml, .yml`);
|
|
599
|
-
}
|
|
600
|
-
// Validate configuration structure
|
|
601
|
-
if (!configData || typeof configData !== "object") {
|
|
602
|
-
throw new Error("Invalid configuration format: must be an object");
|
|
603
|
-
}
|
|
604
|
-
const config = configData;
|
|
605
|
-
// Load provider configurations from file
|
|
606
|
-
if (config.providers && typeof config.providers === "object") {
|
|
607
|
-
const providers = config.providers;
|
|
608
|
-
for (const [providerName, providerConfig] of Object.entries(providers)) {
|
|
609
|
-
if (this.isValidProviderConfiguration(providerConfig)) {
|
|
610
|
-
this.configurations.set(providerName, providerConfig);
|
|
611
|
-
logger.debug(`Loaded configuration for provider: ${providerName}`);
|
|
612
|
-
}
|
|
613
|
-
else {
|
|
614
|
-
logger.warn(`Invalid configuration for provider: ${providerName}, skipping`);
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
// Load global model name overrides
|
|
619
|
-
if (config.modelNames && typeof config.modelNames === "object") {
|
|
620
|
-
const modelNames = config.modelNames;
|
|
621
|
-
this.applyModelNameOverrides(modelNames);
|
|
622
|
-
}
|
|
623
|
-
// Load global defaults
|
|
624
|
-
if (config.defaults && typeof config.defaults === "object") {
|
|
625
|
-
const defaults = config.defaults;
|
|
626
|
-
this.applyGlobalDefaults(defaults);
|
|
627
|
-
}
|
|
628
|
-
this.configSource = "file";
|
|
629
|
-
this.lastUpdated = Date.now();
|
|
630
|
-
logger.info(`Successfully loaded configurations from file: ${configPath}`);
|
|
631
|
-
logger.debug(`Loaded ${this.configurations.size} provider configurations`);
|
|
632
|
-
}
|
|
633
|
-
catch (error) {
|
|
634
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
635
|
-
logger.error(`Failed to load configurations from file: ${errorMessage}`);
|
|
636
|
-
throw new Error(`Configuration loading failed: ${errorMessage}`, {
|
|
637
|
-
cause: error,
|
|
638
|
-
});
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
/**
|
|
642
|
-
* Validate provider configuration structure
|
|
643
|
-
*/
|
|
644
|
-
isValidProviderConfiguration(config) {
|
|
645
|
-
if (!config || typeof config !== "object") {
|
|
646
|
-
return false;
|
|
647
|
-
}
|
|
648
|
-
const providerConfig = config;
|
|
649
|
-
// Check required fields
|
|
650
|
-
const requiredFields = [
|
|
651
|
-
"provider",
|
|
652
|
-
"models",
|
|
653
|
-
"defaultCost",
|
|
654
|
-
"requiredEnvVars",
|
|
655
|
-
"performance",
|
|
656
|
-
];
|
|
657
|
-
for (const field of requiredFields) {
|
|
658
|
-
if (!(field in providerConfig)) {
|
|
659
|
-
return false;
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
// Validate models structure
|
|
663
|
-
if (typeof providerConfig.models !== "object" || !providerConfig.models) {
|
|
664
|
-
return false;
|
|
665
|
-
}
|
|
666
|
-
const models = providerConfig.models;
|
|
667
|
-
const requiredTiers = ["fast", "balanced", "quality"];
|
|
668
|
-
for (const tier of requiredTiers) {
|
|
669
|
-
if (typeof models[tier] !== "string") {
|
|
670
|
-
return false;
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
// Validate defaultCost structure
|
|
674
|
-
if (typeof providerConfig.defaultCost !== "object" ||
|
|
675
|
-
!providerConfig.defaultCost) {
|
|
676
|
-
return false;
|
|
677
|
-
}
|
|
678
|
-
const defaultCost = providerConfig.defaultCost;
|
|
679
|
-
if (typeof defaultCost.input !== "number" ||
|
|
680
|
-
typeof defaultCost.output !== "number") {
|
|
681
|
-
return false;
|
|
682
|
-
}
|
|
683
|
-
// Validate requiredEnvVars
|
|
684
|
-
if (!Array.isArray(providerConfig.requiredEnvVars)) {
|
|
685
|
-
return false;
|
|
686
|
-
}
|
|
687
|
-
// Validate performance structure
|
|
688
|
-
if (typeof providerConfig.performance !== "object" ||
|
|
689
|
-
!providerConfig.performance) {
|
|
690
|
-
return false;
|
|
691
|
-
}
|
|
692
|
-
const performance = providerConfig.performance;
|
|
693
|
-
const perfFields = ["speed", "quality", "cost"];
|
|
694
|
-
for (const field of perfFields) {
|
|
695
|
-
if (typeof performance[field] !== "number") {
|
|
696
|
-
return false;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
return true;
|
|
700
|
-
}
|
|
701
|
-
/**
|
|
702
|
-
* Apply model name overrides from configuration file
|
|
703
|
-
*/
|
|
704
|
-
applyModelNameOverrides(modelNames) {
|
|
705
|
-
try {
|
|
706
|
-
// Apply overrides to existing configurations
|
|
707
|
-
for (const [providerKey, providerModels] of Object.entries(modelNames)) {
|
|
708
|
-
if (typeof providerModels === "object" && providerModels) {
|
|
709
|
-
const models = providerModels;
|
|
710
|
-
const existingConfig = this.configurations.get(providerKey);
|
|
711
|
-
if (existingConfig) {
|
|
712
|
-
// Update existing configuration
|
|
713
|
-
for (const [tier, model] of Object.entries(models)) {
|
|
714
|
-
if (typeof model === "string" &&
|
|
715
|
-
["fast", "balanced", "quality"].includes(tier)) {
|
|
716
|
-
existingConfig.models[tier] = model;
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
this.configurations.set(providerKey, existingConfig);
|
|
720
|
-
logger.debug(`Applied model name overrides for provider: ${providerKey}`);
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
catch (error) {
|
|
726
|
-
logger.warn(`Failed to apply model name overrides: ${error instanceof Error ? error.message : String(error)}`);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
/**
|
|
730
|
-
* Apply global default configurations
|
|
731
|
-
*/
|
|
732
|
-
applyGlobalDefaults(defaults) {
|
|
733
|
-
try {
|
|
734
|
-
// Apply global defaults to all existing configurations
|
|
735
|
-
for (const [providerName, config] of this.configurations.entries()) {
|
|
736
|
-
let updated = false;
|
|
737
|
-
// Apply default cost overrides
|
|
738
|
-
if (defaults.defaultCost && typeof defaults.defaultCost === "object") {
|
|
739
|
-
const defaultCost = defaults.defaultCost;
|
|
740
|
-
if (typeof defaultCost.input === "number") {
|
|
741
|
-
config.defaultCost.input = defaultCost.input;
|
|
742
|
-
updated = true;
|
|
743
|
-
}
|
|
744
|
-
if (typeof defaultCost.output === "number") {
|
|
745
|
-
config.defaultCost.output = defaultCost.output;
|
|
746
|
-
updated = true;
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
// Apply performance overrides
|
|
750
|
-
if (defaults.performance && typeof defaults.performance === "object") {
|
|
751
|
-
const performance = defaults.performance;
|
|
752
|
-
["speed", "quality", "cost"].forEach((field) => {
|
|
753
|
-
if (typeof performance[field] === "number") {
|
|
754
|
-
config.performance[field] =
|
|
755
|
-
performance[field];
|
|
756
|
-
updated = true;
|
|
757
|
-
}
|
|
758
|
-
});
|
|
759
|
-
}
|
|
760
|
-
if (updated) {
|
|
761
|
-
this.configurations.set(providerName, config);
|
|
762
|
-
logger.debug(`Applied global defaults to provider: ${providerName}`);
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
catch (error) {
|
|
767
|
-
logger.warn(`Failed to apply global defaults: ${error instanceof Error ? error.message : String(error)}`);
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
/**
|
|
771
|
-
* Get configuration metadata
|
|
772
|
-
*/
|
|
773
|
-
getConfigurationMeta() {
|
|
774
|
-
return {
|
|
775
|
-
source: this.configSource,
|
|
776
|
-
lastUpdated: this.lastUpdated,
|
|
777
|
-
providerCount: this.configurations.size,
|
|
778
|
-
};
|
|
779
|
-
}
|
|
780
504
|
/**
|
|
781
505
|
* Get model for specific tier and provider
|
|
782
506
|
*/
|
|
@@ -822,31 +546,4 @@ export class ModelConfigurationManager {
|
|
|
822
546
|
* Global instance accessor
|
|
823
547
|
*/
|
|
824
548
|
export const modelConfig = ModelConfigurationManager.getInstance();
|
|
825
|
-
/**
|
|
826
|
-
* Convenience functions for common operations
|
|
827
|
-
*/
|
|
828
|
-
/**
|
|
829
|
-
* Get provider configuration (backwards compatible)
|
|
830
|
-
*/
|
|
831
|
-
export function getProviderConfiguration(provider) {
|
|
832
|
-
return modelConfig.getProviderConfiguration(provider);
|
|
833
|
-
}
|
|
834
|
-
/**
|
|
835
|
-
* Get model for tier (backwards compatible)
|
|
836
|
-
*/
|
|
837
|
-
export function getModelForTier(provider, tier) {
|
|
838
|
-
return modelConfig.getModelForTier(provider, tier);
|
|
839
|
-
}
|
|
840
|
-
/**
|
|
841
|
-
* Get cost information (backwards compatible)
|
|
842
|
-
*/
|
|
843
|
-
export function getCostInfo(provider, model) {
|
|
844
|
-
return modelConfig.getCostInfo(provider, model);
|
|
845
|
-
}
|
|
846
|
-
/**
|
|
847
|
-
* Check provider availability (backwards compatible)
|
|
848
|
-
*/
|
|
849
|
-
export function isProviderAvailable(provider) {
|
|
850
|
-
return modelConfig.isProviderAvailable(provider);
|
|
851
|
-
}
|
|
852
549
|
//# sourceMappingURL=modelConfiguration.js.map
|
|
@@ -25,7 +25,7 @@ import { calculateCacheSavingsPercent, extractCacheCreationTokens, extractCacheR
|
|
|
25
25
|
import { DEFAULT_MAX_STEPS, DEFAULT_WRAPUP_TIME_LEAD_MS, } from "../constants.js";
|
|
26
26
|
import { createStepBudgetGuard, estimateFixedOverheadTokens, } from "../../context/stepBudgetGuard.js";
|
|
27
27
|
import { isTemperatureDeprecatedError, isSchemaComplexityError, isToolsSchemaConflictError, isToolsSchemaExclusionInForce, } from "./structuredOutputPolicy.js";
|
|
28
|
-
import { coerceJsonToSchema } from "../../utils/json/coerce.js";
|
|
28
|
+
import { coerceJsonToSchema, recoverScalarRoot, schemaAccepts, } from "../../utils/json/coerce.js";
|
|
29
29
|
import { convertZodToJsonSchema } from "../../utils/schemaConversion.js";
|
|
30
30
|
import { NoObjectGeneratedError } from "../../utils/generationErrors.js";
|
|
31
31
|
import { Output, stepCountIs } from "../../utils/tool.js";
|
|
@@ -247,8 +247,8 @@ export class GenerationHandler {
|
|
|
247
247
|
// JSON Schema to the provider instead: it appends an additive
|
|
248
248
|
// `final_result` tool and returns the answer as that tool's arguments,
|
|
249
249
|
// keeping the real tools callable. Bedrock is deliberately excluded — it
|
|
250
|
-
//
|
|
251
|
-
// handling.
|
|
250
|
+
// talks to the raw AWS SDK directly, not an ai-sdk provider package, and
|
|
251
|
+
// has no such handling.
|
|
252
252
|
const finalResultSchema = this.providerName === "anthropic" &&
|
|
253
253
|
!!options.schema &&
|
|
254
254
|
shouldUseTools &&
|
|
@@ -800,26 +800,35 @@ export class GenerationHandler {
|
|
|
800
800
|
}
|
|
801
801
|
return coerced.content;
|
|
802
802
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
803
|
+
const scalar = recoverScalarRoot(strippedText, options.schema);
|
|
804
|
+
switch (scalar.kind) {
|
|
805
|
+
case "empty":
|
|
806
806
|
// A JSON-encoded empty string is an EMPTY completion, not a
|
|
807
807
|
// recovered scalar — normalize to a true empty ('' content, no
|
|
808
808
|
// structuredData) so callers' empty-response handling fires
|
|
809
809
|
// instead of a literal '""' reaching the user.
|
|
810
810
|
logger.warn("[GenerationHandler] schema requested but the model returned an empty JSON string; normalizing to empty content", { provider: this.providerName, model: this.modelName });
|
|
811
811
|
return "";
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
812
|
+
case "accepted":
|
|
813
|
+
// A JSON scalar root is only real structured data when the caller's
|
|
814
|
+
// schema actually accepts it. Under an OBJECT schema a recovered
|
|
815
|
+
// string/number is the raw completion in disguise (the shape a
|
|
816
|
+
// truncated response degrades to) — publishing it would hand the
|
|
817
|
+
// caller a `structuredData` that violates the schema they passed.
|
|
818
|
+
structuredData = scalar.value;
|
|
819
|
+
return strippedText;
|
|
820
|
+
case "rejected":
|
|
821
|
+
logger.warn("[GenerationHandler] recovered a JSON scalar the requested schema rejects; leaving structuredData unset", {
|
|
822
|
+
provider: this.providerName,
|
|
823
|
+
model: this.modelName,
|
|
824
|
+
scalarType: typeof scalar.value,
|
|
825
|
+
});
|
|
826
|
+
return strippedText;
|
|
827
|
+
case "nullish":
|
|
828
|
+
case "not-json":
|
|
829
|
+
logger.warn("[GenerationHandler] schema requested but no JSON could be recovered from model text; returning raw text", { provider: this.providerName, model: this.modelName });
|
|
815
830
|
return strippedText;
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
catch {
|
|
819
|
-
// not JSON at all — fall through to raw text + WARN
|
|
820
831
|
}
|
|
821
|
-
logger.warn("[GenerationHandler] schema requested but no JSON could be recovered from model text; returning raw text", { provider: this.providerName, model: this.modelName });
|
|
822
|
-
return strippedText;
|
|
823
832
|
};
|
|
824
833
|
if (useStructuredOutput) {
|
|
825
834
|
try {
|
|
@@ -834,7 +843,20 @@ export class GenerationHandler {
|
|
|
834
843
|
// (a string identical to the step text) and coerce it instead.
|
|
835
844
|
const rawTextEcho = typeof experimentalOutput === "string" &&
|
|
836
845
|
experimentalOutput === (generateResult.text ?? "");
|
|
837
|
-
|
|
846
|
+
// The equality check above only catches an EXACT echo. On a multi-step
|
|
847
|
+
// or truncated turn the echo can differ from `text` (a different step's
|
|
848
|
+
// text, a fence, trailing whitespace), and a raw string would then be
|
|
849
|
+
// published as `structuredData` under an object schema — the "returned
|
|
850
|
+
// a string instead of the schema object" failure. A string is trusted
|
|
851
|
+
// as structured output ONLY when the caller's schema accepts it
|
|
852
|
+
// (string-root schemas keep working); otherwise it is coerced like any
|
|
853
|
+
// other raw model text.
|
|
854
|
+
const untrustedStringOutput = typeof experimentalOutput === "string" &&
|
|
855
|
+
!!options.schema &&
|
|
856
|
+
!schemaAccepts(options.schema, experimentalOutput);
|
|
857
|
+
if (experimentalOutput !== undefined &&
|
|
858
|
+
!rawTextEcho &&
|
|
859
|
+
!untrustedStringOutput) {
|
|
838
860
|
// AI-SDK already parsed + schema-validated the object. Expose it
|
|
839
861
|
// directly and serialise canonically — no hand-parsing needed.
|
|
840
862
|
structuredData = experimentalOutput;
|
|
@@ -29,8 +29,8 @@ export declare function isGeminiProvider(providerName: string, modelName: string
|
|
|
29
29
|
* `providerOptions.anthropic.finalResultSchema`, and the provider appends an
|
|
30
30
|
* additive `final_result` tool (see providers/anthropic/structuredOutput.ts) —
|
|
31
31
|
* schema enforcement without giving up tool calling. "bedrock" has no such
|
|
32
|
-
* handling (it
|
|
33
|
-
* falls back to text-mode coercion.
|
|
32
|
+
* handling (it talks to the raw AWS SDK directly, not an ai-sdk provider
|
|
33
|
+
* package) and still falls back to text-mode coercion.
|
|
34
34
|
*/
|
|
35
35
|
export declare function isNativeAnthropicProvider(providerName: string): boolean;
|
|
36
36
|
/**
|
|
@@ -39,8 +39,8 @@ export function isGeminiProvider(providerName, modelName) {
|
|
|
39
39
|
* `providerOptions.anthropic.finalResultSchema`, and the provider appends an
|
|
40
40
|
* additive `final_result` tool (see providers/anthropic/structuredOutput.ts) —
|
|
41
41
|
* schema enforcement without giving up tool calling. "bedrock" has no such
|
|
42
|
-
* handling (it
|
|
43
|
-
* falls back to text-mode coercion.
|
|
42
|
+
* handling (it talks to the raw AWS SDK directly, not an ai-sdk provider
|
|
43
|
+
* package) and still falls back to text-mode coercion.
|
|
44
44
|
*/
|
|
45
45
|
export function isNativeAnthropicProvider(providerName) {
|
|
46
46
|
return providerName === "anthropic" || providerName === "bedrock";
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import type { NeuroLink } from "../neurolink.js";
|
|
2
2
|
import type { AIProviderName } from "../constants/enums.js";
|
|
3
3
|
import type { AIProvider, NeurolinkCredentials, ProviderConstructor, ProviderRegistration } from "../types/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* Maps registered provider names to NeurolinkCredentials keys. Most names
|
|
6
|
+
* match (openai, anthropic, vertex, bedrock, etc.) but every kebab-case
|
|
7
|
+
* provider whose canonical credentials key is camelCase — or otherwise
|
|
8
|
+
* spelled differently — MUST be mapped here, otherwise per-call/instance
|
|
9
|
+
* credential overrides silently get dropped (createProvider() looks up
|
|
10
|
+
* credentials["lm-studio"], which is undefined, while the caller wrote
|
|
11
|
+
* credentials.lmStudio).
|
|
12
|
+
*/
|
|
13
|
+
export declare const CREDENTIAL_KEY_MAP: Record<string, string>;
|
|
14
|
+
/**
|
|
15
|
+
* Resolve a registered provider name to its NeurolinkCredentials key.
|
|
16
|
+
* Falls back to the provider name itself when no remapping is needed.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveCredentialKey(providerName: string): string;
|
|
4
19
|
/**
|
|
5
20
|
* True Factory Pattern implementation for AI Providers
|
|
6
21
|
* Uses registration-based approach to eliminate switch statements
|
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
import { logger } from "../utils/logger.js";
|
|
2
2
|
// Pure factory pattern with no hardcoded imports
|
|
3
3
|
// All providers loaded dynamically via registry to avoid circular dependencies
|
|
4
|
+
/**
|
|
5
|
+
* Maps registered provider names to NeurolinkCredentials keys. Most names
|
|
6
|
+
* match (openai, anthropic, vertex, bedrock, etc.) but every kebab-case
|
|
7
|
+
* provider whose canonical credentials key is camelCase — or otherwise
|
|
8
|
+
* spelled differently — MUST be mapped here, otherwise per-call/instance
|
|
9
|
+
* credential overrides silently get dropped (createProvider() looks up
|
|
10
|
+
* credentials["lm-studio"], which is undefined, while the caller wrote
|
|
11
|
+
* credentials.lmStudio).
|
|
12
|
+
*/
|
|
13
|
+
export const CREDENTIAL_KEY_MAP = {
|
|
14
|
+
"google-ai": "googleAiStudio",
|
|
15
|
+
"openai-compatible": "openaiCompatible",
|
|
16
|
+
huggingface: "huggingFace",
|
|
17
|
+
"lm-studio": "lmStudio",
|
|
18
|
+
"nvidia-nim": "nvidiaNim",
|
|
19
|
+
"together-ai": "together",
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Resolve a registered provider name to its NeurolinkCredentials key.
|
|
23
|
+
* Falls back to the provider name itself when no remapping is needed.
|
|
24
|
+
*/
|
|
25
|
+
export function resolveCredentialKey(providerName) {
|
|
26
|
+
return (CREDENTIAL_KEY_MAP[providerName.toLowerCase()] ?? providerName.toLowerCase());
|
|
27
|
+
}
|
|
4
28
|
/**
|
|
5
29
|
* True Factory Pattern implementation for AI Providers
|
|
6
30
|
* Uses registration-based approach to eliminate switch statements
|
|
@@ -58,21 +82,7 @@ export class ProviderFactory {
|
|
|
58
82
|
// Fallback to registry default if no env var
|
|
59
83
|
model = model || registration.defaultModel;
|
|
60
84
|
}
|
|
61
|
-
|
|
62
|
-
// Most names match (openai, anthropic, vertex, bedrock, etc.)
|
|
63
|
-
// but every kebab-case provider whose canonical credentials key is
|
|
64
|
-
// camelCase MUST be mapped here — otherwise per-call credential
|
|
65
|
-
// overrides silently get dropped (the factory looks up
|
|
66
|
-
// credentials["lm-studio"] which is undefined while the user wrote
|
|
67
|
-
// credentials.lmStudio).
|
|
68
|
-
const credentialKeyMap = {
|
|
69
|
-
"google-ai": "googleAiStudio",
|
|
70
|
-
"openai-compatible": "openaiCompatible",
|
|
71
|
-
huggingface: "huggingFace",
|
|
72
|
-
"lm-studio": "lmStudio",
|
|
73
|
-
"nvidia-nim": "nvidiaNim",
|
|
74
|
-
};
|
|
75
|
-
const credKey = credentialKeyMap[normalizedName] ?? normalizedName;
|
|
85
|
+
const credKey = resolveCredentialKey(normalizedName);
|
|
76
86
|
// Extract provider-scoped credential slice (e.g. credentials.openai for OpenAI)
|
|
77
87
|
const scopedCredentials = credentials
|
|
78
88
|
? credentials[credKey]
|
|
@@ -81,30 +91,8 @@ export class ProviderFactory {
|
|
|
81
91
|
if (typeof registration.constructor !== "function") {
|
|
82
92
|
throw new Error(`Invalid constructor for provider ${providerName}: not a function`);
|
|
83
93
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const factoryResult = registration.constructor(model, resolvedProviderName, sdk, region, scopedCredentials);
|
|
87
|
-
// Handle both sync and async results
|
|
88
|
-
result =
|
|
89
|
-
factoryResult instanceof Promise
|
|
90
|
-
? await factoryResult
|
|
91
|
-
: factoryResult;
|
|
92
|
-
}
|
|
93
|
-
catch (factoryError) {
|
|
94
|
-
if (registration.constructor.prototype &&
|
|
95
|
-
registration.constructor.prototype.constructor ===
|
|
96
|
-
registration.constructor) {
|
|
97
|
-
try {
|
|
98
|
-
result = new registration.constructor(model, resolvedProviderName, sdk, region, scopedCredentials);
|
|
99
|
-
}
|
|
100
|
-
catch (constructorError) {
|
|
101
|
-
throw new Error(`Both factory function and constructor failed. Factory error: ${factoryError}. Constructor error: ${constructorError}`, { cause: constructorError });
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
throw factoryError;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
94
|
+
const factoryResult = registration.constructor(model, resolvedProviderName, sdk, region, scopedCredentials);
|
|
95
|
+
const result = factoryResult instanceof Promise ? await factoryResult : factoryResult;
|
|
108
96
|
return result;
|
|
109
97
|
}
|
|
110
98
|
catch (error) {
|
|
@@ -104,10 +104,10 @@ export class ProviderRegistry {
|
|
|
104
104
|
return new GoogleVertexProvider(modelName, providerName, sdk, region, vertexCreds);
|
|
105
105
|
}, VertexModels.CLAUDE_4_6_SONNET, ["vertex", "googleVertex"]);
|
|
106
106
|
// Register Hugging Face provider (Unified Router implementation)
|
|
107
|
-
ProviderFactory.registerProvider(AIProviderName.HUGGINGFACE, async (modelName, _providerName,
|
|
107
|
+
ProviderFactory.registerProvider(AIProviderName.HUGGINGFACE, async (modelName, _providerName, sdk, region, credentials) => {
|
|
108
108
|
const hfCreds = credentials;
|
|
109
109
|
const { HuggingFaceProvider } = await import("../providers/huggingFace/index.js");
|
|
110
|
-
return new HuggingFaceProvider(modelName,
|
|
110
|
+
return new HuggingFaceProvider(modelName, sdk, region, hfCreds);
|
|
111
111
|
}, process.env.HUGGINGFACE_MODEL ||
|
|
112
112
|
HuggingFaceModels.QWEN_2_5_72B_INSTRUCT, ["huggingface", "hf"]);
|
|
113
113
|
// Register Mistral AI provider
|
|
@@ -242,13 +242,6 @@ export declare function getContextWindow(model: string): number;
|
|
|
242
242
|
* @returns The max output tokens, or 0 if model not found
|
|
243
243
|
*/
|
|
244
244
|
export declare function getMaxOutputTokens(model: string): number;
|
|
245
|
-
/**
|
|
246
|
-
* Check if a model supports vision/image input
|
|
247
|
-
*
|
|
248
|
-
* @param model - The model ID
|
|
249
|
-
* @returns true if the model supports vision
|
|
250
|
-
*/
|
|
251
|
-
export declare function supportsVision(model: string): boolean;
|
|
252
245
|
/**
|
|
253
246
|
* Check if a model supports extended thinking
|
|
254
247
|
*
|
|
@@ -531,15 +531,6 @@ export function getContextWindow(model) {
|
|
|
531
531
|
export function getMaxOutputTokens(model) {
|
|
532
532
|
return MODEL_METADATA[model]?.maxOutputTokens ?? 0;
|
|
533
533
|
}
|
|
534
|
-
/**
|
|
535
|
-
* Check if a model supports vision/image input
|
|
536
|
-
*
|
|
537
|
-
* @param model - The model ID
|
|
538
|
-
* @returns true if the model supports vision
|
|
539
|
-
*/
|
|
540
|
-
export function supportsVision(model) {
|
|
541
|
-
return MODEL_METADATA[model]?.supportsVision ?? false;
|
|
542
|
-
}
|
|
543
534
|
/**
|
|
544
535
|
* Check if a model supports extended thinking
|
|
545
536
|
*
|
package/dist/lib/neurolink.d.ts
CHANGED
|
@@ -775,6 +775,21 @@ export declare class NeuroLink {
|
|
|
775
775
|
private applyClassifierRouting;
|
|
776
776
|
private prepareGenerateAugmentations;
|
|
777
777
|
private buildGenerateTextOptions;
|
|
778
|
+
/**
|
|
779
|
+
* Provider-agnostic JSON recovery for schema requests. Structured-output
|
|
780
|
+
* enforcement makes valid JSON the overwhelming case; for every other
|
|
781
|
+
* provider path — including generate() overrides (Vertex, Anthropic,
|
|
782
|
+
* Bedrock, Google AI Studio) — object/array roots are recovered here via
|
|
783
|
+
* balanced-scan + jsonrepair and scalar JSON roots via plain JSON.parse,
|
|
784
|
+
* with the parsed value exposed as `structuredData`. If nothing JSON-shaped
|
|
785
|
+
* is recoverable (pure prose), the raw text is returned, `structuredData`
|
|
786
|
+
* stays undefined, and a WARN makes the case observable.
|
|
787
|
+
*
|
|
788
|
+
* Mutates `textResult` in place, and must run BEFORE the end-of-generation
|
|
789
|
+
* emits so event consumers see the same content/structuredData the caller
|
|
790
|
+
* receives.
|
|
791
|
+
*/
|
|
792
|
+
private recoverStructuredData;
|
|
778
793
|
private finalizeGenerateRequestResult;
|
|
779
794
|
private emitGenerateErrorEvent;
|
|
780
795
|
/**
|