vibecodingmachine-core 1.0.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 (54) hide show
  1. package/.babelrc +13 -0
  2. package/README.md +28 -0
  3. package/__tests__/applescript-manager-claude-fix.test.js +286 -0
  4. package/__tests__/requirement-2-auto-start-looping.test.js +69 -0
  5. package/__tests__/requirement-3-auto-start-looping.test.js +69 -0
  6. package/__tests__/requirement-4-auto-start-looping.test.js +69 -0
  7. package/__tests__/requirement-6-auto-start-looping.test.js +73 -0
  8. package/__tests__/requirement-7-status-tracking.test.js +332 -0
  9. package/jest.config.js +18 -0
  10. package/jest.setup.js +12 -0
  11. package/package.json +46 -0
  12. package/src/auth/access-denied.html +119 -0
  13. package/src/auth/shared-auth-storage.js +230 -0
  14. package/src/autonomous-mode/feature-implementer.cjs +70 -0
  15. package/src/autonomous-mode/feature-implementer.js +425 -0
  16. package/src/chat-management/chat-manager.cjs +71 -0
  17. package/src/chat-management/chat-manager.js +342 -0
  18. package/src/ide-integration/__tests__/applescript-manager-thread-closure.test.js +227 -0
  19. package/src/ide-integration/aider-cli-manager.cjs +850 -0
  20. package/src/ide-integration/applescript-diagnostics.js +0 -0
  21. package/src/ide-integration/applescript-manager.cjs +1088 -0
  22. package/src/ide-integration/applescript-manager.js +2803 -0
  23. package/src/ide-integration/applescript-open-apps.js +0 -0
  24. package/src/ide-integration/applescript-read-response.js +0 -0
  25. package/src/ide-integration/applescript-send-text.js +0 -0
  26. package/src/ide-integration/applescript-thread-closure.js +0 -0
  27. package/src/ide-integration/applescript-utils.js +306 -0
  28. package/src/ide-integration/cdp-manager.cjs +221 -0
  29. package/src/ide-integration/cdp-manager.js +321 -0
  30. package/src/ide-integration/claude-code-cli-manager.cjs +301 -0
  31. package/src/ide-integration/cline-cli-manager.cjs +2252 -0
  32. package/src/ide-integration/continue-cli-manager.js +431 -0
  33. package/src/ide-integration/provider-manager.cjs +354 -0
  34. package/src/ide-integration/quota-detector.cjs +34 -0
  35. package/src/ide-integration/quota-detector.js +349 -0
  36. package/src/ide-integration/windows-automation-manager.js +262 -0
  37. package/src/index.cjs +43 -0
  38. package/src/index.js +17 -0
  39. package/src/llm/direct-llm-manager.cjs +609 -0
  40. package/src/ui/ButtonComponents.js +247 -0
  41. package/src/ui/ChatInterface.js +499 -0
  42. package/src/ui/StateManager.js +259 -0
  43. package/src/ui/StateManager.test.js +0 -0
  44. package/src/utils/audit-logger.cjs +116 -0
  45. package/src/utils/config-helpers.cjs +94 -0
  46. package/src/utils/config-helpers.js +94 -0
  47. package/src/utils/electron-update-checker.js +78 -0
  48. package/src/utils/gcloud-auth.cjs +394 -0
  49. package/src/utils/logger.cjs +193 -0
  50. package/src/utils/logger.js +191 -0
  51. package/src/utils/repo-helpers.cjs +120 -0
  52. package/src/utils/repo-helpers.js +120 -0
  53. package/src/utils/requirement-helpers.js +432 -0
  54. package/src/utils/update-checker.js +167 -0
@@ -0,0 +1,394 @@
1
+ // Google Cloud Authentication Helper
2
+ // Handles gcloud installation, authentication, and API key generation
3
+ const { execSync, spawn } = require('child_process');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const os = require('os');
7
+
8
+ class GCloudAuth {
9
+ constructor() {
10
+ this.logger = console;
11
+ this.configDir = path.join(os.homedir(), '.allnightai');
12
+ this.apiKeyFile = path.join(this.configDir, 'gcloud-api-key.json');
13
+ }
14
+
15
+ /**
16
+ * Check if gcloud CLI is installed
17
+ */
18
+ isGCloudInstalled() {
19
+ try {
20
+ execSync('which gcloud', { stdio: 'pipe' });
21
+ return true;
22
+ } catch {
23
+ return false;
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Install gcloud CLI
29
+ */
30
+ async installGCloud() {
31
+ this.logger.log('Installing Google Cloud CLI...');
32
+
33
+ try {
34
+ const platform = os.platform();
35
+
36
+ if (platform === 'darwin') {
37
+ // macOS - use Homebrew
38
+ this.logger.log('Installing via Homebrew...');
39
+ execSync('brew install --cask google-cloud-sdk', {
40
+ stdio: 'inherit',
41
+ timeout: 300000 // 5 minute timeout
42
+ });
43
+ } else if (platform === 'linux') {
44
+ // Linux - use curl installer
45
+ this.logger.log('Installing via curl...');
46
+ execSync('curl https://sdk.cloud.google.com | bash', {
47
+ stdio: 'inherit',
48
+ shell: true,
49
+ timeout: 300000
50
+ });
51
+ // Source the completion script
52
+ execSync('exec -l $SHELL', { stdio: 'inherit', shell: true });
53
+ } else {
54
+ return {
55
+ success: false,
56
+ error: 'Unsupported platform. Please install gcloud CLI manually: https://cloud.google.com/sdk/docs/install'
57
+ };
58
+ }
59
+
60
+ this.logger.log('Google Cloud CLI installed successfully');
61
+ return { success: true };
62
+ } catch (error) {
63
+ this.logger.error('Failed to install gcloud CLI:', error.message);
64
+ return {
65
+ success: false,
66
+ error: error.message
67
+ };
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Check if user is authenticated with gcloud
73
+ */
74
+ isAuthenticated() {
75
+ try {
76
+ const result = execSync('gcloud auth list --filter=status:ACTIVE --format="value(account)"', {
77
+ encoding: 'utf8',
78
+ stdio: 'pipe'
79
+ });
80
+ return result.trim().length > 0;
81
+ } catch {
82
+ return false;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Authenticate with Google Cloud (opens browser)
88
+ */
89
+ async authenticate() {
90
+ this.logger.log('Opening browser for Google Cloud authentication...');
91
+
92
+ try {
93
+ // This will open the browser automatically
94
+ execSync('gcloud auth login', {
95
+ stdio: 'inherit',
96
+ timeout: 180000 // 3 minute timeout
97
+ });
98
+
99
+ this.logger.log('Successfully authenticated with Google Cloud');
100
+ return { success: true };
101
+ } catch (error) {
102
+ this.logger.error('Failed to authenticate:', error.message);
103
+ return {
104
+ success: false,
105
+ error: error.message
106
+ };
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Get or create project
112
+ */
113
+ async ensureProject() {
114
+ try {
115
+ // Get current project
116
+ let project = execSync('gcloud config get-value project', {
117
+ encoding: 'utf8',
118
+ stdio: 'pipe'
119
+ }).trim();
120
+
121
+ if (!project || project === '(unset)') {
122
+ // Create a new project
123
+ const projectId = `allnightai-${Date.now()}`;
124
+ this.logger.log(`Creating new project: ${projectId}`);
125
+
126
+ execSync(`gcloud projects create ${projectId} --name="AllNightAI"`, {
127
+ stdio: 'inherit'
128
+ });
129
+
130
+ execSync(`gcloud config set project ${projectId}`, {
131
+ stdio: 'inherit'
132
+ });
133
+
134
+ project = projectId;
135
+ }
136
+
137
+ return { success: true, project };
138
+ } catch (error) {
139
+ return {
140
+ success: false,
141
+ error: error.message
142
+ };
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Enable required APIs
148
+ */
149
+ async enableAPIs() {
150
+ try {
151
+ this.logger.log('Enabling Vertex AI API...');
152
+
153
+ execSync('gcloud services enable aiplatform.googleapis.com', {
154
+ stdio: 'inherit',
155
+ timeout: 120000
156
+ });
157
+
158
+ this.logger.log('APIs enabled successfully');
159
+ return { success: true };
160
+ } catch (error) {
161
+ return {
162
+ success: false,
163
+ error: error.message
164
+ };
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Set up gcloud PATH
170
+ */
171
+ setupGCloudPath() {
172
+ const gcloudPaths = [
173
+ '/opt/homebrew/share/google-cloud-sdk/bin',
174
+ '/usr/local/share/google-cloud-sdk/bin',
175
+ path.join(os.homedir(), 'google-cloud-sdk', 'bin')
176
+ ];
177
+
178
+ for (const gcloudPath of gcloudPaths) {
179
+ if (fs.existsSync(gcloudPath)) {
180
+ if (!process.env.PATH.includes(gcloudPath)) {
181
+ process.env.PATH = `${gcloudPath}:${process.env.PATH}`;
182
+ this.logger.log(`Added ${gcloudPath} to PATH`);
183
+ }
184
+ return gcloudPath;
185
+ }
186
+ }
187
+ return null;
188
+ }
189
+
190
+ /**
191
+ * Generate API key using Application Default Credentials
192
+ */
193
+ async generateAPIKey() {
194
+ try {
195
+ this.logger.log('Generating API credentials...');
196
+
197
+ // Ensure gcloud is in PATH
198
+ this.setupGCloudPath();
199
+
200
+ // Get current project
201
+ const project = await this.getCurrentProject();
202
+
203
+ // Display prominent warning about selecting all permissions
204
+ console.log('\n╔══════════════════════════════════════════════════════════════════╗');
205
+ console.log('║ ║');
206
+ console.log('║ ⚠️ IMPORTANT INSTRUCTIONS ⚠️ ║');
207
+ console.log('║ ║');
208
+ console.log('║ Your browser will open for Google Cloud authentication. ║');
209
+ console.log('║ ║');
210
+ console.log('║ ╔════════════════════════════════════════════════════════╗ ║');
211
+ console.log('║ ║ ✓ CLICK "SELECT ALL" TO SELECT ALL PERMISSIONS ║ ║');
212
+ console.log('║ ╚════════════════════════════════════════════════════════╝ ║');
213
+ console.log('║ ║');
214
+ console.log('║ Then click "Continue" or "Allow" to consent. ║');
215
+ console.log('║ ║');
216
+ console.log('║ If you don\'t select all permissions, authentication will fail. ║');
217
+ console.log('║ ║');
218
+ console.log('╚══════════════════════════════════════════════════════════════════╝');
219
+ console.log('\nProject: ' + project);
220
+ console.log('Opening browser in 3 seconds...\n');
221
+
222
+ // Give user time to read the warning
223
+ await new Promise(resolve => setTimeout(resolve, 3000));
224
+
225
+ // Use Application Default Credentials with browser
226
+ execSync(`gcloud auth application-default login --project=${project}`, {
227
+ stdio: 'inherit',
228
+ timeout: 300000, // 5 minutes
229
+ env: { ...process.env, PATH: process.env.PATH }
230
+ });
231
+
232
+ // Get the credentials file location
233
+ const credsPath = path.join(
234
+ os.homedir(),
235
+ '.config',
236
+ 'gcloud',
237
+ 'application_default_credentials.json'
238
+ );
239
+
240
+ if (!fs.existsSync(credsPath)) {
241
+ throw new Error('Credentials file not found');
242
+ }
243
+
244
+ // Copy credentials to our config directory
245
+ fs.mkdirSync(this.configDir, { recursive: true });
246
+ const creds = JSON.parse(fs.readFileSync(credsPath, 'utf8'));
247
+
248
+ // Save API key info
249
+ const apiKeyInfo = {
250
+ type: 'gcloud_application_default',
251
+ credentials_path: credsPath,
252
+ project: creds.quota_project_id || project,
253
+ created_at: new Date().toISOString()
254
+ };
255
+
256
+ fs.writeFileSync(this.apiKeyFile, JSON.stringify(apiKeyInfo, null, 2));
257
+
258
+ this.logger.log('API credentials generated and saved');
259
+ return {
260
+ success: true,
261
+ keyFile: this.apiKeyFile,
262
+ credsPath
263
+ };
264
+ } catch (error) {
265
+ return {
266
+ success: false,
267
+ error: error.message
268
+ };
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Get current project ID
274
+ */
275
+ async getCurrentProject() {
276
+ try {
277
+ const project = execSync('gcloud config get-value project', {
278
+ encoding: 'utf8',
279
+ stdio: 'pipe'
280
+ }).trim();
281
+ return project;
282
+ } catch {
283
+ return null;
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Get saved API key info
289
+ */
290
+ getSavedAPIKey() {
291
+ try {
292
+ if (!fs.existsSync(this.apiKeyFile)) {
293
+ return null;
294
+ }
295
+ return JSON.parse(fs.readFileSync(this.apiKeyFile, 'utf8'));
296
+ } catch {
297
+ return null;
298
+ }
299
+ }
300
+
301
+ /**
302
+ * Check if Application Default Credentials already exist
303
+ */
304
+ hasApplicationDefaultCredentials() {
305
+ const credsPath = path.join(
306
+ os.homedir(),
307
+ '.config',
308
+ 'gcloud',
309
+ 'application_default_credentials.json'
310
+ );
311
+ return fs.existsSync(credsPath);
312
+ }
313
+
314
+ /**
315
+ * Full authentication flow
316
+ */
317
+ async fullAuthFlow() {
318
+ // 1. Check/install gcloud
319
+ if (!this.isGCloudInstalled()) {
320
+ this.logger.log('Google Cloud CLI not found. Installing...');
321
+ const installResult = await this.installGCloud();
322
+ if (!installResult.success) {
323
+ return installResult;
324
+ }
325
+ }
326
+
327
+ // Ensure gcloud is in PATH
328
+ this.setupGCloudPath();
329
+
330
+ // 2. Authenticate
331
+ if (!this.isAuthenticated()) {
332
+ this.logger.log('Not authenticated. Starting authentication...');
333
+ const authResult = await this.authenticate();
334
+ if (!authResult.success) {
335
+ return authResult;
336
+ }
337
+ }
338
+
339
+ // 3. Ensure project
340
+ const projectResult = await this.ensureProject();
341
+ if (!projectResult.success) {
342
+ return projectResult;
343
+ }
344
+
345
+ // 4. Enable APIs
346
+ const apiResult = await this.enableAPIs();
347
+ if (!apiResult.success) {
348
+ return apiResult;
349
+ }
350
+
351
+ // 5. Generate API key (or use existing)
352
+ if (this.hasApplicationDefaultCredentials()) {
353
+ this.logger.log('Application Default Credentials already exist');
354
+
355
+ const credsPath = path.join(
356
+ os.homedir(),
357
+ '.config',
358
+ 'gcloud',
359
+ 'application_default_credentials.json'
360
+ );
361
+
362
+ // Save API key info
363
+ fs.mkdirSync(this.configDir, { recursive: true });
364
+ const apiKeyInfo = {
365
+ type: 'gcloud_application_default',
366
+ credentials_path: credsPath,
367
+ project: projectResult.project,
368
+ created_at: new Date().toISOString()
369
+ };
370
+ fs.writeFileSync(this.apiKeyFile, JSON.stringify(apiKeyInfo, null, 2));
371
+
372
+ return {
373
+ success: true,
374
+ keyFile: this.apiKeyFile,
375
+ credsPath: credsPath,
376
+ project: projectResult.project
377
+ };
378
+ }
379
+
380
+ const keyResult = await this.generateAPIKey();
381
+ if (!keyResult.success) {
382
+ return keyResult;
383
+ }
384
+
385
+ return {
386
+ success: true,
387
+ keyFile: keyResult.keyFile,
388
+ credsPath: keyResult.credsPath,
389
+ project: projectResult.project
390
+ };
391
+ }
392
+ }
393
+
394
+ module.exports = { GCloudAuth };
@@ -0,0 +1,193 @@
1
+ // @vibecodingmachine/core - Logger Utility (CommonJS)
2
+ // Provides consistent logging functionality across the core package
3
+
4
+ /**
5
+ * Logger utility for consistent logging
6
+ * Provides structured logging with different levels and formatting
7
+ */
8
+ class Logger {
9
+ constructor(options = {}) {
10
+ this.level = options.level || 'info';
11
+ this.prefix = options.prefix || 'VibeCodingMachine';
12
+ this.enableTimestamp = options.enableTimestamp !== false;
13
+ this.enableColors = options.enableColors !== false;
14
+
15
+ // Log levels in order of priority
16
+ this.levels = {
17
+ error: 0,
18
+ warn: 1,
19
+ info: 2,
20
+ debug: 3,
21
+ trace: 4
22
+ };
23
+ }
24
+
25
+ /**
26
+ * Get current timestamp
27
+ * @returns {string} Formatted timestamp
28
+ */
29
+ getTimestamp() {
30
+ if (!this.enableTimestamp) return '';
31
+ return new Date().toISOString();
32
+ }
33
+
34
+ /**
35
+ * Format log message
36
+ * @param {string} level - Log level
37
+ * @param {string} message - Log message
38
+ * @param {Array} args - Additional arguments
39
+ * @returns {string} Formatted log message
40
+ */
41
+ formatMessage(level, message, args = []) {
42
+ const timestamp = this.getTimestamp();
43
+ const timestampStr = timestamp ? `[${timestamp}] ` : '';
44
+ const prefixStr = this.prefix ? `[${this.prefix}] ` : '';
45
+ const levelStr = `[${level.toUpperCase()}] `;
46
+
47
+ let formattedMessage = `${timestampStr}${prefixStr}${levelStr}${message}`;
48
+
49
+ if (args.length > 0) {
50
+ formattedMessage += ' ' + args.map(arg =>
51
+ typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
52
+ ).join(' ');
53
+ }
54
+
55
+ return formattedMessage;
56
+ }
57
+
58
+ /**
59
+ * Check if level should be logged
60
+ * @param {string} level - Log level to check
61
+ * @returns {boolean} Whether to log this level
62
+ */
63
+ shouldLog(level) {
64
+ return this.levels[level] <= this.levels[this.level];
65
+ }
66
+
67
+ /**
68
+ * Log error message
69
+ * @param {string} message - Error message
70
+ * @param {...any} args - Additional arguments
71
+ */
72
+ error(message, ...args) {
73
+ if (!this.shouldLog('error')) return;
74
+
75
+ const formattedMessage = this.formatMessage('error', message, args);
76
+ console.error(formattedMessage);
77
+ }
78
+
79
+ /**
80
+ * Log warning message
81
+ * @param {string} message - Warning message
82
+ * @param {...any} args - Additional arguments
83
+ */
84
+ warn(message, ...args) {
85
+ if (!this.shouldLog('warn')) return;
86
+
87
+ const formattedMessage = this.formatMessage('warn', message, args);
88
+ console.warn(formattedMessage);
89
+ }
90
+
91
+ /**
92
+ * Log info message
93
+ * @param {string} message - Info message
94
+ * @param {...any} args - Additional arguments
95
+ */
96
+ info(message, ...args) {
97
+ if (!this.shouldLog('info')) return;
98
+
99
+ const formattedMessage = this.formatMessage('info', message, args);
100
+ console.info(formattedMessage);
101
+ }
102
+
103
+ /**
104
+ * Log debug message
105
+ * @param {string} message - Debug message
106
+ * @param {...any} args - Additional arguments
107
+ */
108
+ debug(message, ...args) {
109
+ if (!this.shouldLog('debug')) return;
110
+
111
+ const formattedMessage = this.formatMessage('debug', message, args);
112
+ console.debug(formattedMessage);
113
+ }
114
+
115
+ /**
116
+ * Log trace message
117
+ * @param {string} message - Trace message
118
+ * @param {...any} args - Additional arguments
119
+ */
120
+ trace(message, ...args) {
121
+ if (!this.shouldLog('trace')) return;
122
+
123
+ const formattedMessage = this.formatMessage('trace', message, args);
124
+ console.trace(formattedMessage);
125
+ }
126
+
127
+ /**
128
+ * Log message (alias for info)
129
+ * @param {string} message - Log message
130
+ * @param {...any} args - Additional arguments
131
+ */
132
+ log(message, ...args) {
133
+ this.info(message, ...args);
134
+ }
135
+
136
+ /**
137
+ * Set log level
138
+ * @param {string} level - New log level
139
+ */
140
+ setLevel(level) {
141
+ if (this.levels.hasOwnProperty(level)) {
142
+ this.level = level;
143
+ } else {
144
+ this.warn(`Invalid log level: ${level}. Using 'info' instead.`);
145
+ this.level = 'info';
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Get current log level
151
+ * @returns {string} Current log level
152
+ */
153
+ getLevel() {
154
+ return this.level;
155
+ }
156
+
157
+ /**
158
+ * Create a child logger with a specific prefix
159
+ * @param {string} childPrefix - Prefix for the child logger
160
+ * @param {Object} options - Additional options
161
+ * @returns {Logger} Child logger instance
162
+ */
163
+ child(childPrefix, options = {}) {
164
+ const fullPrefix = this.prefix ? `${this.prefix}:${childPrefix}` : childPrefix;
165
+ return new Logger({
166
+ level: this.level,
167
+ prefix: fullPrefix,
168
+ enableTimestamp: this.enableTimestamp,
169
+ enableColors: this.enableColors,
170
+ ...options
171
+ });
172
+ }
173
+ }
174
+
175
+ // Create default logger instance
176
+ const logger = new Logger({
177
+ level: process.env.NODE_ENV === 'development' ? 'debug' : 'info',
178
+ prefix: 'VibeCodingMachine',
179
+ enableTimestamp: true,
180
+ enableColors: true
181
+ });
182
+
183
+ // Export console methods for backward compatibility
184
+ const consoleLogger = {
185
+ log: (...args) => logger.log(...args),
186
+ info: (...args) => logger.info(...args),
187
+ warn: (...args) => logger.warn(...args),
188
+ error: (...args) => logger.error(...args),
189
+ debug: (...args) => logger.debug(...args),
190
+ trace: (...args) => logger.trace(...args)
191
+ };
192
+
193
+ module.exports = { logger, Logger, consoleLogger };