@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,369 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Google AI Studio Setup Command
4
+ *
5
+ * Simple setup for Google AI Studio (Google AI) integration:
6
+ * - GOOGLE_AI_API_KEY (required)
7
+ * - GOOGLE_AI_MODEL (optional, with recommended choices)
8
+ *
9
+ * Follows the same UX patterns as setup-openai and setup-gcp
10
+ */
11
+ import path from "path";
12
+ import inquirer from "inquirer";
13
+ import chalk from "chalk";
14
+ import ora from "ora";
15
+ import { logger } from "../../lib/utils/logger.js";
16
+ import { GoogleAIModels } from "../../lib/types/providers.js";
17
+ import { updateEnvFile as updateEnvFileManager, displayEnvUpdateSummary, } from "../utils/envManager.js";
18
+ /**
19
+ * Get the runtime default model that matches the provider implementation
20
+ */
21
+ function getRuntimeDefaultModel() {
22
+ return process.env.GOOGLE_AI_MODEL || GoogleAIModels.GEMINI_2_5_FLASH;
23
+ }
24
+ export async function handleGoogleAISetup(argv) {
25
+ try {
26
+ const options = {
27
+ checkOnly: argv.check || false,
28
+ interactive: !argv.nonInteractive,
29
+ };
30
+ logger.always(chalk.blue("šŸ” Checking Google AI Studio configuration..."));
31
+ // Step 1: Check for existing configuration
32
+ const hasApiKey = !!(process.env.GOOGLE_AI_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY);
33
+ const hasModel = !!process.env.GOOGLE_AI_MODEL;
34
+ const currentApiKey = process.env.GOOGLE_AI_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY;
35
+ // Display current status
36
+ displayCurrentStatus(hasApiKey, hasModel);
37
+ // Check-only mode - show status and exit
38
+ if (options.checkOnly) {
39
+ if (hasApiKey && currentApiKey) {
40
+ logger.always(chalk.green("āœ… Google AI Studio setup complete"));
41
+ logger.always(` API Key: ${maskCredential(currentApiKey)}`);
42
+ if (hasModel) {
43
+ logger.always(` Model: ${process.env.GOOGLE_AI_MODEL}`);
44
+ }
45
+ else {
46
+ logger.always(` Model: ${getRuntimeDefaultModel()} (default)`);
47
+ }
48
+ }
49
+ else {
50
+ logger.always(chalk.yellow("āš ļø Google AI Studio setup incomplete"));
51
+ }
52
+ return;
53
+ }
54
+ const config = {};
55
+ // Step 2: Handle existing configuration
56
+ if (hasApiKey && currentApiKey) {
57
+ logger.always(chalk.green("āœ… Google AI Studio API key found in environment"));
58
+ logger.always(` API Key: ${maskCredential(currentApiKey)}`);
59
+ if (hasModel) {
60
+ logger.always(` Model: ${process.env.GOOGLE_AI_MODEL}`);
61
+ }
62
+ else {
63
+ logger.always(` Model: ${getRuntimeDefaultModel()} (default)`);
64
+ }
65
+ if (options.interactive) {
66
+ const { reconfigure } = await inquirer.prompt([
67
+ {
68
+ type: "confirm",
69
+ name: "reconfigure",
70
+ message: "Google AI Studio is already configured. Do you want to reconfigure?",
71
+ default: false,
72
+ },
73
+ ]);
74
+ if (!reconfigure) {
75
+ // Still offer model selection if no model is set
76
+ if (!hasModel) {
77
+ const { wantsCustomModel } = await inquirer.prompt([
78
+ {
79
+ type: "confirm",
80
+ name: "wantsCustomModel",
81
+ message: "Do you want to specify a Google AI model? (optional)",
82
+ default: false,
83
+ },
84
+ ]);
85
+ if (wantsCustomModel) {
86
+ config.model = await promptForModel();
87
+ }
88
+ }
89
+ else {
90
+ // Offer to change existing model
91
+ const { wantsChangeModel } = await inquirer.prompt([
92
+ {
93
+ type: "confirm",
94
+ name: "wantsChangeModel",
95
+ message: `Do you want to change the Google AI model? (current: ${process.env.GOOGLE_AI_MODEL})`,
96
+ default: false,
97
+ },
98
+ ]);
99
+ if (wantsChangeModel) {
100
+ config.model = await promptForModel();
101
+ }
102
+ }
103
+ if (config.model) {
104
+ await updateEnvFile(config);
105
+ logger.always(chalk.green("āœ… Model configuration updated!"));
106
+ logger.always(` GOOGLE_AI_MODEL=${config.model}`);
107
+ }
108
+ else {
109
+ logger.always(chalk.blue("šŸ‘ Keeping existing configuration."));
110
+ }
111
+ // Show usage example
112
+ showUsageExample();
113
+ return;
114
+ }
115
+ else {
116
+ // User chose to reconfigure - mark this for proper handling
117
+ logger.always(chalk.blue("šŸ“ Reconfiguring Google AI Studio setup..."));
118
+ config.isReconfiguring = true;
119
+ }
120
+ }
121
+ else {
122
+ // Non-interactive mode - just use existing credentials
123
+ logger.always(chalk.green("āœ… Setup complete! Using existing Google AI Studio configuration."));
124
+ return;
125
+ }
126
+ }
127
+ // Step 3: Interactive setup for missing or reconfiguring credentials
128
+ if (options.interactive) {
129
+ const isReconfiguring = config.isReconfiguring === true;
130
+ // Handle API key setup/reconfiguration
131
+ if (!hasApiKey) {
132
+ // No API key exists - prompt for it
133
+ logger.always("");
134
+ logger.always(chalk.yellow("šŸ“‹ To get your Google AI Studio API key:"));
135
+ logger.always("1. Visit: https://aistudio.google.com/app/apikey");
136
+ logger.always("2. Sign in with your Google account");
137
+ logger.always("3. Click 'Create API key' (free tier available)");
138
+ logger.always("4. Copy the API key (starts with AIza...)");
139
+ logger.always("");
140
+ const { apiKey } = await inquirer.prompt([
141
+ {
142
+ type: "password",
143
+ name: "apiKey",
144
+ message: "Enter your Google AI Studio API key:",
145
+ validate: validateApiKey,
146
+ },
147
+ ]);
148
+ config.apiKey = apiKey.trim();
149
+ }
150
+ else if (isReconfiguring) {
151
+ // API key exists and user is reconfiguring - ask if they want to change it
152
+ const { wantsChangeApiKey } = await inquirer.prompt([
153
+ {
154
+ type: "confirm",
155
+ name: "wantsChangeApiKey",
156
+ message: `Do you want to change the Google AI Studio API key? (current: ${currentApiKey ? maskCredential(currentApiKey) : "****"})`,
157
+ default: false,
158
+ },
159
+ ]);
160
+ if (wantsChangeApiKey) {
161
+ logger.always("");
162
+ logger.always(chalk.yellow("šŸ“‹ To get your Google AI Studio API key:"));
163
+ logger.always("1. Visit: https://aistudio.google.com/app/apikey");
164
+ logger.always("2. Sign in with your Google account");
165
+ logger.always("3. Click 'Create API key' (free tier available)");
166
+ logger.always("4. Copy the API key (starts with AIza...)");
167
+ logger.always("");
168
+ const { apiKey } = await inquirer.prompt([
169
+ {
170
+ type: "password",
171
+ name: "apiKey",
172
+ message: "Enter your new Google AI Studio API key (replacing existing):",
173
+ validate: validateApiKey,
174
+ },
175
+ ]);
176
+ config.apiKey = apiKey.trim();
177
+ }
178
+ }
179
+ // Prompt for model selection
180
+ const { wantsCustomModel } = await inquirer.prompt([
181
+ {
182
+ type: "confirm",
183
+ name: "wantsCustomModel",
184
+ message: hasModel
185
+ ? `Do you want to change the Google AI model? (current: ${process.env.GOOGLE_AI_MODEL})`
186
+ : "Do you want to specify a Google AI model? (optional)",
187
+ default: false,
188
+ },
189
+ ]);
190
+ if (wantsCustomModel) {
191
+ config.model = await promptForModel();
192
+ }
193
+ }
194
+ else {
195
+ // Non-interactive mode
196
+ logger.always(chalk.yellow("āš ļø Non-interactive mode: setup incomplete"));
197
+ logger.always(chalk.yellow("šŸ’” Run without --non-interactive to configure Google AI Studio"));
198
+ return;
199
+ }
200
+ // Step 4: Update .env file
201
+ if (config.apiKey || config.model) {
202
+ await updateEnvFile(config);
203
+ logger.always(chalk.green("āœ… Google AI Studio setup complete!"));
204
+ if (config.apiKey) {
205
+ logger.always(` API Key: ${maskCredential(config.apiKey)}`);
206
+ }
207
+ if (config.model) {
208
+ logger.always(` Model: ${config.model}`);
209
+ }
210
+ // Show usage example
211
+ showUsageExample();
212
+ }
213
+ else if (options.interactive && !options.checkOnly) {
214
+ logger.always(chalk.green("āœ… Setup complete!"));
215
+ showUsageExample();
216
+ }
217
+ }
218
+ catch (error) {
219
+ logger.error(chalk.red("āŒ Google AI Studio setup failed:"));
220
+ logger.error(chalk.red(error instanceof Error ? error.message : "Unknown error"));
221
+ process.exit(1);
222
+ }
223
+ }
224
+ /**
225
+ * Display current configuration status
226
+ */
227
+ function displayCurrentStatus(hasApiKey, hasModel) {
228
+ if (hasApiKey) {
229
+ logger.always(chalk.green("āœ” Google AI Studio API key found in environment"));
230
+ }
231
+ else {
232
+ logger.always(chalk.red("✘ Google AI Studio API key not found"));
233
+ }
234
+ if (hasModel) {
235
+ logger.always(chalk.green(`āœ” GOOGLE_AI_MODEL found: ${process.env.GOOGLE_AI_MODEL}`));
236
+ }
237
+ else {
238
+ logger.always(chalk.yellow(`⚠ GOOGLE_AI_MODEL not set (will use ${getRuntimeDefaultModel()} default)`));
239
+ }
240
+ }
241
+ /**
242
+ * Validate Google AI Studio API key format
243
+ */
244
+ function validateApiKey(input) {
245
+ if (!input.trim()) {
246
+ return "Google AI Studio API key is required";
247
+ }
248
+ const trimmed = input.trim();
249
+ if (!trimmed.startsWith("AIza")) {
250
+ return "Google AI Studio API key should start with 'AIza'";
251
+ }
252
+ if (trimmed.length < 20) {
253
+ return "Google AI Studio API key seems too short";
254
+ }
255
+ // Basic format check: AIza[32+ char random string]
256
+ if (!/^AIza[a-zA-Z0-9_-]{20,}$/.test(trimmed)) {
257
+ return "Invalid Google AI Studio API key format";
258
+ }
259
+ return true;
260
+ }
261
+ /**
262
+ * Prompt user for model selection
263
+ */
264
+ async function promptForModel() {
265
+ const { modelChoice } = await inquirer.prompt([
266
+ {
267
+ type: "list",
268
+ name: "modelChoice",
269
+ message: "Select a Google AI model:",
270
+ choices: [
271
+ {
272
+ name: "gemini-2.5-pro (Recommended - Latest high-capability model)",
273
+ value: "gemini-2.5-pro",
274
+ },
275
+ {
276
+ name: "gemini-2.5-flash (Fast and efficient)",
277
+ value: "gemini-2.5-flash",
278
+ },
279
+ {
280
+ name: "gemini-pro-vision (Multimodal - text and images)",
281
+ value: "gemini-pro-vision",
282
+ },
283
+ {
284
+ name: "gemini-pro (Previous generation)",
285
+ value: "gemini-pro",
286
+ },
287
+ {
288
+ name: "Custom model (enter manually)",
289
+ value: "custom",
290
+ },
291
+ ],
292
+ },
293
+ ]);
294
+ if (modelChoice === "custom") {
295
+ const { customModel } = await inquirer.prompt([
296
+ {
297
+ type: "input",
298
+ name: "customModel",
299
+ message: "Enter your custom Google AI model name:",
300
+ validate: (input) => {
301
+ if (!input.trim()) {
302
+ return "Model name is required";
303
+ }
304
+ // Basic validation - Google AI models typically follow certain patterns
305
+ const trimmed = input.trim();
306
+ if (!/^[a-z0-9-._]+$/i.test(trimmed)) {
307
+ return "Model name should contain only letters, numbers, hyphens, dots, and underscores";
308
+ }
309
+ return true;
310
+ },
311
+ },
312
+ ]);
313
+ return customModel.trim();
314
+ }
315
+ return modelChoice;
316
+ }
317
+ /**
318
+ * Update .env file with Google AI Studio configuration
319
+ */
320
+ async function updateEnvFile(config) {
321
+ const envPath = path.join(process.cwd(), ".env");
322
+ const spinner = ora("šŸ’¾ Updating .env file...").start();
323
+ try {
324
+ // Prepare environment variables to update
325
+ const envVars = {};
326
+ const keysToDelete = [];
327
+ if (config.apiKey) {
328
+ // Use GOOGLE_AI_API_KEY as the primary key
329
+ envVars.GOOGLE_AI_API_KEY = config.apiKey;
330
+ // Remove alternative key if it exists
331
+ keysToDelete.push("GOOGLE_GENERATIVE_AI_API_KEY");
332
+ }
333
+ if (config.model) {
334
+ envVars.GOOGLE_AI_MODEL = config.model;
335
+ }
336
+ // Update .env file using centralized envManager
337
+ const result = updateEnvFileManager(envVars, envPath, true, keysToDelete);
338
+ spinner.succeed(chalk.green("āœ” .env file updated successfully"));
339
+ // Display summary of changes (quietly, since we have our own success message)
340
+ displayEnvUpdateSummary(result, true);
341
+ }
342
+ catch (error) {
343
+ spinner.fail(chalk.red("āŒ Failed to update .env file"));
344
+ logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
345
+ throw error;
346
+ }
347
+ }
348
+ /**
349
+ * Mask API key for display
350
+ */
351
+ function maskCredential(credential) {
352
+ if (!credential || credential.length < 8) {
353
+ return "****";
354
+ }
355
+ const start = credential.slice(0, 7); // Show 'AIza' plus a few chars
356
+ const end = credential.slice(-4);
357
+ const middle = "*".repeat(Math.max(4, credential.length - 11));
358
+ return `${start}${middle}${end}`;
359
+ }
360
+ /**
361
+ * Show usage example
362
+ */
363
+ function showUsageExample() {
364
+ logger.always("");
365
+ logger.always(chalk.green("šŸš€ You can now use Google AI Studio with the NeuroLink CLI:"));
366
+ logger.always(chalk.cyan(" pnpm cli generate 'Hello from Google AI!' --provider google-ai"));
367
+ logger.always(chalk.cyan(" pnpm cli generate 'Explain quantum computing' --provider google-ai"));
368
+ logger.always(chalk.cyan(" pnpm cli generate 'Analyze this data' --provider google-ai --enable-analytics"));
369
+ }
@@ -0,0 +1,8 @@
1
+ import type { Arguments, CommandBuilder } from "yargs";
2
+ interface SetupHuggingFaceArgs {
3
+ check?: boolean;
4
+ "non-interactive"?: boolean;
5
+ }
6
+ export declare const handleHuggingFaceSetup: (argv: Arguments<SetupHuggingFaceArgs>) => Promise<void>;
7
+ export declare const setupHuggingFaceBuilder: CommandBuilder;
8
+ export {};
@@ -0,0 +1,200 @@
1
+ import chalk from "chalk";
2
+ import ora from "ora";
3
+ import inquirer from "inquirer";
4
+ import { logger } from "../../lib/utils/logger.js";
5
+ import { updateEnvFile as writeEnvFile, displayEnvUpdateSummary, } from "../utils/envManager.js";
6
+ /**
7
+ * Validates Hugging Face API key format
8
+ * Must start with "hf_" prefix
9
+ */
10
+ function validateHuggingFaceApiKey(apiKey) {
11
+ return (typeof apiKey === "string" && apiKey.startsWith("hf_") && apiKey.length > 10);
12
+ }
13
+ /**
14
+ * Check current Hugging Face configuration
15
+ */
16
+ function checkHuggingFaceConfig() {
17
+ const apiKey = process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN;
18
+ const model = process.env.HUGGINGFACE_MODEL;
19
+ const hasApiKey = !!apiKey;
20
+ const hasModel = !!model;
21
+ const isValid = hasApiKey && validateHuggingFaceApiKey(apiKey);
22
+ return {
23
+ hasApiKey,
24
+ hasModel,
25
+ apiKey: apiKey ? `hf_${"*".repeat(6)}` : undefined,
26
+ model,
27
+ isValid,
28
+ };
29
+ }
30
+ export const handleHuggingFaceSetup = async (argv) => {
31
+ const spinner = ora();
32
+ try {
33
+ spinner.start("Checking Hugging Face configuration...");
34
+ const config = checkHuggingFaceConfig();
35
+ spinner.stop();
36
+ // Display current status
37
+ logger.always(chalk.bold.blue("\nšŸ¤— Hugging Face Configuration Status\n"));
38
+ logger.always(`${config.hasApiKey ? "āœ…" : "āŒ"} API Key: ${config.apiKey || "Not set"}`);
39
+ logger.always(`${config.hasModel ? "āœ…" : "āš ļø"} Model: ${config.model || "Not set (will use default)"}`);
40
+ if (config.isValid) {
41
+ logger.always(chalk.green("\nāœ… Hugging Face is properly configured!"));
42
+ if (argv.check) {
43
+ return;
44
+ }
45
+ const { shouldReconfigure } = await inquirer.prompt([
46
+ {
47
+ type: "confirm",
48
+ name: "shouldReconfigure",
49
+ message: "Configuration looks good. Do you want to reconfigure anyway?",
50
+ default: false,
51
+ },
52
+ ]);
53
+ if (!shouldReconfigure) {
54
+ logger.always(chalk.green("āœ… Keeping existing configuration."));
55
+ return;
56
+ }
57
+ }
58
+ else {
59
+ logger.always(chalk.yellow("\nāš ļø Hugging Face configuration needs setup."));
60
+ if (argv.check) {
61
+ throw new Error("Hugging Face configuration is incomplete");
62
+ }
63
+ }
64
+ if (argv["non-interactive"]) {
65
+ logger.always(chalk.yellow("Non-interactive mode: Skipping configuration setup."));
66
+ logger.always(chalk.blue("Please set HUGGINGFACE_API_KEY manually."));
67
+ return;
68
+ }
69
+ // Interactive setup
70
+ logger.always(chalk.blue("\nšŸ› ļø Let's configure Hugging Face!\n"));
71
+ // Step 1: API Key
72
+ const { apiKey } = await inquirer.prompt([
73
+ {
74
+ type: "password",
75
+ name: "apiKey",
76
+ message: "Enter your Hugging Face API token:",
77
+ mask: "*",
78
+ validate: (input) => {
79
+ if (!input.trim()) {
80
+ return "API token is required";
81
+ }
82
+ if (!validateHuggingFaceApiKey(input.trim())) {
83
+ return "Invalid API token format. Must start with 'hf_'";
84
+ }
85
+ return true;
86
+ },
87
+ },
88
+ ]);
89
+ // Step 2: Model Selection
90
+ const { modelChoice } = await inquirer.prompt([
91
+ {
92
+ type: "list",
93
+ name: "modelChoice",
94
+ message: "Select a Hugging Face model:",
95
+ choices: [
96
+ {
97
+ name: "Skip - use default (microsoft/DialoGPT-large)",
98
+ value: "default",
99
+ },
100
+ {
101
+ name: "microsoft/DialoGPT-large (Conversational AI - Recommended)",
102
+ value: "microsoft/DialoGPT-large",
103
+ },
104
+ {
105
+ name: "microsoft/DialoGPT-medium (Faster, smaller)",
106
+ value: "microsoft/DialoGPT-medium",
107
+ },
108
+ {
109
+ name: "facebook/blenderbot-400M-distill (General purpose)",
110
+ value: "facebook/blenderbot-400M-distill",
111
+ },
112
+ {
113
+ name: "microsoft/DialoGPT-small (Fastest)",
114
+ value: "microsoft/DialoGPT-small",
115
+ },
116
+ {
117
+ name: "Custom model name",
118
+ value: "custom",
119
+ },
120
+ ],
121
+ default: "default",
122
+ },
123
+ ]);
124
+ let selectedModel;
125
+ if (modelChoice === "custom") {
126
+ const { customModel } = await inquirer.prompt([
127
+ {
128
+ type: "input",
129
+ name: "customModel",
130
+ message: "Enter custom model name:",
131
+ validate: (input) => {
132
+ const trimmed = input.trim();
133
+ if (!trimmed) {
134
+ return "Model name is required";
135
+ }
136
+ if (!trimmed.includes("/")) {
137
+ return "Model name should include organization (e.g., 'microsoft/DialoGPT-large')";
138
+ }
139
+ return true;
140
+ },
141
+ },
142
+ ]);
143
+ selectedModel = customModel.trim();
144
+ }
145
+ else if (modelChoice !== "default") {
146
+ selectedModel = modelChoice;
147
+ }
148
+ // If modelChoice === "default", selectedModel remains undefined
149
+ // Save configuration
150
+ spinner.start("Saving configuration...");
151
+ const updates = {
152
+ HUGGINGFACE_API_KEY: apiKey.trim(),
153
+ };
154
+ // Only set model if user didn't choose default
155
+ if (selectedModel) {
156
+ updates.HUGGINGFACE_MODEL = selectedModel;
157
+ }
158
+ try {
159
+ const result = writeEnvFile(updates);
160
+ spinner.stop();
161
+ // Display update summary
162
+ displayEnvUpdateSummary(result, false);
163
+ logger.always(chalk.green("\nāœ… Hugging Face configuration saved successfully!"));
164
+ }
165
+ catch (envError) {
166
+ spinner.stop();
167
+ throw new Error(`Failed to save configuration: ${envError instanceof Error ? envError.message : String(envError)}`);
168
+ }
169
+ logger.always(chalk.blue("\nšŸ“– Usage examples:"));
170
+ logger.always(chalk.gray(' neurolink generate "Hello, how are you?" --provider huggingface'));
171
+ if (selectedModel) {
172
+ logger.always(chalk.gray(` neurolink generate "Tell me a story" --provider huggingface --model ${selectedModel}`));
173
+ }
174
+ else {
175
+ logger.always(chalk.gray(' neurolink generate "Tell me a story" --provider huggingface'));
176
+ logger.always(chalk.gray(' neurolink generate "Explain AI" --provider huggingface --model microsoft/DialoGPT-medium'));
177
+ }
178
+ logger.always(chalk.blue("\nšŸ”— Resources:"));
179
+ logger.always(chalk.gray(" • Hugging Face Models: https://huggingface.co/models"));
180
+ logger.always(chalk.gray(" • API Documentation: https://huggingface.co/docs/api-inference"));
181
+ logger.always(chalk.gray(" • Get API Token: https://huggingface.co/settings/tokens"));
182
+ }
183
+ catch (error) {
184
+ spinner.stop();
185
+ logger.error("Hugging Face setup failed", error);
186
+ throw error;
187
+ }
188
+ };
189
+ export const setupHuggingFaceBuilder = {
190
+ check: {
191
+ type: "boolean",
192
+ describe: "Only check existing configuration without prompting",
193
+ default: false,
194
+ },
195
+ "non-interactive": {
196
+ type: "boolean",
197
+ describe: "Skip interactive prompts",
198
+ default: false,
199
+ },
200
+ };
@@ -0,0 +1,8 @@
1
+ import type { Arguments, CommandBuilder } from "yargs";
2
+ interface SetupMistralArgs {
3
+ check?: boolean;
4
+ "non-interactive"?: boolean;
5
+ }
6
+ export declare const handleMistralSetup: (argv: Arguments<SetupMistralArgs>) => Promise<void>;
7
+ export declare const setupMistralBuilder: CommandBuilder;
8
+ export {};