@juspay/neurolink 7.1.0 → 7.3.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.
Files changed (92) hide show
  1. package/CHANGELOG.md +15 -2
  2. package/README.md +16 -11
  3. package/dist/cli/commands/config.d.ts +2 -2
  4. package/dist/cli/commands/config.js +22 -21
  5. package/dist/cli/commands/mcp.d.ts +79 -0
  6. package/dist/cli/commands/mcp.js +916 -0
  7. package/dist/cli/commands/models.d.ts +63 -0
  8. package/dist/cli/commands/models.js +653 -0
  9. package/dist/cli/commands/ollama.js +56 -55
  10. package/dist/cli/factories/commandFactory.d.ts +14 -0
  11. package/dist/cli/factories/commandFactory.js +346 -47
  12. package/dist/cli/index.js +25 -10
  13. package/dist/cli/utils/completeSetup.js +9 -8
  14. package/dist/cli/utils/envManager.js +7 -6
  15. package/dist/cli/utils/interactiveSetup.js +20 -19
  16. package/dist/core/analytics.js +25 -38
  17. package/dist/core/baseProvider.d.ts +8 -0
  18. package/dist/core/baseProvider.js +177 -68
  19. package/dist/core/constants.d.ts +11 -0
  20. package/dist/core/constants.js +17 -0
  21. package/dist/core/evaluation.js +25 -14
  22. package/dist/core/factory.js +19 -18
  23. package/dist/core/streamAnalytics.d.ts +65 -0
  24. package/dist/core/streamAnalytics.js +125 -0
  25. package/dist/lib/core/analytics.js +25 -38
  26. package/dist/lib/core/baseProvider.d.ts +8 -0
  27. package/dist/lib/core/baseProvider.js +177 -68
  28. package/dist/lib/core/constants.d.ts +11 -0
  29. package/dist/lib/core/constants.js +17 -0
  30. package/dist/lib/core/evaluation.js +25 -14
  31. package/dist/lib/core/factory.js +19 -18
  32. package/dist/lib/core/streamAnalytics.d.ts +65 -0
  33. package/dist/lib/core/streamAnalytics.js +125 -0
  34. package/dist/lib/models/modelRegistry.d.ts +132 -0
  35. package/dist/lib/models/modelRegistry.js +483 -0
  36. package/dist/lib/models/modelResolver.d.ts +115 -0
  37. package/dist/lib/models/modelResolver.js +467 -0
  38. package/dist/lib/neurolink.d.ts +4 -1
  39. package/dist/lib/neurolink.js +101 -67
  40. package/dist/lib/providers/anthropic.js +3 -0
  41. package/dist/lib/providers/googleAiStudio.js +13 -0
  42. package/dist/lib/providers/huggingFace.js +15 -3
  43. package/dist/lib/providers/mistral.js +19 -7
  44. package/dist/lib/providers/ollama.js +31 -7
  45. package/dist/lib/providers/openAI.js +12 -0
  46. package/dist/lib/sdk/toolRegistration.js +2 -2
  47. package/dist/lib/types/cli.d.ts +56 -1
  48. package/dist/lib/types/contextTypes.d.ts +110 -0
  49. package/dist/lib/types/contextTypes.js +176 -0
  50. package/dist/lib/types/index.d.ts +4 -1
  51. package/dist/lib/types/mcpTypes.d.ts +118 -7
  52. package/dist/lib/types/providers.d.ts +81 -0
  53. package/dist/lib/types/streamTypes.d.ts +44 -7
  54. package/dist/lib/types/tools.d.ts +9 -0
  55. package/dist/lib/types/universalProviderOptions.d.ts +3 -1
  56. package/dist/lib/types/universalProviderOptions.js +2 -1
  57. package/dist/lib/utils/logger.d.ts +7 -0
  58. package/dist/lib/utils/logger.js +11 -0
  59. package/dist/lib/utils/performance.d.ts +105 -0
  60. package/dist/lib/utils/performance.js +210 -0
  61. package/dist/lib/utils/retryHandler.d.ts +89 -0
  62. package/dist/lib/utils/retryHandler.js +269 -0
  63. package/dist/models/modelRegistry.d.ts +132 -0
  64. package/dist/models/modelRegistry.js +483 -0
  65. package/dist/models/modelResolver.d.ts +115 -0
  66. package/dist/models/modelResolver.js +468 -0
  67. package/dist/neurolink.d.ts +4 -1
  68. package/dist/neurolink.js +101 -67
  69. package/dist/providers/anthropic.js +3 -0
  70. package/dist/providers/googleAiStudio.js +13 -0
  71. package/dist/providers/huggingFace.js +15 -3
  72. package/dist/providers/mistral.js +19 -7
  73. package/dist/providers/ollama.js +31 -7
  74. package/dist/providers/openAI.js +12 -0
  75. package/dist/sdk/toolRegistration.js +2 -2
  76. package/dist/types/cli.d.ts +56 -1
  77. package/dist/types/contextTypes.d.ts +110 -0
  78. package/dist/types/contextTypes.js +177 -0
  79. package/dist/types/index.d.ts +4 -1
  80. package/dist/types/mcpTypes.d.ts +118 -7
  81. package/dist/types/providers.d.ts +81 -0
  82. package/dist/types/streamTypes.d.ts +44 -7
  83. package/dist/types/tools.d.ts +9 -0
  84. package/dist/types/universalProviderOptions.d.ts +3 -1
  85. package/dist/types/universalProviderOptions.js +3 -1
  86. package/dist/utils/logger.d.ts +7 -0
  87. package/dist/utils/logger.js +11 -0
  88. package/dist/utils/performance.d.ts +105 -0
  89. package/dist/utils/performance.js +210 -0
  90. package/dist/utils/retryHandler.d.ts +89 -0
  91. package/dist/utils/retryHandler.js +269 -0
  92. package/package.json +2 -1
package/dist/cli/index.js CHANGED
@@ -10,6 +10,7 @@ import { hideBin } from "yargs/helpers";
10
10
  import chalk from "chalk";
11
11
  import { addOllamaCommands } from "./commands/ollama.js";
12
12
  import { CLICommandFactory } from "./factories/commandFactory.js";
13
+ import { logger } from "../lib/utils/logger.js";
13
14
  // Load environment variables from .env file
14
15
  try {
15
16
  // Try to import and configure dotenv
@@ -81,24 +82,24 @@ function handleError(error, context) {
81
82
  "Authorization error: You are not authorized to perform this action or access this resource.";
82
83
  }
83
84
  // If no specific condition matched, genericMessage remains error.message
84
- console.error(chalk.red(`❌ ${context} failed: ${genericMessage}`));
85
+ logger.error(chalk.red(`❌ ${context} failed: ${genericMessage}`));
85
86
  // Smart hints for common errors (just string matching!)
86
87
  if (genericMessage.toLowerCase().includes("api key") ||
87
88
  genericMessage.toLowerCase().includes("credential")) {
88
- console.error(chalk.yellow("💡 Set Google AI Studio API key (RECOMMENDED): export GOOGLE_AI_API_KEY=AIza-..."));
89
- console.error(chalk.yellow("💡 Or set OpenAI API key: export OPENAI_API_KEY=sk-..."));
90
- console.error(chalk.yellow("💡 Or set AWS Bedrock credentials: export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... AWS_REGION=us-east-1"));
91
- console.error(chalk.yellow("💡 Or set Google Vertex AI credentials: export GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json"));
92
- console.error(chalk.yellow("💡 Or set Anthropic API key: export ANTHROPIC_API_KEY=sk-ant-..."));
93
- console.error(chalk.yellow("💡 Or set Azure OpenAI credentials: export AZURE_OPENAI_API_KEY=... AZURE_OPENAI_ENDPOINT=..."));
89
+ logger.error(chalk.yellow("💡 Set Google AI Studio API key (RECOMMENDED): export GOOGLE_AI_API_KEY=AIza-..."));
90
+ logger.error(chalk.yellow("💡 Or set OpenAI API key: export OPENAI_API_KEY=sk-..."));
91
+ logger.error(chalk.yellow("💡 Or set AWS Bedrock credentials: export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... AWS_REGION=us-east-1"));
92
+ logger.error(chalk.yellow("💡 Or set Google Vertex AI credentials: export GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json"));
93
+ logger.error(chalk.yellow("💡 Or set Anthropic API key: export ANTHROPIC_API_KEY=sk-ant-..."));
94
+ logger.error(chalk.yellow("💡 Or set Azure OpenAI credentials: export AZURE_OPENAI_API_KEY=... AZURE_OPENAI_ENDPOINT=..."));
94
95
  }
95
96
  if (error.message.toLowerCase().includes("rate limit")) {
96
- console.error(chalk.yellow("💡 Try again in a few moments or use --provider vertex"));
97
+ logger.error(chalk.yellow("💡 Try again in a few moments or use --provider vertex"));
97
98
  }
98
99
  if (error.message.toLowerCase().includes("not authorized") ||
99
100
  error.message.toLowerCase().includes("permission denied")) {
100
- console.error(chalk.yellow("💡 Check your account permissions for the selected model/service."));
101
- console.error(chalk.yellow("💡 For AWS Bedrock, ensure you have permissions for the specific model and consider using inference profile ARNs."));
101
+ logger.error(chalk.yellow("💡 Check your account permissions for the selected model/service."));
102
+ logger.error(chalk.yellow("💡 For AWS Bedrock, ensure you have permissions for the specific model and consider using inference profile ARNs."));
102
103
  }
103
104
  process.exit(1);
104
105
  }
@@ -118,6 +119,14 @@ const cli = yargs(args)
118
119
  .epilogue("For more info: https://github.com/juspay/neurolink")
119
120
  .showHelpOnFail(true, "Specify --help for available options")
120
121
  .middleware((argv) => {
122
+ // Handle no-color option globally
123
+ if (argv.noColor || process.env.NO_COLOR || !process.stdout.isTTY) {
124
+ process.env.FORCE_COLOR = "0";
125
+ }
126
+ // Handle custom config file
127
+ if (argv.configFile) {
128
+ process.env.NEUROLINK_CONFIG_FILE = argv.configFile;
129
+ }
121
130
  // Control SDK logging based on debug flag
122
131
  if (argv.debug) {
123
132
  process.env.NEUROLINK_DEBUG = "true";
@@ -205,6 +214,12 @@ const cli = yargs(args)
205
214
  .command(CLICommandFactory.createProviderCommands())
206
215
  // Status command alias - Using CLICommandFactory
207
216
  .command(CLICommandFactory.createStatusCommand())
217
+ // Models Command Group - Using CLICommandFactory
218
+ .command(CLICommandFactory.createModelsCommands())
219
+ // MCP Command Group - Using CLICommandFactory
220
+ .command(CLICommandFactory.createMCPCommands())
221
+ // Discover Command - Using CLICommandFactory
222
+ .command(CLICommandFactory.createDiscoverCommand())
208
223
  // Configuration Command Group - Using CLICommandFactory
209
224
  .command(CLICommandFactory.createConfigCommands())
210
225
  // Get Best Provider Command - Using CLICommandFactory
@@ -7,6 +7,7 @@
7
7
  import { runInteractiveSetup, testProviderConnectivity, displaySetupSummary, } from "./interactiveSetup.js";
8
8
  import { updateEnvFile, displayEnvUpdateSummary } from "./envManager.js";
9
9
  import chalk from "chalk";
10
+ import { logger } from "../../lib/utils/logger.js";
10
11
  /**
11
12
  * Run the complete interactive setup process
12
13
  */
@@ -14,20 +15,20 @@ export async function runCompleteSetup(quiet = false) {
14
15
  try {
15
16
  // Step 1: Run interactive setup wizard
16
17
  if (!quiet) {
17
- console.log(chalk.blue("🚀 Starting NeuroLink Configuration Setup...\n"));
18
+ logger.always(chalk.blue("🚀 Starting NeuroLink Configuration Setup...\n"));
18
19
  }
19
20
  const setupResult = await runInteractiveSetup(quiet);
20
21
  // If no providers selected, exit early
21
22
  if (setupResult.selectedProviders.length === 0) {
22
23
  if (!quiet) {
23
- console.log(chalk.yellow("⚠️ No providers selected. Setup cancelled."));
24
+ logger.always(chalk.yellow("⚠️ No providers selected. Setup cancelled."));
24
25
  }
25
26
  return setupResult;
26
27
  }
27
28
  // Step 2: Update environment file with credentials
28
29
  if (Object.keys(setupResult.credentials).length > 0) {
29
30
  if (!quiet) {
30
- console.log(chalk.blue("\n💾 Updating environment configuration...\n"));
31
+ logger.always(chalk.blue("\n💾 Updating environment configuration...\n"));
31
32
  }
32
33
  try {
33
34
  const envResult = updateEnvFile(setupResult.credentials, ".env", true);
@@ -42,14 +43,14 @@ export async function runCompleteSetup(quiet = false) {
42
43
  }
43
44
  catch (error) {
44
45
  if (!quiet) {
45
- console.error(chalk.red(`❌ Failed to update environment file: ${error instanceof Error ? error.message : String(error)}`));
46
+ logger.error(chalk.red(`❌ Failed to update environment file: ${error instanceof Error ? error.message : String(error)}`));
46
47
  }
47
48
  throw error;
48
49
  }
49
50
  }
50
51
  // Step 3: Test provider connectivity
51
52
  if (!quiet) {
52
- console.log(chalk.blue("\n🧪 Testing configured providers...\n"));
53
+ logger.always(chalk.blue("\n🧪 Testing configured providers...\n"));
53
54
  }
54
55
  setupResult.testResults = await testProviderConnectivity(setupResult.selectedProviders, quiet);
55
56
  // Step 4: Display summary
@@ -58,8 +59,8 @@ export async function runCompleteSetup(quiet = false) {
58
59
  }
59
60
  catch (error) {
60
61
  if (!quiet) {
61
- console.error(chalk.red(`❌ Setup failed: ${error instanceof Error ? error.message : String(error)}`));
62
- console.log(chalk.yellow("💡 You can retry setup with: neurolink config setup"));
62
+ logger.error(chalk.red(`❌ Setup failed: ${error instanceof Error ? error.message : String(error)}`));
63
+ logger.always(chalk.yellow("💡 You can retry setup with: neurolink config setup"));
63
64
  }
64
65
  throw error;
65
66
  }
@@ -75,7 +76,7 @@ export async function configSetup(quiet = false) {
75
76
  */
76
77
  export async function configInit(quiet = false) {
77
78
  if (!quiet) {
78
- console.log(chalk.gray("📝 config init is an alias for config setup\n"));
79
+ logger.always(chalk.gray("📝 config init is an alias for config setup\n"));
79
80
  }
80
81
  await runCompleteSetup(quiet);
81
82
  }
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import fs from "fs";
7
7
  import chalk from "chalk";
8
+ import { logger } from "../../lib/utils/logger.js";
8
9
  /**
9
10
  * Create a timestamped backup of the existing .env file
10
11
  */
@@ -158,23 +159,23 @@ export function displayEnvUpdateSummary(result, quiet = false) {
158
159
  return;
159
160
  }
160
161
  if (result.backup.existed && result.backup.backupPath) {
161
- console.log(chalk.gray(`💾 Created backup: ${result.backup.backupPath}`));
162
+ logger.always(chalk.gray(`💾 Created backup: ${result.backup.backupPath}`));
162
163
  }
163
164
  if (result.added.length > 0) {
164
- console.log(chalk.green(`➕ Added ${result.added.length} new variables: ${result.added.join(", ")}`));
165
+ logger.always(chalk.green(`➕ Added ${result.added.length} new variables: ${result.added.join(", ")}`));
165
166
  }
166
167
  if (result.updated.length > 0) {
167
- console.log(chalk.yellow(`🔄 Updated ${result.updated.length} existing variables: ${result.updated.join(", ")}`));
168
+ logger.always(chalk.yellow(`🔄 Updated ${result.updated.length} existing variables: ${result.updated.join(", ")}`));
168
169
  }
169
170
  if (result.unchanged.length > 0) {
170
- console.log(chalk.gray(`✓ ${result.unchanged.length} variables unchanged: ${result.unchanged.join(", ")}`));
171
+ logger.always(chalk.gray(`✓ ${result.unchanged.length} variables unchanged: ${result.unchanged.join(", ")}`));
171
172
  }
172
173
  const totalChanges = result.added.length + result.updated.length;
173
174
  if (totalChanges > 0) {
174
- console.log(chalk.blue(`📝 Environment file updated with ${totalChanges} changes`));
175
+ logger.always(chalk.blue(`📝 Environment file updated with ${totalChanges} changes`));
175
176
  }
176
177
  else {
177
- console.log(chalk.gray("📝 No changes needed to environment file"));
178
+ logger.always(chalk.gray("📝 No changes needed to environment file"));
178
179
  }
179
180
  }
180
181
  /**
@@ -8,6 +8,7 @@ import { AIProviderName } from "../../lib/core/types.js";
8
8
  import { NeuroLink } from "../../lib/neurolink.js";
9
9
  import chalk from "chalk";
10
10
  import ora from "ora";
11
+ import { logger } from "../../lib/utils/logger.js";
11
12
  export const PROVIDER_CONFIGS = [
12
13
  {
13
14
  id: AIProviderName.OPENAI,
@@ -145,8 +146,8 @@ export async function runInteractiveSetup(quiet = false) {
145
146
  testResults: [],
146
147
  };
147
148
  if (!quiet) {
148
- console.log(chalk.blue("\n🎉 Welcome to NeuroLink Interactive Setup!"));
149
- console.log(chalk.gray("This wizard will help you configure AI providers for NeuroLink.\n"));
149
+ logger.always(chalk.blue("\n🎉 Welcome to NeuroLink Interactive Setup!"));
150
+ logger.always(chalk.gray("This wizard will help you configure AI providers for NeuroLink.\n"));
150
151
  }
151
152
  // Step 1: Provider Selection
152
153
  const providerChoices = PROVIDER_CONFIGS.map((config) => ({
@@ -171,7 +172,7 @@ export async function runInteractiveSetup(quiet = false) {
171
172
  result.selectedProviders = selectedProviders;
172
173
  // Step 2: Credential Collection
173
174
  if (!quiet) {
174
- console.log(chalk.blue("\n🔑 Collecting credentials for selected providers...\n"));
175
+ logger.always(chalk.blue("\n🔑 Collecting credentials for selected providers...\n"));
175
176
  }
176
177
  for (const providerId of selectedProviders) {
177
178
  const config = PROVIDER_CONFIGS.find((c) => c.id === providerId);
@@ -179,7 +180,7 @@ export async function runInteractiveSetup(quiet = false) {
179
180
  continue;
180
181
  }
181
182
  if (!quiet) {
182
- console.log(chalk.yellow(`\n📋 Configuring ${config.name}:`));
183
+ logger.always(chalk.yellow(`\n📋 Configuring ${config.name}:`));
183
184
  }
184
185
  for (const envVar of config.envVars) {
185
186
  const currentValue = process.env[envVar.key];
@@ -235,7 +236,7 @@ export async function testProviderConnectivity(providers, quiet = false) {
235
236
  const sdk = new NeuroLink();
236
237
  const results = [];
237
238
  if (!quiet) {
238
- console.log(chalk.blue("\n🧪 Testing provider connectivity...\n"));
239
+ logger.always(chalk.blue("\n🧪 Testing provider connectivity...\n"));
239
240
  }
240
241
  const spinner = quiet ? null : ora().start();
241
242
  for (const provider of providers) {
@@ -252,7 +253,7 @@ export async function testProviderConnectivity(providers, quiet = false) {
252
253
  spinner.start(); // Restart for next provider
253
254
  }
254
255
  else if (!quiet) {
255
- console.log(`${provider}: ${chalk.green("✅ Working")} (${duration}ms)`);
256
+ logger.always(`${provider}: ${chalk.green("✅ Working")} (${duration}ms)`);
256
257
  }
257
258
  }
258
259
  catch (error) {
@@ -263,7 +264,7 @@ export async function testProviderConnectivity(providers, quiet = false) {
263
264
  spinner.start(); // Restart for next provider
264
265
  }
265
266
  else if (!quiet) {
266
- console.error(`${provider}: ${chalk.red("❌ Failed")} - ${errorMessage.split("\n")[0]}`);
267
+ logger.error(`${provider}: ${chalk.red("❌ Failed")} - ${errorMessage.split("\n")[0]}`);
267
268
  }
268
269
  }
269
270
  }
@@ -281,22 +282,22 @@ export function displaySetupSummary(result, quiet = false) {
281
282
  }
282
283
  const working = result.testResults.filter((r) => r.status === "working").length;
283
284
  const total = result.testResults.length;
284
- console.log(chalk.blue("\n📊 Setup Summary:"));
285
- console.log(chalk.blue("================"));
286
- console.log(`Selected providers: ${result.selectedProviders.length}`);
287
- console.log(`Working providers: ${working}/${total}`);
285
+ logger.always(chalk.blue("\n📊 Setup Summary:"));
286
+ logger.always(chalk.blue("================"));
287
+ logger.always(`Selected providers: ${result.selectedProviders.length}`);
288
+ logger.always(`Working providers: ${working}/${total}`);
288
289
  if (result.envFileBackup) {
289
- console.log(chalk.gray(`Environment backup: ${result.envFileBackup}`));
290
+ logger.always(chalk.gray(`Environment backup: ${result.envFileBackup}`));
290
291
  }
291
292
  if (working > 0) {
292
- console.log(chalk.green("\n✅ Setup completed successfully!"));
293
- console.log(chalk.yellow("💡 You can now use NeuroLink with your configured providers."));
294
- console.log(chalk.gray(' Try: neurolink generate "Hello, AI!"'));
293
+ logger.always(chalk.green("\n✅ Setup completed successfully!"));
294
+ logger.always(chalk.yellow("💡 You can now use NeuroLink with your configured providers."));
295
+ logger.always(chalk.gray(' Try: neurolink generate "Hello, AI!"'));
295
296
  }
296
297
  else {
297
- console.log(chalk.red("\n❌ No providers are working."));
298
- console.log(chalk.yellow("💡 Please check your credentials and try again."));
299
- console.log(chalk.gray(" Run: neurolink config setup"));
298
+ logger.always(chalk.red("\n❌ No providers are working."));
299
+ logger.always(chalk.yellow("💡 Please check your credentials and try again."));
300
+ logger.always(chalk.gray(" Run: neurolink config setup"));
300
301
  }
301
- console.log(chalk.blue("\n📚 Documentation: https://github.com/juspay/neurolink#setup"));
302
+ logger.always(chalk.blue("\n📚 Documentation: https://github.com/juspay/neurolink#setup"));
302
303
  }
@@ -50,52 +50,39 @@ export function createAnalytics(provider, model, result, responseTime, context)
50
50
  * Extract token usage from various AI result formats
51
51
  */
52
52
  function extractTokenUsage(result) {
53
- // Handle different response formats
53
+ // Use properly typed usage object from BaseProvider or direct AI SDK
54
54
  if (result.usage &&
55
55
  typeof result.usage === "object" &&
56
56
  result.usage !== null) {
57
57
  const usage = result.usage;
58
- // Standard format
59
- if (typeof usage.promptTokens === "number" &&
60
- typeof usage.completionTokens === "number") {
61
- return {
62
- input: usage.promptTokens || 0,
63
- output: usage.completionTokens || 0,
64
- total: typeof usage.totalTokens === "number"
65
- ? usage.totalTokens
66
- : usage.promptTokens + usage.completionTokens,
67
- };
58
+ // Try BaseProvider normalized format first (inputTokens/outputTokens)
59
+ if (typeof usage.inputTokens === "number" ||
60
+ typeof usage.outputTokens === "number") {
61
+ const input = typeof usage.inputTokens === "number" ? usage.inputTokens : 0;
62
+ const output = typeof usage.outputTokens === "number" ? usage.outputTokens : 0;
63
+ const total = typeof usage.totalTokens === "number"
64
+ ? usage.totalTokens
65
+ : input + output;
66
+ return { input, output, total };
68
67
  }
69
- // Alternative formats
70
- if (typeof usage.input_tokens === "number" &&
71
- typeof usage.output_tokens === "number") {
72
- return {
73
- input: usage.input_tokens || 0,
74
- output: usage.output_tokens || 0,
75
- total: typeof usage.total_tokens === "number"
76
- ? usage.total_tokens
77
- : usage.input_tokens + usage.output_tokens,
78
- };
68
+ // Try OpenAI/Mistral format (promptTokens/completionTokens)
69
+ if (typeof usage.promptTokens === "number" ||
70
+ typeof usage.completionTokens === "number") {
71
+ const input = typeof usage.promptTokens === "number" ? usage.promptTokens : 0;
72
+ const output = typeof usage.completionTokens === "number" ? usage.completionTokens : 0;
73
+ const total = typeof usage.totalTokens === "number"
74
+ ? usage.totalTokens
75
+ : input + output;
76
+ return { input, output, total };
79
77
  }
80
- // Generic tokens field
81
- if (typeof usage.tokens === "number") {
82
- return {
83
- input: 0,
84
- output: 0,
85
- total: usage.tokens,
86
- };
78
+ // Handle total-only case
79
+ if (typeof usage.totalTokens === "number") {
80
+ return { input: 0, output: 0, total: usage.totalTokens };
87
81
  }
88
82
  }
89
- // Fallback: estimate from text length
90
- const textLength = (typeof result.text === "string" ? result.text.length : 0) ||
91
- (typeof result.content === "string" ? result.content.length : 0) ||
92
- 0;
93
- const estimatedTokens = Math.ceil(textLength / 4); // ~4 chars per token
94
- return {
95
- input: 0,
96
- output: estimatedTokens,
97
- total: estimatedTokens,
98
- };
83
+ // Fallback for edge cases
84
+ logger.debug("Token extraction failed: unknown usage format", { result });
85
+ return { input: 0, output: 0, total: 0 };
99
86
  }
100
87
  /**
101
88
  * Estimate cost based on provider, model, and token usage
@@ -447,5 +447,13 @@ export declare abstract class BaseProvider implements AIProvider {
447
447
  * Get timeout value in milliseconds
448
448
  */
449
449
  getTimeout(options: TextGenerationOptions | StreamOptions): number;
450
+ /**
451
+ * Utility method to chunk large prompts into smaller pieces
452
+ * @param prompt The prompt to chunk
453
+ * @param maxChunkSize Maximum size per chunk (default: 900,000 characters)
454
+ * @param overlap Overlap between chunks to maintain context (default: 100 characters)
455
+ * @returns Array of prompt chunks
456
+ */
457
+ static chunkPrompt(prompt: string, maxChunkSize?: number, overlap?: number): string[];
450
458
  }
451
459
  export {};