vibecodingmachine-cli 2025.12.1-534 → 2025.12.22-2230

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.
@@ -0,0 +1,212 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const os = require('os');
4
+ const { execSync } = require('child_process');
5
+ const ora = require('ora');
6
+ const chalk = require('chalk');
7
+
8
+ async function installAntigravity() {
9
+ console.log(chalk.cyan('\nšŸš€ Initiating Google Antigravity IDE Installation...'));
10
+
11
+ const spinner = ora('Checking system requirements...').start();
12
+ await new Promise((r) => setTimeout(r, 800));
13
+
14
+ if (os.platform() !== 'darwin') {
15
+ spinner.fail('Automated Antigravity installation is only supported on macOS');
16
+ return false;
17
+ }
18
+
19
+ const arch = os.arch();
20
+ const isArm = arch === 'arm64';
21
+
22
+ // URLs from electron-app IDE installer
23
+ const downloadUrl = isArm
24
+ ? 'https://edgedl.me.gvt1.com/edgedl/release2/j0qc3/antigravity/stable/1.11.2-6251250307170304/darwin-arm/Antigravity.dmg'
25
+ : 'https://edgedl.me.gvt1.com/edgedl/release2/j0qc3/antigravity/stable/1.11.2-6251250307170304/darwin-x64/Antigravity.dmg';
26
+
27
+ spinner.succeed(`System OK (${isArm ? 'Apple Silicon' : 'Intel'})`);
28
+
29
+ try {
30
+ const cacheDir = path.join(os.homedir(), '.vibecodingmachine', 'cache');
31
+ await fs.ensureDir(cacheDir);
32
+ const cachedPath = path.join(cacheDir, 'Antigravity.dmg');
33
+ const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'antigravity-'));
34
+ const dmgPath = path.join(tempDir, 'Antigravity.dmg');
35
+ const { downloadWithProgress } = require('./download-with-progress');
36
+
37
+ // Prefer cached DMG if it exists and matches upstream size (or exists at all)
38
+ let usedCache = false;
39
+ try {
40
+ if (await fs.pathExists(cachedPath)) {
41
+ // Try HEAD to compare sizes
42
+ try {
43
+ const fetch = require('node-fetch');
44
+ const head = await fetch(downloadUrl, { method: 'HEAD' });
45
+ const total = Number(head.headers.get('content-length')) || 0;
46
+ const stat = await fs.stat(cachedPath);
47
+ if (total && stat.size === total) {
48
+ await fs.copy(cachedPath, dmgPath);
49
+ usedCache = true;
50
+ console.log(chalk.gray('Using cached Antigravity DMG'));
51
+ }
52
+ } catch (e) {
53
+ // If HEAD fails, still allow reuse of cache to avoid re-download
54
+ await fs.copy(cachedPath, dmgPath);
55
+ usedCache = true;
56
+ console.log(chalk.gray('Using cached Antigravity DMG (no HEAD)'));
57
+ }
58
+ }
59
+ } catch (e) {
60
+ // ignore cache errors
61
+ usedCache = false;
62
+ }
63
+
64
+ // Use download helper which displays progress and ETA if we didn't reuse cache
65
+ if (!usedCache) {
66
+ await downloadWithProgress(downloadUrl, dmgPath, { label: 'Downloading Antigravity...' });
67
+ // Save to cache for future runs
68
+ try { await fs.copy(dmgPath, cachedPath); } catch (e) { /* ignore cache write errors */ }
69
+ }
70
+
71
+ const installSpinner = ora('Installing Antigravity...').start();
72
+
73
+ try {
74
+ installSpinner.text = 'Mounting disk image...';
75
+ execSync(`hdiutil attach "${dmgPath}" -nobrowse -noverify -mountpoint "${tempDir}/mount"`);
76
+
77
+ installSpinner.text = 'Copying to /Applications...';
78
+ const files = await fs.readdir(path.join(tempDir, 'mount'));
79
+ const appName = files.find((f) => f.endsWith('.app'));
80
+ if (!appName) throw new Error('Could not find .app in DMG');
81
+
82
+ const src = path.join(tempDir, 'mount', appName);
83
+ const dest = path.join('/Applications', appName);
84
+
85
+ if (await fs.pathExists(dest)) {
86
+ installSpinner.text = 'Replacing existing application...';
87
+ await fs.remove(dest);
88
+ }
89
+
90
+ // Prefer rsync/ditto; fallback to node-stream copy with progress
91
+ try {
92
+ const { copyAppWithProgress } = require('./copy-with-progress');
93
+ installSpinner.stop();
94
+ const ok = await copyAppWithProgress(src, dest, { spinner: installSpinner });
95
+ if (!ok) {
96
+ installSpinner.text = 'Copying (fs fallback) to /Applications...';
97
+ await fs.copy(src, dest);
98
+ }
99
+ } catch (e) {
100
+ // final fallback
101
+ installSpinner.text = 'Copying (fs fallback) to /Applications...';
102
+ try {
103
+ execSync(`cp -R "${src}" "/Applications/"`, { stdio: 'inherit' });
104
+ } catch (err) {
105
+ await fs.copy(src, dest);
106
+ }
107
+ }
108
+
109
+ installSpinner.text = 'Cleaning up...';
110
+ execSync(`hdiutil detach "${tempDir}/mount" -force`);
111
+ await fs.remove(tempDir);
112
+
113
+ installSpinner.succeed('Antigravity installed');
114
+ console.log(chalk.green(`\nāœ… Installed to ${dest}`));
115
+ // Attempt to automatically configure Antigravity's first-run settings
116
+ try {
117
+ await configureAntigravityDefaults(dest);
118
+ } catch (e) {
119
+ // Non-fatal: log and continue
120
+ console.log(chalk.yellow('Warning: could not auto-configure Antigravity:'), e.message || e);
121
+ }
122
+
123
+ return true;
124
+ } catch (err) {
125
+ installSpinner.fail('Installation failed');
126
+ try {
127
+ if (await fs.pathExists(path.join(tempDir, 'mount'))) {
128
+ execSync(`hdiutil detach "${tempDir}/mount" -force`);
129
+ }
130
+ try { await fs.remove(tempDir); } catch (e) { /* ignore */ }
131
+ console.log(chalk.red('\nInstallation error:'), err.message);
132
+ return false;
133
+ }
134
+ } catch (error) {
135
+ console.log(chalk.red('\nFailed to install Antigravity:'), error.message);
136
+ return false;
137
+ }
138
+ }
139
+
140
+ async function configureAntigravityDefaults() {
141
+ // Attempt to open Antigravity and set the onboarding defaults via AppleScript
142
+ // Desired selections:
143
+ // - Agent-driven development (instead of recommended Agent-assisted)
144
+ // - Terminal execution policy: Turbo
145
+ // - Review policy: Always Proceed
146
+ // - Use the default allowlist for the browser (checked)
147
+ try {
148
+ const script = `
149
+ tell application "Antigravity"
150
+ activate
151
+ end tell
152
+ delay 0.8
153
+ tell application "System Events"
154
+ tell process "Antigravity"
155
+ set frontmost to true
156
+ delay 0.5
157
+ -- Try to select Agent-driven development radio button
158
+ try
159
+ click radio button "Agent-driven development" of radio group 1 of window 1
160
+ delay 0.2
161
+ end try
162
+
163
+ -- Set Terminal execution policy to Turbo (attempt by label, then by index)
164
+ try
165
+ try
166
+ click pop up button "Terminal execution policy" of window 1
167
+ delay 0.2
168
+ click menu item "Turbo" of menu 1 of pop up button "Terminal execution policy" of window 1
169
+ on error
170
+ -- fallback: click first pop up button and choose Turbo
171
+ click pop up button 1 of window 1
172
+ delay 0.2
173
+ click menu item "Turbo" of menu 1 of pop up button 1 of window 1
174
+ end try
175
+ delay 0.2
176
+ end try
177
+
178
+ -- Set Review policy to Always Proceed
179
+ try
180
+ click pop up button "Review policy" of window 1
181
+ delay 0.2
182
+ click menu item "Always Proceed" of menu 1 of pop up button "Review policy" of window 1
183
+ delay 0.2
184
+ end try
185
+
186
+ -- Ensure default allowlist checkbox is checked
187
+ try
188
+ set cb to checkbox "Use the default allowlist for the browser" of window 1
189
+ if (value of cb as boolean) is false then click cb
190
+ delay 0.2
191
+ end try
192
+
193
+ -- Advance the onboarding if a Next/Done button exists
194
+ try
195
+ if exists button "Next" of window 1 then click button "Next" of window 1
196
+ delay 0.3
197
+ end try
198
+ end tell
199
+ end tell
200
+ `;
201
+
202
+ // Use osascript to run the UI automation. JSON-stringify ensures safe quoting.
203
+ const { execSync } = require('child_process');
204
+ execSync(`osascript -e ${JSON.stringify(script)}`, { stdio: 'ignore', timeout: 15000 });
205
+ console.log(chalk.gray('Auto-configured Antigravity first-run preferences'));
206
+ return true;
207
+ } catch (err) {
208
+ throw new Error(err.message || err);
209
+ }
210
+ }
211
+
212
+ module.exports = { installAntigravity };
@@ -0,0 +1,60 @@
1
+ const chalk = require('chalk');
2
+ const {
3
+ getProviderPreferences,
4
+ saveProviderPreferences
5
+ } = require('./provider-registry');
6
+
7
+ /**
8
+ * Check if Antigravity agent has hit a rate limit.
9
+ * @param {string} stderr - Standard error output from the agent.
10
+ * @returns {{isRateLimited: boolean, message: string|null}} - Rate limit status and message.
11
+ */
12
+ function checkAntigravityRateLimit(stderr) {
13
+ const rateLimitPatterns = [
14
+ /quota limit/i,
15
+ /rate limit/i,
16
+ /too many requests/i,
17
+ /limit exceeded/i
18
+ ];
19
+
20
+ for (const pattern of rateLimitPatterns) {
21
+ if (pattern.test(stderr)) {
22
+ return {
23
+ isRateLimited: true,
24
+ message: 'Antigravity quota limit reached.'
25
+ };
26
+ }
27
+ }
28
+
29
+ return { isRateLimited: false, message: null };
30
+ }
31
+
32
+ /**
33
+ * Handle rate limit for Antigravity by disabling it and selecting the next available provider.
34
+ * @returns {Promise<{success: boolean, nextProvider: string|null, error: string|null}>}
35
+ */
36
+ async function handleAntigravityRateLimit() {
37
+ console.log(chalk.yellow('Antigravity rate limit detected. Disabling for this session.'));
38
+
39
+ try {
40
+ const prefs = await getProviderPreferences();
41
+ prefs.enabled.antigravity = false;
42
+ await saveProviderPreferences(prefs);
43
+
44
+ const nextProvider = prefs.order.find(p => p !== 'antigravity' && prefs.enabled[p]);
45
+
46
+ if (nextProvider) {
47
+ console.log(chalk.cyan(`Switching to next available provider: ${nextProvider}`));
48
+ return { success: true, nextProvider, error: null };
49
+ } else {
50
+ return { success: false, nextProvider: null, error: 'No fallback providers available.' };
51
+ }
52
+ } catch (error) {
53
+ return { success: false, nextProvider: null, error: 'Failed to update provider preferences.' };
54
+ }
55
+ }
56
+
57
+ module.exports = {
58
+ checkAntigravityRateLimit,
59
+ handleAntigravityRateLimit
60
+ };
@@ -0,0 +1,60 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+
4
+ /**
5
+ * Scans the assets directory and removes 0-byte PNG files
6
+ * This is a mitigation for an issue where empty PNG files are mysteriously created
7
+ */
8
+ async function cleanupBrokenAssets() {
9
+ try {
10
+ // Find assets directory - assuming we are in packages/cli/src/utils
11
+ // and assets is at root of repo, but simpler to look relative to where VCM runs
12
+ // effectively, we look for 'assets' in the current working directory as CWD is usually the repo root or where the CLI is run
13
+ // Better: define path relative to the project root if possible, or CWD if that's how it's structured.
14
+ // Based on previous search, assets/ is at the root of the repo.
15
+ // However, when installed, strict paths matters.
16
+ // But for the user's workspace context, iterating 'assets/' in CWD (repo root) is correct for their dev environment.
17
+ // Let's try to be smart about finding specific 'assets' dir if we can, but CWD is a safe start for the CLI tool which is often run from root.
18
+
19
+ // Actually, looking at previous grep, `assets/` was checked specifically.
20
+ // Let's just check `assets` in process.cwd() as a primary target.
21
+
22
+ const assetsDir = path.join(process.cwd(), 'assets');
23
+
24
+ if (!await fs.pathExists(assetsDir)) {
25
+ return; // No assets dir, nothing to clean
26
+ }
27
+
28
+ const files = await fs.readdir(assetsDir);
29
+ let removedCount = 0;
30
+
31
+ for (const file of files) {
32
+ if (file.toLowerCase().endsWith('.png')) {
33
+ const filePath = path.join(assetsDir, file);
34
+ try {
35
+ const stats = await fs.stat(filePath);
36
+ if (stats.size === 0) {
37
+ await fs.remove(filePath);
38
+ removedCount++;
39
+ }
40
+ } catch (err) {
41
+ // Ignore errors accessing specific files
42
+ }
43
+ }
44
+ }
45
+
46
+ if (removedCount > 0) {
47
+ // Only log if we actually did something, to keep noise down
48
+ // But maybe we want to know? The plan said "verification: verify removed".
49
+ // We can use a debug flag or just log.
50
+ // Let's log to console for now as it's a CLI tool.
51
+ // console.log(chalk.gray(`Cleaned up ${removedCount} broken (0-byte) asset files.`));
52
+ }
53
+
54
+ } catch (error) {
55
+ // Silently fail to avoid disrupting startup
56
+ // console.error('Asset cleanup failed:', error);
57
+ }
58
+ }
59
+
60
+ module.exports = { cleanupBrokenAssets };
package/src/utils/auth.js CHANGED
@@ -2,7 +2,6 @@ const chalk = require('chalk');
2
2
  const http = require('http');
3
3
  const crypto = require('crypto');
4
4
  const fs = require('fs');
5
- const path = require('path');
6
5
  const net = require('net');
7
6
  const sharedAuth = require('vibecodingmachine-core/src/auth/shared-auth-storage');
8
7
 
@@ -31,7 +30,37 @@ class CLIAuth {
31
30
  * Check if authenticated (uses shared storage)
32
31
  */
33
32
  async isAuthenticated() {
34
- return await sharedAuth.isAuthenticated();
33
+ // First check if current token is valid
34
+ const isValid = await sharedAuth.isAuthenticated();
35
+ if (isValid) {
36
+ // Update user activity in database
37
+ await this._updateUserActivity();
38
+ return true;
39
+ }
40
+
41
+ // If not valid, try to refresh
42
+ try {
43
+ const refreshToken = await sharedAuth.getRefreshToken();
44
+ if (refreshToken) {
45
+ // console.log(chalk.gray('Refreshing session...'));
46
+ const newTokens = await this._refreshTokens(refreshToken);
47
+
48
+ // Validate new ID token
49
+ await this._validateToken(newTokens.id_token);
50
+
51
+ // Save new tokens
52
+ await sharedAuth.saveToken(newTokens);
53
+
54
+ // Update user activity in database
55
+ await this._updateUserActivity();
56
+ return true;
57
+ }
58
+ } catch (error) {
59
+ // Refresh failed (token expired or revoked), user needs to login again
60
+ // console.log(chalk.gray('Session refresh failed, please login again.'));
61
+ }
62
+
63
+ return false;
35
64
  }
36
65
 
37
66
  /**
@@ -82,7 +111,7 @@ class CLIAuth {
82
111
  res.on('end', () => {
83
112
  if (res.statusCode === 200) {
84
113
  const tokens = JSON.parse(data);
85
- resolve(tokens.id_token); // Return the ID token
114
+ resolve(tokens); // Return full tokens object
86
115
  } else {
87
116
  reject(new Error(`Token exchange failed: ${res.statusCode} - ${data}`));
88
117
  }
@@ -97,7 +126,53 @@ class CLIAuth {
97
126
  req.end();
98
127
  });
99
128
  }
129
+ /**
130
+ * Refresh tokens using refresh_token
131
+ */
132
+ async _refreshTokens(refreshToken) {
133
+ const https = require('https');
134
+
135
+ const tokenEndpoint = `https://${COGNITO_DOMAIN}/oauth2/token`;
136
+ const postData = new URLSearchParams({
137
+ grant_type: 'refresh_token',
138
+ client_id: CLIENT_ID,
139
+ refresh_token: refreshToken
140
+ }).toString();
100
141
 
142
+ return new Promise((resolve, reject) => {
143
+ const options = {
144
+ method: 'POST',
145
+ headers: {
146
+ 'Content-Type': 'application/x-www-form-urlencoded',
147
+ 'Content-Length': postData.length
148
+ }
149
+ };
150
+
151
+ const req = https.request(tokenEndpoint, options, (res) => {
152
+ let data = '';
153
+ res.on('data', (chunk) => { data += chunk; });
154
+ res.on('end', () => {
155
+ if (res.statusCode === 200) {
156
+ const tokens = JSON.parse(data);
157
+ // Cognito might not return a new refresh token, so we keep the old one if not provided
158
+ if (!tokens.refresh_token) {
159
+ tokens.refresh_token = refreshToken;
160
+ }
161
+ resolve(tokens);
162
+ } else {
163
+ reject(new Error(`Token refresh failed: ${res.statusCode} - ${data}`));
164
+ }
165
+ });
166
+ });
167
+
168
+ req.on('error', (error) => {
169
+ reject(new Error(`Token refresh request failed: ${error.message}`));
170
+ });
171
+
172
+ req.write(postData);
173
+ req.end();
174
+ });
175
+ }
101
176
  /**
102
177
  * Validate JWT token with signature verification
103
178
  * @param {string} idToken - JWT token to validate
@@ -312,18 +387,25 @@ class CLIAuth {
312
387
  try {
313
388
  // Exchange code for tokens
314
389
  console.log(chalk.gray('Exchanging authorization code for tokens...'));
315
- const idToken = await this._exchangeCodeForTokens(
390
+ // Exchange code for tokens
391
+ console.log(chalk.gray('Exchanging authorization code for tokens...'));
392
+ const tokens = await this._exchangeCodeForTokens(
316
393
  code,
317
394
  codeVerifier,
318
395
  `http://localhost:${PORT}/callback`
319
396
  );
320
397
 
398
+ const idToken = tokens.id_token;
399
+
321
400
  // Validate token (signature + claims)
322
401
  console.log(chalk.gray('Validating token...'));
323
402
  await this._validateToken(idToken);
324
403
 
325
404
  // Save token
326
- await sharedAuth.saveToken(idToken);
405
+ await sharedAuth.saveToken(tokens);
406
+
407
+ // Register/update user in enhanced database
408
+ await this._registerUserInDatabase(idToken);
327
409
 
328
410
  // Show success page
329
411
  res.writeHead(200, {
@@ -428,7 +510,7 @@ class CLIAuth {
428
510
  serverClosed = true;
429
511
  server.close();
430
512
  console.log(chalk.green('āœ“ Authentication successful!\n'));
431
- resolve(idToken);
513
+ resolve(tokens.id_token);
432
514
  }
433
515
  } catch (error) {
434
516
  // Token exchange or validation failed
@@ -560,12 +642,16 @@ class CLIAuth {
560
642
 
561
643
  // Exchange code for tokens
562
644
  console.log(chalk.gray('Exchanging authorization code for tokens...'));
563
- const idToken = await this._exchangeCodeForTokens(
645
+ // Exchange code for tokens
646
+ console.log(chalk.gray('Exchanging authorization code for tokens...'));
647
+ const tokens = await this._exchangeCodeForTokens(
564
648
  code,
565
649
  codeVerifier,
566
650
  'http://localhost:3000/callback'
567
651
  );
568
652
 
653
+ const idToken = tokens.id_token;
654
+
569
655
  // Validate JWT token
570
656
  console.log(chalk.gray('Validating token...'));
571
657
  try {
@@ -577,7 +663,10 @@ class CLIAuth {
577
663
  }
578
664
 
579
665
  // Save token using shared storage (only if validation passed)
580
- await sharedAuth.saveToken(idToken);
666
+ await sharedAuth.saveToken(tokens);
667
+
668
+ // Register/update user in enhanced database
669
+ await this._registerUserInDatabase(idToken);
581
670
 
582
671
  console.log(chalk.green('\nāœ“ Authentication successful!'));
583
672
  return idToken;
@@ -614,6 +703,141 @@ class CLIAuth {
614
703
  async activateLicense(licenseKey) {
615
704
  return await sharedAuth.activateLicense(licenseKey);
616
705
  }
706
+
707
+ /**
708
+ * Register or update user in enhanced database system
709
+ */
710
+ async _registerUserInDatabase(idToken) {
711
+ try {
712
+ // Decode JWT to get user info (without verification since we already validated)
713
+ const payload = JSON.parse(Buffer.from(idToken.split('.')[1], 'base64').toString());
714
+
715
+ const UserDatabase = require('vibecodingmachine-core/src/database/user-schema');
716
+ const userDb = new UserDatabase();
717
+
718
+ const userInfo = {
719
+ email: payload.email,
720
+ name: payload.name || payload.email.split('@')[0],
721
+ cognitoId: payload.sub
722
+ };
723
+
724
+ // Register/update user
725
+ const user = await userDb.registerUser(userInfo);
726
+
727
+ // Register computer
728
+ await userDb.registerComputer(user.userId, {
729
+ interface: 'cli'
730
+ });
731
+
732
+ // Track login activity
733
+ await userDb.trackActivity(user.userId, {
734
+ interface: 'cli',
735
+ action: 'login',
736
+ duration: 0,
737
+ metadata: {
738
+ authMethod: 'cognito',
739
+ timestamp: Date.now()
740
+ }
741
+ });
742
+
743
+ } catch (error) {
744
+ // Don't fail authentication if database registration fails
745
+ console.error('Warning: Failed to register user in database:', error.message);
746
+ }
747
+ }
748
+
749
+ /**
750
+ * Update user activity in database
751
+ */
752
+ async _updateUserActivity() {
753
+ try {
754
+ const token = await sharedAuth.getToken();
755
+ if (!token || !token.id_token) return;
756
+
757
+ // Decode JWT to get user info
758
+ const payload = JSON.parse(Buffer.from(token.id_token.split('.')[1], 'base64').toString());
759
+
760
+ const UserDatabase = require('vibecodingmachine-core/src/database/user-schema');
761
+ const userDb = new UserDatabase();
762
+
763
+ const userId = userDb.generateUserId(payload.email);
764
+
765
+ // Update last activity
766
+ await userDb.updateUserActivity(userId, {
767
+ lastActivity: Date.now()
768
+ });
769
+
770
+ } catch (error) {
771
+ // Silently fail - don't disrupt user experience
772
+ console.error('Warning: Failed to update user activity:', error.message);
773
+ }
774
+ }
775
+
776
+ /**
777
+ * Track CLI usage activity
778
+ */
779
+ async trackCLIActivity(action, metadata = {}) {
780
+ try {
781
+ const token = await sharedAuth.getToken();
782
+ if (!token) return;
783
+
784
+ // Handle both string tokens and object tokens with id_token property
785
+ const idToken = typeof token === 'string' ? token : token.id_token;
786
+ if (!idToken) return;
787
+
788
+ const payload = JSON.parse(Buffer.from(idToken.split('.')[1], 'base64').toString());
789
+
790
+ const UserDatabase = require('vibecodingmachine-core/src/database/user-schema');
791
+ const userDb = new UserDatabase();
792
+
793
+ const userId = userDb.generateUserId(payload.email);
794
+
795
+ await userDb.trackActivity(userId, {
796
+ interface: 'cli',
797
+ action,
798
+ duration: metadata.duration || 0,
799
+ metadata: {
800
+ ...metadata,
801
+ timestamp: Date.now()
802
+ }
803
+ });
804
+
805
+ } catch (error) {
806
+ // Silently fail - don't disrupt user experience
807
+ console.error('Warning: Failed to track CLI activity:', error.message);
808
+ }
809
+ }
810
+
811
+ /**
812
+ * Get current user information
813
+ */
814
+ async getCurrentUser() {
815
+ try {
816
+ const token = await sharedAuth.getToken();
817
+ if (!token) return null;
818
+
819
+ // Handle both string token and object with id_token
820
+ const idToken = typeof token === 'string' ? token : token.id_token;
821
+ if (!idToken) return null;
822
+
823
+ const payload = JSON.parse(Buffer.from(idToken.split('.')[1], 'base64').toString());
824
+
825
+ const UserDatabase = require('vibecodingmachine-core/src/database/user-schema');
826
+ const userDb = new UserDatabase();
827
+
828
+ const userId = userDb.generateUserId(payload.email);
829
+
830
+ return {
831
+ userId,
832
+ email: payload.email,
833
+ name: payload.name || payload.email.split('@')[0],
834
+ cognitoId: payload.sub
835
+ };
836
+ } catch (error) {
837
+ console.error('Error getting current user:', error.message);
838
+ return null;
839
+ }
840
+ }
617
841
  }
618
842
 
619
843
  module.exports = new CLIAuth();
@@ -1,6 +1,5 @@
1
1
  const chalk = require('chalk');
2
2
  const ansiEscapes = require('ansi-escapes');
3
- const stripAnsi = require('strip-ansi');
4
3
 
5
4
  /**
6
5
  * ANSI-based UI for Auto Mode