@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,569 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Google Vertex AI Setup Command
4
+ *
5
+ * Supports three authentication methods:
6
+ * - Method 1: File Path (GOOGLE_APPLICATION_CREDENTIALS)
7
+ * - Method 2: JSON String (GOOGLE_SERVICE_ACCOUNT_KEY)
8
+ * - Method 3: Individual Vars (GOOGLE_AUTH_CLIENT_EMAIL + GOOGLE_AUTH_PRIVATE_KEY)
9
+ *
10
+ * All methods require GOOGLE_VERTEX_PROJECT
11
+ * Optional: GOOGLE_VERTEX_LOCATION (defaults to 'us-east5')
12
+ */
13
+ import fs from "fs";
14
+ import path from "path";
15
+ import os from "os";
16
+ import inquirer from "inquirer";
17
+ import chalk from "chalk";
18
+ import ora from "ora";
19
+ import { logger } from "../../lib/utils/logger.js";
20
+ var AuthMethod;
21
+ (function (AuthMethod) {
22
+ AuthMethod["FILE_PATH"] = "file-path";
23
+ AuthMethod["JSON_STRING"] = "json-string";
24
+ AuthMethod["INDIVIDUAL_VARS"] = "individual-vars";
25
+ })(AuthMethod || (AuthMethod = {}));
26
+ const AUTH_METHOD_NAMES = {
27
+ [AuthMethod.FILE_PATH]: "Method 1: File Path",
28
+ [AuthMethod.JSON_STRING]: "Method 2: JSON String",
29
+ [AuthMethod.INDIVIDUAL_VARS]: "Method 3: Individual Vars",
30
+ };
31
+ export async function handleGCPSetup(argv) {
32
+ try {
33
+ const options = {
34
+ checkOnly: argv.check || false,
35
+ interactive: !argv.nonInteractive,
36
+ };
37
+ logger.always(chalk.blue("🔍 Checking environment..."));
38
+ // Step 1: Detect current authentication method status
39
+ const status = detectAuthMethodStatus();
40
+ // Step 2: Display current status
41
+ displayAuthStatus(status);
42
+ // Check-only mode - show status and exit
43
+ if (options.checkOnly) {
44
+ const completeMethod = getCompleteMethod(status);
45
+ if (completeMethod) {
46
+ logger.always(chalk.green("✅ Google Vertex setup complete with " +
47
+ AUTH_METHOD_NAMES[completeMethod]));
48
+ if (status.common.hasProject) {
49
+ logger.always(` Project: ${process.env.GOOGLE_VERTEX_PROJECT}`);
50
+ }
51
+ if (status.common.hasLocation) {
52
+ logger.always(` Location: ${process.env.GOOGLE_VERTEX_LOCATION}`);
53
+ }
54
+ else {
55
+ logger.always(` Location: us-east5 (default)`);
56
+ }
57
+ }
58
+ return;
59
+ }
60
+ // Step 3: Check if any method is complete and offer to reconfigure
61
+ const completeMethod = getCompleteMethod(status);
62
+ if (completeMethod) {
63
+ logger.always(chalk.green("✅ Current setup: " +
64
+ AUTH_METHOD_NAMES[completeMethod] +
65
+ " (Complete)"));
66
+ if (status.common.hasProject) {
67
+ logger.always(` Project: ${process.env.GOOGLE_VERTEX_PROJECT}`);
68
+ }
69
+ if (status.common.hasLocation) {
70
+ logger.always(` Location: ${process.env.GOOGLE_VERTEX_LOCATION}`);
71
+ }
72
+ else {
73
+ logger.always(` Location: us-east5 (default)`);
74
+ }
75
+ const { reconfigure } = await inquirer.prompt([
76
+ {
77
+ type: "confirm",
78
+ name: "reconfigure",
79
+ message: "Setup is already complete. Do you want to reconfigure or switch methods?",
80
+ default: false,
81
+ },
82
+ ]);
83
+ if (!reconfigure) {
84
+ logger.always(chalk.blue("👍 Keeping existing configuration."));
85
+ return;
86
+ }
87
+ }
88
+ // Step 4: Interactive setup
89
+ if (!options.interactive) {
90
+ logger.always(chalk.yellow("⚠️ Non-interactive mode: setup incomplete"));
91
+ return;
92
+ }
93
+ // Step 5: Method selection
94
+ const selectedMethod = await selectAuthMethod(status);
95
+ logger.always(chalk.blue(`👉 You selected ${AUTH_METHOD_NAMES[selectedMethod]}. Completing setup...`));
96
+ // Step 6: Prompt for missing values
97
+ const config = await promptForMissingValues(selectedMethod, status);
98
+ // Step 7: Update .env file
99
+ await updateEnvFile(selectedMethod, config);
100
+ // Step 8: Success message
101
+ logger.always(chalk.green(`✅ Google Vertex setup complete with ${AUTH_METHOD_NAMES[selectedMethod]}`));
102
+ logger.always(` Project: ${config.project}`);
103
+ logger.always(` Location: ${config.location || "us-east5"}`);
104
+ }
105
+ catch (error) {
106
+ logger.error(chalk.red("❌ GCP setup failed:"));
107
+ logger.error(chalk.red(error instanceof Error ? error.message : "Unknown error"));
108
+ process.exit(1);
109
+ }
110
+ }
111
+ /**
112
+ * Detect the current status of all authentication methods
113
+ */
114
+ function detectAuthMethodStatus() {
115
+ const hasCredentials = !!process.env.GOOGLE_APPLICATION_CREDENTIALS;
116
+ const hasServiceAccountKey = !!process.env.GOOGLE_SERVICE_ACCOUNT_KEY;
117
+ const hasClientEmail = !!process.env.GOOGLE_AUTH_CLIENT_EMAIL;
118
+ const hasPrivateKey = !!process.env.GOOGLE_AUTH_PRIVATE_KEY;
119
+ const hasProject = !!process.env.GOOGLE_VERTEX_PROJECT;
120
+ const hasLocation = !!process.env.GOOGLE_VERTEX_LOCATION;
121
+ const status = {
122
+ method1: {
123
+ complete: hasCredentials && hasProject,
124
+ hasCredentials,
125
+ missingVars: [],
126
+ },
127
+ method2: {
128
+ complete: hasServiceAccountKey && hasProject,
129
+ hasServiceAccountKey,
130
+ missingVars: [],
131
+ },
132
+ method3: {
133
+ complete: hasClientEmail && hasPrivateKey && hasProject,
134
+ hasClientEmail,
135
+ hasPrivateKey,
136
+ missingVars: [],
137
+ },
138
+ common: {
139
+ hasProject,
140
+ hasLocation,
141
+ missingVars: [],
142
+ },
143
+ };
144
+ // Calculate missing variables for each method
145
+ if (!hasCredentials) {
146
+ status.method1.missingVars.push("GOOGLE_APPLICATION_CREDENTIALS");
147
+ }
148
+ if (!hasProject) {
149
+ status.method1.missingVars.push("GOOGLE_VERTEX_PROJECT");
150
+ }
151
+ if (!hasServiceAccountKey) {
152
+ status.method2.missingVars.push("GOOGLE_SERVICE_ACCOUNT_KEY");
153
+ }
154
+ if (!hasProject) {
155
+ status.method2.missingVars.push("GOOGLE_VERTEX_PROJECT");
156
+ }
157
+ if (!hasClientEmail) {
158
+ status.method3.missingVars.push("GOOGLE_AUTH_CLIENT_EMAIL");
159
+ }
160
+ if (!hasPrivateKey) {
161
+ status.method3.missingVars.push("GOOGLE_AUTH_PRIVATE_KEY");
162
+ }
163
+ if (!hasProject) {
164
+ status.method3.missingVars.push("GOOGLE_VERTEX_PROJECT");
165
+ }
166
+ if (!hasProject) {
167
+ status.common.missingVars.push("GOOGLE_VERTEX_PROJECT");
168
+ }
169
+ return status;
170
+ }
171
+ /**
172
+ * Display the current authentication status
173
+ */
174
+ function displayAuthStatus(status) {
175
+ if (status.method1.complete) {
176
+ logger.always(chalk.green("✔ Method 1: Complete"));
177
+ }
178
+ else if (status.method1.hasCredentials) {
179
+ logger.always(chalk.yellow(`⚠ Method 1: Partially set (missing ${status.method1.missingVars.join(", ")})`));
180
+ }
181
+ else {
182
+ logger.always(chalk.red("✘ Method 1: Not set"));
183
+ }
184
+ if (status.method2.complete) {
185
+ logger.always(chalk.green("✔ Method 2: Complete"));
186
+ }
187
+ else if (status.method2.hasServiceAccountKey) {
188
+ logger.always(chalk.yellow(`⚠ Method 2: Partially set (missing ${status.method2.missingVars.join(", ")})`));
189
+ }
190
+ else {
191
+ logger.always(chalk.red("✘ Method 2: Not set"));
192
+ }
193
+ if (status.method3.complete) {
194
+ logger.always(chalk.green("✔ Method 3: Complete"));
195
+ }
196
+ else if (status.method3.hasClientEmail || status.method3.hasPrivateKey) {
197
+ logger.always(chalk.yellow(`⚠ Method 3: Partially set (missing ${status.method3.missingVars.join(", ")})`));
198
+ }
199
+ else {
200
+ logger.always(chalk.red("✘ Method 3: Not set"));
201
+ }
202
+ }
203
+ /**
204
+ * Check if any authentication method is complete
205
+ */
206
+ function getCompleteMethod(status) {
207
+ if (status.method1.complete) {
208
+ return AuthMethod.FILE_PATH;
209
+ }
210
+ if (status.method2.complete) {
211
+ return AuthMethod.JSON_STRING;
212
+ }
213
+ if (status.method3.complete) {
214
+ return AuthMethod.INDIVIDUAL_VARS;
215
+ }
216
+ return null;
217
+ }
218
+ /**
219
+ * Let user select authentication method
220
+ */
221
+ async function selectAuthMethod(status) {
222
+ // Check for partially filled methods
223
+ const partiallyFilledMethods = [];
224
+ if (status.method1.hasCredentials && !status.method1.complete) {
225
+ partiallyFilledMethods.push({
226
+ method: AuthMethod.FILE_PATH,
227
+ name: "Method 1",
228
+ count: 1,
229
+ });
230
+ }
231
+ if (status.method2.hasServiceAccountKey && !status.method2.complete) {
232
+ partiallyFilledMethods.push({
233
+ method: AuthMethod.JSON_STRING,
234
+ name: "Method 2",
235
+ count: 1,
236
+ });
237
+ }
238
+ if ((status.method3.hasClientEmail || status.method3.hasPrivateKey) &&
239
+ !status.method3.complete) {
240
+ const count = (status.method3.hasClientEmail ? 1 : 0) +
241
+ (status.method3.hasPrivateKey ? 1 : 0);
242
+ partiallyFilledMethods.push({
243
+ method: AuthMethod.INDIVIDUAL_VARS,
244
+ name: "Method 3",
245
+ count,
246
+ });
247
+ }
248
+ // If there's a partially filled method, suggest continuing with it
249
+ if (partiallyFilledMethods.length > 0) {
250
+ const partial = partiallyFilledMethods[0];
251
+ const totalVars = partial.method === AuthMethod.INDIVIDUAL_VARS ? 2 : 1;
252
+ logger.always(chalk.yellow(`\nYou already have ${partial.count}/${totalVars} values set for ${partial.name}.`));
253
+ const { continueWithPartial } = await inquirer.prompt([
254
+ {
255
+ type: "confirm",
256
+ name: "continueWithPartial",
257
+ message: `Do you want to continue with ${partial.name} or pick another method?`,
258
+ default: true,
259
+ },
260
+ ]);
261
+ if (continueWithPartial) {
262
+ return partial.method;
263
+ }
264
+ }
265
+ // Present method selection
266
+ const { method } = await inquirer.prompt([
267
+ {
268
+ type: "list",
269
+ name: "method",
270
+ message: "Which authentication method would you like to use?",
271
+ choices: [
272
+ {
273
+ name: "File Path (Recommended for local development)",
274
+ value: AuthMethod.FILE_PATH,
275
+ },
276
+ {
277
+ name: "JSON String (Good for containers/cloud)",
278
+ value: AuthMethod.JSON_STRING,
279
+ },
280
+ {
281
+ name: "Individual Vars (Good for CI/CD)",
282
+ value: AuthMethod.INDIVIDUAL_VARS,
283
+ },
284
+ ],
285
+ },
286
+ ]);
287
+ return method;
288
+ }
289
+ /**
290
+ * Prompt user for missing values based on selected method
291
+ */
292
+ async function promptForMissingValues(method, status) {
293
+ const config = {};
294
+ switch (method) {
295
+ case AuthMethod.FILE_PATH:
296
+ if (!status.method1.hasCredentials) {
297
+ // Try to auto-detect ADC file first
298
+ const adcPath = path.join(os.homedir(), ".config", "gcloud", "application_default_credentials.json");
299
+ if (fs.existsSync(adcPath)) {
300
+ logger.always(chalk.green("✔ Found Application Default Credentials"));
301
+ logger.always(chalk.blue(` Location: ${adcPath}`));
302
+ config.credentialsPath = adcPath;
303
+ }
304
+ else {
305
+ const { credentialsPath } = await inquirer.prompt([
306
+ {
307
+ type: "input",
308
+ name: "credentialsPath",
309
+ message: "Enter the path to your Google Cloud credentials JSON file:",
310
+ validate: validateCredentialsFile,
311
+ transformer: (input) => input.replace(/^~/, os.homedir()),
312
+ },
313
+ ]);
314
+ config.credentialsPath = credentialsPath.replace(/^~/, os.homedir());
315
+ }
316
+ }
317
+ break;
318
+ case AuthMethod.JSON_STRING:
319
+ if (!status.method2.hasServiceAccountKey) {
320
+ const { serviceAccountKey } = await inquirer.prompt([
321
+ {
322
+ type: "password",
323
+ mask: "*",
324
+ name: "serviceAccountKey",
325
+ message: "Enter your service account JSON as a string:",
326
+ validate: validateServiceAccountJSON,
327
+ },
328
+ ]);
329
+ config.serviceAccountKey = serviceAccountKey;
330
+ }
331
+ break;
332
+ case AuthMethod.INDIVIDUAL_VARS:
333
+ if (!status.method3.hasClientEmail) {
334
+ const { clientEmail } = await inquirer.prompt([
335
+ {
336
+ type: "input",
337
+ name: "clientEmail",
338
+ message: "Enter your service account client email (format: name@project.iam.gserviceaccount.com):",
339
+ validate: (input) => {
340
+ if (!input.trim()) {
341
+ return "Client email is required";
342
+ }
343
+ // Check for basic email format
344
+ if (!input.includes("@")) {
345
+ return "Invalid email format. Expected: service-account@project-id.iam.gserviceaccount.com";
346
+ }
347
+ // Check for Google service account domain
348
+ if (!input.endsWith(".iam.gserviceaccount.com")) {
349
+ return "Invalid service account email. Must end with '.iam.gserviceaccount.com'\nExample: my-service-account@my-project.iam.gserviceaccount.com";
350
+ }
351
+ // Validate the structure: name@project.iam.gserviceaccount.com
352
+ const emailPattern = /^[a-z0-9-]+@[a-z0-9-]+\.iam\.gserviceaccount\.com$/;
353
+ if (!emailPattern.test(input.trim())) {
354
+ return "Invalid format. Expected: service-account-name@project-id.iam.gserviceaccount.com\nExample: my-service-account@my-project-123.iam.gserviceaccount.com";
355
+ }
356
+ return true;
357
+ },
358
+ },
359
+ ]);
360
+ config.clientEmail = clientEmail.trim();
361
+ }
362
+ if (!status.method3.hasPrivateKey) {
363
+ const { privateKey } = await inquirer.prompt([
364
+ {
365
+ type: "password",
366
+ mask: "*",
367
+ name: "privateKey",
368
+ message: "Enter your service account private key:",
369
+ validate: (input) => {
370
+ if (!input.trim()) {
371
+ return "Private key is required";
372
+ }
373
+ if (!input.includes("BEGIN PRIVATE KEY") ||
374
+ !input.includes("END PRIVATE KEY")) {
375
+ return "Invalid private key format. Should include BEGIN and END markers.";
376
+ }
377
+ return true;
378
+ },
379
+ },
380
+ ]);
381
+ config.privateKey = privateKey.trim();
382
+ }
383
+ break;
384
+ }
385
+ // Always prompt for project if missing
386
+ if (!status.common.hasProject) {
387
+ const { project } = await inquirer.prompt([
388
+ {
389
+ type: "input",
390
+ name: "project",
391
+ message: "Enter your Google Cloud Project ID:",
392
+ validate: (input) => {
393
+ if (!input.trim()) {
394
+ return "Project ID is required";
395
+ }
396
+ if (!/^[a-z][a-z0-9-]{4,28}[a-z0-9]$/.test(input.trim())) {
397
+ return "Invalid project ID format. Must be 6-30 characters, start with lowercase letter, contain only lowercase letters, numbers, and hyphens.";
398
+ }
399
+ return true;
400
+ },
401
+ },
402
+ ]);
403
+ config.project = project.trim();
404
+ }
405
+ else {
406
+ config.project = process.env.GOOGLE_VERTEX_PROJECT;
407
+ }
408
+ // Always prompt for location if missing, with default
409
+ if (!status.common.hasLocation) {
410
+ const { location } = await inquirer.prompt([
411
+ {
412
+ type: "input",
413
+ name: "location",
414
+ message: "Enter your Google Vertex AI location:",
415
+ default: "us-east5",
416
+ validate: (input) => {
417
+ if (!input.trim()) {
418
+ return "Location is required";
419
+ }
420
+ return true;
421
+ },
422
+ },
423
+ ]);
424
+ config.location = location.trim();
425
+ }
426
+ else {
427
+ config.location = process.env.GOOGLE_VERTEX_LOCATION;
428
+ }
429
+ return config;
430
+ }
431
+ /**
432
+ * Validate credentials file path
433
+ */
434
+ function validateCredentialsFile(input) {
435
+ if (!input.trim()) {
436
+ return "Credentials path is required";
437
+ }
438
+ const expandedPath = input.replace(/^~/, os.homedir());
439
+ if (!fs.existsSync(expandedPath)) {
440
+ return `File not found: ${expandedPath}`;
441
+ }
442
+ try {
443
+ const content = fs.readFileSync(expandedPath, "utf8");
444
+ const parsed = JSON.parse(content);
445
+ if (!parsed.client_email || !parsed.private_key) {
446
+ return "Invalid service account file: missing client_email or private_key";
447
+ }
448
+ return true;
449
+ }
450
+ catch {
451
+ return "Invalid JSON file";
452
+ }
453
+ }
454
+ /**
455
+ * Validate service account JSON string
456
+ */
457
+ function validateServiceAccountJSON(input) {
458
+ if (!input.trim()) {
459
+ return "Service account JSON is required";
460
+ }
461
+ try {
462
+ const parsed = JSON.parse(input.trim());
463
+ if (!parsed.client_email || !parsed.private_key) {
464
+ return "Invalid service account JSON: missing client_email or private_key";
465
+ }
466
+ return true;
467
+ }
468
+ catch {
469
+ return "Invalid JSON format";
470
+ }
471
+ }
472
+ /**
473
+ * Update .env file with selected authentication method
474
+ */
475
+ async function updateEnvFile(method, config) {
476
+ const envPath = path.join(process.cwd(), ".env");
477
+ const spinner = ora("💾 Updating .env file...").start();
478
+ try {
479
+ let envContent = "";
480
+ // Read existing .env file if it exists
481
+ if (fs.existsSync(envPath)) {
482
+ envContent = fs.readFileSync(envPath, "utf8");
483
+ }
484
+ // Parse existing environment variables
485
+ const envLines = envContent.split("\n");
486
+ const existingVars = new Map();
487
+ const otherLines = [];
488
+ for (const line of envLines) {
489
+ const trimmed = line.trim();
490
+ if (trimmed && !trimmed.startsWith("#")) {
491
+ const equalsIndex = trimmed.indexOf("=");
492
+ if (equalsIndex > 0) {
493
+ const key = trimmed.substring(0, equalsIndex);
494
+ const value = trimmed.substring(equalsIndex + 1);
495
+ existingVars.set(key, value);
496
+ }
497
+ else {
498
+ otherLines.push(line);
499
+ }
500
+ }
501
+ else {
502
+ otherLines.push(line);
503
+ }
504
+ }
505
+ // Remove all Google Vertex auth variables first (clean slate)
506
+ existingVars.delete("GOOGLE_APPLICATION_CREDENTIALS");
507
+ existingVars.delete("GOOGLE_SERVICE_ACCOUNT_KEY");
508
+ existingVars.delete("GOOGLE_AUTH_CLIENT_EMAIL");
509
+ existingVars.delete("GOOGLE_AUTH_PRIVATE_KEY");
510
+ // Set variables for selected method
511
+ switch (method) {
512
+ case AuthMethod.FILE_PATH:
513
+ if (config.credentialsPath) {
514
+ existingVars.set("GOOGLE_APPLICATION_CREDENTIALS", config.credentialsPath);
515
+ }
516
+ break;
517
+ case AuthMethod.JSON_STRING:
518
+ if (config.serviceAccountKey) {
519
+ existingVars.set("GOOGLE_SERVICE_ACCOUNT_KEY", config.serviceAccountKey);
520
+ }
521
+ break;
522
+ case AuthMethod.INDIVIDUAL_VARS:
523
+ if (config.clientEmail) {
524
+ existingVars.set("GOOGLE_AUTH_CLIENT_EMAIL", config.clientEmail);
525
+ }
526
+ if (config.privateKey) {
527
+ const escaped = config.privateKey
528
+ .replace(/\r?\n/g, "\\n")
529
+ .replace(/"/g, '\\"');
530
+ existingVars.set("GOOGLE_AUTH_PRIVATE_KEY", `"${escaped}"`);
531
+ }
532
+ break;
533
+ }
534
+ // Always set project and location
535
+ if (config.project) {
536
+ existingVars.set("GOOGLE_VERTEX_PROJECT", config.project);
537
+ }
538
+ if (config.location) {
539
+ existingVars.set("GOOGLE_VERTEX_LOCATION", config.location);
540
+ }
541
+ // Reconstruct .env content preserving structure
542
+ const newEnvLines = [];
543
+ // Add non-variable lines first (comments, empty lines)
544
+ for (const line of otherLines) {
545
+ newEnvLines.push(line);
546
+ }
547
+ // Add separator comment for Google Vertex if needed
548
+ if (!envContent.includes("GOOGLE VERTEX AI CONFIGURATION")) {
549
+ if (newEnvLines.length > 0 &&
550
+ newEnvLines[newEnvLines.length - 1].trim()) {
551
+ newEnvLines.push("");
552
+ }
553
+ newEnvLines.push("# GOOGLE VERTEX AI CONFIGURATION");
554
+ }
555
+ // Add all environment variables
556
+ for (const [key, value] of existingVars.entries()) {
557
+ newEnvLines.push(`${key}=${value}`);
558
+ }
559
+ // Write updated content
560
+ const finalContent = newEnvLines.join("\n") + (newEnvLines.length > 0 ? "\n" : "");
561
+ fs.writeFileSync(envPath, finalContent, "utf8");
562
+ spinner.succeed(chalk.green("✔ .env file updated successfully"));
563
+ }
564
+ catch (error) {
565
+ spinner.fail(chalk.red("❌ Failed to update .env file"));
566
+ logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
567
+ throw error;
568
+ }
569
+ }
@@ -0,0 +1,16 @@
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
+ interface GoogleAISetupArgv {
12
+ check?: boolean;
13
+ nonInteractive?: boolean;
14
+ }
15
+ export declare function handleGoogleAISetup(argv: GoogleAISetupArgv): Promise<void>;
16
+ export {};