@juspay/neurolink 7.34.0 → 7.36.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 (57) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +64 -7
  3. package/dist/adapters/providerImageAdapter.d.ts +56 -0
  4. package/dist/adapters/providerImageAdapter.js +257 -0
  5. package/dist/cli/commands/config.d.ts +20 -20
  6. package/dist/cli/commands/setup-anthropic.d.ts +16 -0
  7. package/dist/cli/commands/setup-anthropic.js +414 -0
  8. package/dist/cli/commands/setup-azure.d.ts +17 -0
  9. package/dist/cli/commands/setup-azure.js +415 -0
  10. package/dist/cli/commands/setup-bedrock.d.ts +13 -0
  11. package/dist/cli/commands/setup-bedrock.js +487 -0
  12. package/dist/cli/commands/setup-gcp.d.ts +18 -0
  13. package/dist/cli/commands/setup-gcp.js +569 -0
  14. package/dist/cli/commands/setup-google-ai.d.ts +16 -0
  15. package/dist/cli/commands/setup-google-ai.js +369 -0
  16. package/dist/cli/commands/setup-huggingface.d.ts +8 -0
  17. package/dist/cli/commands/setup-huggingface.js +200 -0
  18. package/dist/cli/commands/setup-mistral.d.ts +8 -0
  19. package/dist/cli/commands/setup-mistral.js +233 -0
  20. package/dist/cli/commands/setup-openai.d.ts +16 -0
  21. package/dist/cli/commands/setup-openai.js +402 -0
  22. package/dist/cli/commands/setup.d.ts +19 -0
  23. package/dist/cli/commands/setup.js +539 -0
  24. package/dist/cli/factories/commandFactory.d.ts +5 -0
  25. package/dist/cli/factories/commandFactory.js +67 -3
  26. package/dist/cli/factories/setupCommandFactory.d.ts +18 -0
  27. package/dist/cli/factories/setupCommandFactory.js +137 -0
  28. package/dist/cli/parser.js +4 -1
  29. package/dist/cli/utils/envManager.d.ts +3 -2
  30. package/dist/cli/utils/envManager.js +18 -4
  31. package/dist/core/baseProvider.js +99 -45
  32. package/dist/core/types.d.ts +3 -0
  33. package/dist/lib/adapters/providerImageAdapter.d.ts +56 -0
  34. package/dist/lib/adapters/providerImageAdapter.js +257 -0
  35. package/dist/lib/core/baseProvider.js +99 -45
  36. package/dist/lib/core/types.d.ts +3 -0
  37. package/dist/lib/neurolink.js +8 -3
  38. package/dist/lib/types/content.d.ts +78 -0
  39. package/dist/lib/types/content.js +5 -0
  40. package/dist/lib/types/conversation.d.ts +19 -0
  41. package/dist/lib/types/generateTypes.d.ts +4 -1
  42. package/dist/lib/types/streamTypes.d.ts +6 -3
  43. package/dist/lib/utils/imageProcessor.d.ts +84 -0
  44. package/dist/lib/utils/imageProcessor.js +362 -0
  45. package/dist/lib/utils/messageBuilder.d.ts +8 -1
  46. package/dist/lib/utils/messageBuilder.js +279 -0
  47. package/dist/neurolink.js +8 -3
  48. package/dist/types/content.d.ts +78 -0
  49. package/dist/types/content.js +5 -0
  50. package/dist/types/conversation.d.ts +19 -0
  51. package/dist/types/generateTypes.d.ts +4 -1
  52. package/dist/types/streamTypes.d.ts +6 -3
  53. package/dist/utils/imageProcessor.d.ts +84 -0
  54. package/dist/utils/imageProcessor.js +362 -0
  55. package/dist/utils/messageBuilder.d.ts +8 -1
  56. package/dist/utils/messageBuilder.js +279 -0
  57. package/package.json +1 -1
@@ -0,0 +1,414 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Anthropic Setup Command
4
+ *
5
+ * Simple setup for Anthropic Claude integration:
6
+ * - ANTHROPIC_API_KEY (required)
7
+ * - ANTHROPIC_MODEL (optional, with Claude model choices)
8
+ *
9
+ * Follows the same UX patterns as setup-openai and setup-google-ai
10
+ */
11
+ import fs from "fs";
12
+ import path from "path";
13
+ import inquirer from "inquirer";
14
+ import chalk from "chalk";
15
+ import ora from "ora";
16
+ import { logger } from "../../lib/utils/logger.js";
17
+ export async function handleAnthropicSetup(argv) {
18
+ try {
19
+ const options = {
20
+ checkOnly: argv.check || false,
21
+ interactive: !argv.nonInteractive,
22
+ };
23
+ logger.always(chalk.blue("🔍 Checking Anthropic configuration..."));
24
+ // Step 1: Check for existing configuration
25
+ const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
26
+ const hasModel = !!process.env.ANTHROPIC_MODEL;
27
+ // Display current status
28
+ displayCurrentStatus(hasApiKey, hasModel);
29
+ // Check-only mode - show status and exit
30
+ if (options.checkOnly) {
31
+ if (hasApiKey) {
32
+ logger.always(chalk.green("✅ Anthropic setup complete"));
33
+ const apiKey = process.env.ANTHROPIC_API_KEY;
34
+ if (apiKey) {
35
+ logger.always(` API Key: ${maskCredential(apiKey)}`);
36
+ }
37
+ if (hasModel) {
38
+ logger.always(` Model: ${process.env.ANTHROPIC_MODEL}`);
39
+ }
40
+ else {
41
+ logger.always(" Model: claude-3-5-sonnet-20241022 (default)");
42
+ }
43
+ }
44
+ else {
45
+ logger.always(chalk.yellow("⚠️ Anthropic setup incomplete"));
46
+ }
47
+ return;
48
+ }
49
+ const config = {};
50
+ // Step 2: Handle existing configuration
51
+ if (hasApiKey) {
52
+ logger.always(chalk.green("✅ Anthropic API key found in environment"));
53
+ const apiKey = process.env.ANTHROPIC_API_KEY;
54
+ if (apiKey) {
55
+ logger.always(` API Key: ${maskCredential(apiKey)}`);
56
+ }
57
+ if (hasModel) {
58
+ logger.always(` Model: ${process.env.ANTHROPIC_MODEL}`);
59
+ }
60
+ else {
61
+ logger.always(" Model: claude-3-5-sonnet-20241022 (default)");
62
+ }
63
+ if (options.interactive) {
64
+ const { reconfigure } = await inquirer.prompt([
65
+ {
66
+ type: "confirm",
67
+ name: "reconfigure",
68
+ message: "Anthropic is already configured. Do you want to reconfigure?",
69
+ default: false,
70
+ },
71
+ ]);
72
+ if (!reconfigure) {
73
+ // Still offer model selection if no model is set
74
+ if (!hasModel) {
75
+ const { wantsCustomModel } = await inquirer.prompt([
76
+ {
77
+ type: "confirm",
78
+ name: "wantsCustomModel",
79
+ message: "Do you want to specify an Anthropic model? (optional)",
80
+ default: false,
81
+ },
82
+ ]);
83
+ if (wantsCustomModel) {
84
+ config.model = await promptForModel();
85
+ }
86
+ }
87
+ else {
88
+ // Offer to change existing model
89
+ const { wantsChangeModel } = await inquirer.prompt([
90
+ {
91
+ type: "confirm",
92
+ name: "wantsChangeModel",
93
+ message: `Do you want to change the Anthropic model? (current: ${process.env.ANTHROPIC_MODEL})`,
94
+ default: false,
95
+ },
96
+ ]);
97
+ if (wantsChangeModel) {
98
+ config.model = await promptForModel();
99
+ }
100
+ }
101
+ if (config.model) {
102
+ await updateEnvFile(config);
103
+ logger.always(chalk.green("✅ Model configuration updated!"));
104
+ logger.always(` ANTHROPIC_MODEL=${config.model}`);
105
+ }
106
+ else {
107
+ logger.always(chalk.blue("👍 Keeping existing configuration."));
108
+ }
109
+ // Show usage example
110
+ showUsageExample();
111
+ return;
112
+ }
113
+ else {
114
+ // User chose to reconfigure - mark this for proper handling
115
+ logger.always(chalk.blue("📝 Reconfiguring Anthropic setup..."));
116
+ config.isReconfiguring = true;
117
+ }
118
+ }
119
+ else {
120
+ // Non-interactive mode - just use existing credentials
121
+ logger.always(chalk.green("✅ Setup complete! Using existing Anthropic configuration."));
122
+ return;
123
+ }
124
+ }
125
+ // Step 3: Interactive setup for missing or reconfiguring credentials
126
+ if (options.interactive) {
127
+ const isReconfiguring = config.isReconfiguring === true;
128
+ // Handle API key setup/reconfiguration
129
+ if (!hasApiKey) {
130
+ // No API key exists - prompt for it
131
+ logger.always("");
132
+ logger.always(chalk.yellow("📋 To get your Anthropic API key:"));
133
+ logger.always("1. Visit: https://console.anthropic.com/");
134
+ logger.always("2. Sign in to your Anthropic account");
135
+ logger.always("3. Go to 'API Keys' section");
136
+ logger.always("4. Click 'Create Key' and copy the API key (starts with sk-ant-)");
137
+ logger.always("");
138
+ const { apiKey } = await inquirer.prompt([
139
+ {
140
+ type: "password",
141
+ name: "apiKey",
142
+ message: "Enter your Anthropic API key:",
143
+ validate: validateApiKey,
144
+ },
145
+ ]);
146
+ config.apiKey = apiKey.trim();
147
+ }
148
+ else if (isReconfiguring) {
149
+ // API key exists and user is reconfiguring - ask if they want to change it
150
+ const apiKey = process.env.ANTHROPIC_API_KEY;
151
+ const { wantsChangeApiKey } = await inquirer.prompt([
152
+ {
153
+ type: "confirm",
154
+ name: "wantsChangeApiKey",
155
+ message: `Do you want to change the Anthropic API key? (current: ${apiKey ? maskCredential(apiKey) : "****"})`,
156
+ default: false,
157
+ },
158
+ ]);
159
+ if (wantsChangeApiKey) {
160
+ logger.always("");
161
+ logger.always(chalk.yellow("📋 To get your Anthropic API key:"));
162
+ logger.always("1. Visit: https://console.anthropic.com/");
163
+ logger.always("2. Sign in to your Anthropic account");
164
+ logger.always("3. Go to 'API Keys' section");
165
+ logger.always("4. Click 'Create Key' and copy the API key (starts with sk-ant-)");
166
+ logger.always("");
167
+ const { apiKey } = await inquirer.prompt([
168
+ {
169
+ type: "password",
170
+ name: "apiKey",
171
+ message: "Enter your new Anthropic API key (replacing existing):",
172
+ validate: validateApiKey,
173
+ },
174
+ ]);
175
+ config.apiKey = apiKey.trim();
176
+ }
177
+ }
178
+ // Prompt for model selection
179
+ const { wantsCustomModel } = await inquirer.prompt([
180
+ {
181
+ type: "confirm",
182
+ name: "wantsCustomModel",
183
+ message: hasModel
184
+ ? `Do you want to change the Anthropic model? (current: ${process.env.ANTHROPIC_MODEL})`
185
+ : "Do you want to specify an Anthropic model? (optional)",
186
+ default: false,
187
+ },
188
+ ]);
189
+ if (wantsCustomModel) {
190
+ config.model = await promptForModel();
191
+ }
192
+ }
193
+ else {
194
+ // Non-interactive mode
195
+ logger.always(chalk.yellow("⚠️ Non-interactive mode: setup incomplete"));
196
+ logger.always(chalk.yellow("💡 Run without --non-interactive to configure Anthropic"));
197
+ return;
198
+ }
199
+ // Step 4: Update .env file
200
+ if (config.apiKey || config.model) {
201
+ await updateEnvFile(config);
202
+ logger.always(chalk.green("✅ Anthropic setup complete!"));
203
+ if (config.apiKey) {
204
+ logger.always(` API Key: ${maskCredential(config.apiKey)}`);
205
+ }
206
+ if (config.model) {
207
+ logger.always(` Model: ${config.model}`);
208
+ }
209
+ // Show usage example
210
+ showUsageExample();
211
+ }
212
+ else if (options.interactive && !options.checkOnly) {
213
+ logger.always(chalk.green("✅ Setup complete!"));
214
+ showUsageExample();
215
+ }
216
+ }
217
+ catch (error) {
218
+ logger.error(chalk.red("❌ Anthropic setup failed:"));
219
+ logger.error(chalk.red(error instanceof Error ? error.message : "Unknown error"));
220
+ process.exit(1);
221
+ }
222
+ }
223
+ /**
224
+ * Display current configuration status
225
+ */
226
+ function displayCurrentStatus(hasApiKey, hasModel) {
227
+ if (hasApiKey) {
228
+ logger.always(chalk.green("✔ ANTHROPIC_API_KEY found in environment"));
229
+ }
230
+ else {
231
+ logger.always(chalk.red("✘ ANTHROPIC_API_KEY not found"));
232
+ }
233
+ if (hasModel) {
234
+ logger.always(chalk.green(`✔ ANTHROPIC_MODEL found: ${process.env.ANTHROPIC_MODEL}`));
235
+ }
236
+ else {
237
+ logger.always(chalk.yellow("⚠ ANTHROPIC_MODEL not set (will use claude-3-5-sonnet-20241022 default)"));
238
+ }
239
+ }
240
+ /**
241
+ * Validate Anthropic API key format
242
+ */
243
+ function validateApiKey(input) {
244
+ if (!input.trim()) {
245
+ return "Anthropic API key is required";
246
+ }
247
+ const trimmed = input.trim();
248
+ if (!trimmed.startsWith("sk-ant-")) {
249
+ return "Anthropic API key should start with 'sk-ant-'";
250
+ }
251
+ if (trimmed.length < 20) {
252
+ return "Anthropic API key seems too short";
253
+ }
254
+ // Basic format check: sk-ant-[random string]
255
+ if (!/^sk-ant-[a-zA-Z0-9_-]{20,}$/.test(trimmed)) {
256
+ return "Invalid Anthropic API key format";
257
+ }
258
+ return true;
259
+ }
260
+ /**
261
+ * Prompt user for model selection
262
+ */
263
+ async function promptForModel() {
264
+ const { modelChoice } = await inquirer.prompt([
265
+ {
266
+ type: "list",
267
+ name: "modelChoice",
268
+ message: "Select an Anthropic Claude model:",
269
+ choices: [
270
+ {
271
+ name: "claude-3-5-sonnet-20241022 (Recommended - Latest and most capable)",
272
+ value: "claude-3-5-sonnet-20241022",
273
+ },
274
+ {
275
+ name: "claude-3-5-haiku-20241022 (Fast and cost-effective)",
276
+ value: "claude-3-5-haiku-20241022",
277
+ },
278
+ {
279
+ name: "claude-3-opus-20240229 (Most powerful, slower)",
280
+ value: "claude-3-opus-20240229",
281
+ },
282
+ {
283
+ name: "claude-3-sonnet-20240229 (Balanced performance)",
284
+ value: "claude-3-sonnet-20240229",
285
+ },
286
+ {
287
+ name: "claude-3-haiku-20240307 (Fast and economical)",
288
+ value: "claude-3-haiku-20240307",
289
+ },
290
+ {
291
+ name: "Custom model (enter manually)",
292
+ value: "custom",
293
+ },
294
+ ],
295
+ },
296
+ ]);
297
+ if (modelChoice === "custom") {
298
+ const { customModel } = await inquirer.prompt([
299
+ {
300
+ type: "input",
301
+ name: "customModel",
302
+ message: "Enter your custom Anthropic model name:",
303
+ validate: (input) => {
304
+ if (!input.trim()) {
305
+ return "Model name is required";
306
+ }
307
+ // Basic validation - Anthropic models typically follow certain patterns
308
+ const trimmed = input.trim();
309
+ if (!/^[a-z0-9-._]+$/i.test(trimmed)) {
310
+ return "Model name should contain only letters, numbers, hyphens, dots, and underscores";
311
+ }
312
+ return true;
313
+ },
314
+ },
315
+ ]);
316
+ return customModel.trim();
317
+ }
318
+ return modelChoice;
319
+ }
320
+ /**
321
+ * Update .env file with Anthropic configuration
322
+ */
323
+ async function updateEnvFile(config) {
324
+ const envPath = path.join(process.cwd(), ".env");
325
+ const spinner = ora("💾 Updating .env file...").start();
326
+ try {
327
+ let envContent = "";
328
+ // Read existing .env file if it exists
329
+ if (fs.existsSync(envPath)) {
330
+ envContent = fs.readFileSync(envPath, "utf8");
331
+ }
332
+ // Parse existing environment variables
333
+ const envLines = envContent.split("\n");
334
+ const existingVars = new Map();
335
+ const otherLines = [];
336
+ for (const line of envLines) {
337
+ const trimmed = line.trim();
338
+ if (trimmed && !trimmed.startsWith("#")) {
339
+ const equalsIndex = trimmed.indexOf("=");
340
+ if (equalsIndex > 0) {
341
+ const key = trimmed.substring(0, equalsIndex);
342
+ const value = trimmed.substring(equalsIndex + 1);
343
+ existingVars.set(key, value);
344
+ }
345
+ else {
346
+ otherLines.push(line);
347
+ }
348
+ }
349
+ else {
350
+ otherLines.push(line);
351
+ }
352
+ }
353
+ // Update Anthropic variables
354
+ if (config.apiKey) {
355
+ existingVars.set("ANTHROPIC_API_KEY", config.apiKey);
356
+ }
357
+ if (config.model) {
358
+ existingVars.set("ANTHROPIC_MODEL", config.model);
359
+ }
360
+ // Reconstruct .env content preserving structure
361
+ const newEnvLines = [];
362
+ // Add non-variable lines first (comments, empty lines)
363
+ for (const line of otherLines) {
364
+ newEnvLines.push(line);
365
+ }
366
+ // Add separator comment for Anthropic if needed
367
+ if ((config.apiKey || config.model) &&
368
+ !envContent.includes("ANTHROPIC CONFIGURATION") &&
369
+ !envContent.includes("# Anthropic")) {
370
+ if (newEnvLines.length > 0 &&
371
+ newEnvLines[newEnvLines.length - 1].trim()) {
372
+ newEnvLines.push("");
373
+ }
374
+ newEnvLines.push("# Anthropic Configuration");
375
+ }
376
+ // Add all environment variables
377
+ for (const [key, value] of existingVars.entries()) {
378
+ newEnvLines.push(`${key}=${value}`);
379
+ }
380
+ // Write updated content
381
+ const finalContent = newEnvLines.join("\n") + (newEnvLines.length > 0 ? "\n" : "");
382
+ fs.writeFileSync(envPath, finalContent, "utf8");
383
+ spinner.succeed(chalk.green("✔ .env file updated successfully"));
384
+ }
385
+ catch (error) {
386
+ spinner.fail(chalk.red("❌ Failed to update .env file"));
387
+ logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
388
+ throw error;
389
+ }
390
+ }
391
+ /**
392
+ * Mask API key for display
393
+ */
394
+ function maskCredential(credential) {
395
+ if (!credential || credential.length < 8) {
396
+ return "****";
397
+ }
398
+ const knownPrefixes = ["sk-ant-"];
399
+ const prefix = knownPrefixes.find((p) => credential.startsWith(p)) ??
400
+ credential.slice(0, 3);
401
+ const end = credential.slice(-4);
402
+ const stars = "*".repeat(Math.max(4, credential.length - prefix.length - 4));
403
+ return `${prefix}${stars}${end}`;
404
+ }
405
+ /**
406
+ * Show usage example
407
+ */
408
+ function showUsageExample() {
409
+ logger.always("");
410
+ logger.always(chalk.green("🚀 You can now use Anthropic Claude with the NeuroLink CLI:"));
411
+ logger.always(chalk.cyan(" pnpm cli generate 'Hello from Claude!' --provider anthropic"));
412
+ logger.always(chalk.cyan(" pnpm cli generate 'Explain quantum computing' --provider anthropic"));
413
+ logger.always(chalk.cyan(" pnpm cli generate 'Analyze this data' --provider anthropic --enable-analytics"));
414
+ }
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Azure OpenAI Setup Command
4
+ *
5
+ * Setup for Azure OpenAI integration:
6
+ * - AZURE_OPENAI_API_KEY (required)
7
+ * - AZURE_OPENAI_ENDPOINT (required)
8
+ * - AZURE_OPENAI_MODEL (optional)
9
+ *
10
+ * Follows the same UX patterns as other setup commands
11
+ */
12
+ interface AzureSetupArgv {
13
+ check?: boolean;
14
+ nonInteractive?: boolean;
15
+ }
16
+ export declare function handleAzureSetup(argv: AzureSetupArgv): Promise<void>;
17
+ export {};