vibecodingmachine-core 2025.11.2-9.855 → 2025.12.6-1702
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.
- package/package.json +4 -1
- package/src/auth/shared-auth-storage.js +43 -6
- package/src/ide-integration/applescript-manager.cjs +126 -18
- package/src/ide-integration/applescript-manager.js +172 -84
- package/src/index.cjs +2 -0
- package/src/index.js +2 -0
- package/src/sync/aws-setup.js +445 -0
- package/src/sync/sync-engine.js +388 -0
- package/src/utils/electron-update-checker.js +23 -8
- package/src/utils/requirement-helpers.js +139 -70
- package/src/utils/requirements-parser.js +310 -0
- package/src/utils/update-checker.js +15 -3
- package/src/utils/version-checker.js +6 -5
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS Infrastructure Setup for Vibe Coding Machine Multi-Computer Sync
|
|
3
|
+
*
|
|
4
|
+
* This script sets up:
|
|
5
|
+
* 1. DynamoDB table for requirements storage
|
|
6
|
+
* 2. Cognito User Pool with Google OAuth
|
|
7
|
+
* 3. API Gateway for REST endpoints
|
|
8
|
+
* 4. Lambda functions for sync logic
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
DynamoDBClient,
|
|
13
|
+
CreateTableCommand,
|
|
14
|
+
DescribeTableCommand
|
|
15
|
+
} = require('@aws-sdk/client-dynamodb');
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
CognitoIdentityProviderClient,
|
|
19
|
+
CreateUserPoolCommand,
|
|
20
|
+
CreateUserPoolClientCommand,
|
|
21
|
+
CreateIdentityProviderCommand,
|
|
22
|
+
DescribeUserPoolCommand
|
|
23
|
+
} = require('@aws-sdk/client-cognito-identity-provider');
|
|
24
|
+
|
|
25
|
+
const region = process.env.AWS_REGION || 'us-east-1';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Create DynamoDB table for requirements sync
|
|
29
|
+
*/
|
|
30
|
+
async function createDynamoDBTable() {
|
|
31
|
+
const client = new DynamoDBClient({ region });
|
|
32
|
+
const tableName = 'vibecodingmachine-requirements';
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
// Check if table already exists
|
|
36
|
+
try {
|
|
37
|
+
const describeCommand = new DescribeTableCommand({ TableName: tableName });
|
|
38
|
+
await client.send(describeCommand);
|
|
39
|
+
console.log(`✓ DynamoDB table '${tableName}' already exists`);
|
|
40
|
+
return { tableName, status: 'exists' };
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (error.name !== 'ResourceNotFoundException') {
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Create table
|
|
48
|
+
const command = new CreateTableCommand({
|
|
49
|
+
TableName: tableName,
|
|
50
|
+
KeySchema: [
|
|
51
|
+
{ AttributeName: 'computerId', KeyType: 'HASH' }, // Partition key
|
|
52
|
+
{ AttributeName: 'timestamp', KeyType: 'RANGE' } // Sort key
|
|
53
|
+
],
|
|
54
|
+
AttributeDefinitions: [
|
|
55
|
+
{ AttributeName: 'computerId', AttributeType: 'S' },
|
|
56
|
+
{ AttributeName: 'timestamp', AttributeType: 'N' },
|
|
57
|
+
{ AttributeName: 'requirementId', AttributeType: 'S' }
|
|
58
|
+
],
|
|
59
|
+
GlobalSecondaryIndexes: [
|
|
60
|
+
{
|
|
61
|
+
IndexName: 'requirementId-index',
|
|
62
|
+
KeySchema: [
|
|
63
|
+
{ AttributeName: 'requirementId', KeyType: 'HASH' }
|
|
64
|
+
],
|
|
65
|
+
Projection: { ProjectionType: 'ALL' }
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
IndexName: 'timestamp-index',
|
|
69
|
+
KeySchema: [
|
|
70
|
+
{ AttributeName: 'timestamp', KeyType: 'HASH' }
|
|
71
|
+
],
|
|
72
|
+
Projection: { ProjectionType: 'ALL' }
|
|
73
|
+
}
|
|
74
|
+
],
|
|
75
|
+
BillingMode: 'PAY_PER_REQUEST', // On-demand pricing (no ProvisionedThroughput needed)
|
|
76
|
+
StreamSpecification: {
|
|
77
|
+
StreamEnabled: true,
|
|
78
|
+
StreamViewType: 'NEW_AND_OLD_IMAGES'
|
|
79
|
+
},
|
|
80
|
+
TimeToLiveSpecification: {
|
|
81
|
+
Enabled: true,
|
|
82
|
+
AttributeName: 'ttl'
|
|
83
|
+
},
|
|
84
|
+
Tags: [
|
|
85
|
+
{ Key: 'Application', Value: 'VibeCodingMachine' },
|
|
86
|
+
{ Key: 'Purpose', Value: 'RequirementsSync' }
|
|
87
|
+
]
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const response = await client.send(command);
|
|
91
|
+
console.log(`✓ Created DynamoDB table '${tableName}'`);
|
|
92
|
+
console.log(` ARN: ${response.TableDescription.TableArn}`);
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
tableName,
|
|
96
|
+
status: 'created',
|
|
97
|
+
arn: response.TableDescription.TableArn
|
|
98
|
+
};
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error(`✗ Failed to create DynamoDB table:`, error.message);
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Create or update Cognito User Pool with Google OAuth
|
|
107
|
+
*/
|
|
108
|
+
async function setupCognitoWithGoogle() {
|
|
109
|
+
const client = new CognitoIdentityProviderClient({ region });
|
|
110
|
+
|
|
111
|
+
// Use existing user pool if specified
|
|
112
|
+
const existingPoolId = process.env.COGNITO_USER_POOL_ID;
|
|
113
|
+
|
|
114
|
+
if (existingPoolId) {
|
|
115
|
+
console.log(`✓ Using existing Cognito User Pool: ${existingPoolId}`);
|
|
116
|
+
|
|
117
|
+
// Add Google OAuth provider if not already configured
|
|
118
|
+
try {
|
|
119
|
+
const googleClientId = process.env.GOOGLE_CLIENT_ID;
|
|
120
|
+
const googleClientSecret = process.env.GOOGLE_CLIENT_SECRET;
|
|
121
|
+
|
|
122
|
+
if (!googleClientId || !googleClientSecret) {
|
|
123
|
+
console.log('⚠ Google OAuth credentials not provided. Skipping Google provider setup.');
|
|
124
|
+
console.log(' Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET environment variables.');
|
|
125
|
+
return { userPoolId: existingPoolId, status: 'existing' };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const providerCommand = new CreateIdentityProviderCommand({
|
|
129
|
+
UserPoolId: existingPoolId,
|
|
130
|
+
ProviderName: 'Google',
|
|
131
|
+
ProviderType: 'Google',
|
|
132
|
+
ProviderDetails: {
|
|
133
|
+
client_id: googleClientId,
|
|
134
|
+
client_secret: googleClientSecret,
|
|
135
|
+
authorize_scopes: 'openid email profile'
|
|
136
|
+
},
|
|
137
|
+
AttributeMapping: {
|
|
138
|
+
email: 'email',
|
|
139
|
+
name: 'name',
|
|
140
|
+
picture: 'picture',
|
|
141
|
+
username: 'sub'
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
await client.send(providerCommand);
|
|
146
|
+
console.log('✓ Added Google OAuth provider to Cognito User Pool');
|
|
147
|
+
} catch (error) {
|
|
148
|
+
if (error.name === 'DuplicateProviderException') {
|
|
149
|
+
console.log('✓ Google OAuth provider already configured');
|
|
150
|
+
} else {
|
|
151
|
+
console.error('⚠ Failed to add Google provider:', error.message);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return { userPoolId: existingPoolId, status: 'existing' };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Create new user pool
|
|
159
|
+
console.log('Creating new Cognito User Pool...');
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
const poolCommand = new CreateUserPoolCommand({
|
|
163
|
+
PoolName: 'vibecodingmachine-users',
|
|
164
|
+
Policies: {
|
|
165
|
+
PasswordPolicy: {
|
|
166
|
+
MinimumLength: 8,
|
|
167
|
+
RequireUppercase: true,
|
|
168
|
+
RequireLowercase: true,
|
|
169
|
+
RequireNumbers: true,
|
|
170
|
+
RequireSymbols: false
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
AutoVerifiedAttributes: ['email'],
|
|
174
|
+
UsernameAttributes: ['email'],
|
|
175
|
+
Schema: [
|
|
176
|
+
{
|
|
177
|
+
Name: 'email',
|
|
178
|
+
AttributeDataType: 'String',
|
|
179
|
+
Required: true,
|
|
180
|
+
Mutable: true
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
Name: 'name',
|
|
184
|
+
AttributeDataType: 'String',
|
|
185
|
+
Required: false,
|
|
186
|
+
Mutable: true
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
UserPoolTags: {
|
|
190
|
+
Application: 'VibeCodingMachine',
|
|
191
|
+
Purpose: 'Authentication'
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const poolResponse = await client.send(poolCommand);
|
|
196
|
+
const userPoolId = poolResponse.UserPool.Id;
|
|
197
|
+
|
|
198
|
+
console.log(`✓ Created Cognito User Pool: ${userPoolId}`);
|
|
199
|
+
|
|
200
|
+
// Add Google OAuth provider first (if credentials provided)
|
|
201
|
+
const googleClientId = process.env.GOOGLE_CLIENT_ID;
|
|
202
|
+
const googleClientSecret = process.env.GOOGLE_CLIENT_SECRET;
|
|
203
|
+
|
|
204
|
+
let supportedProviders = ['COGNITO'];
|
|
205
|
+
|
|
206
|
+
if (googleClientId && googleClientSecret) {
|
|
207
|
+
try {
|
|
208
|
+
const providerCommand = new CreateIdentityProviderCommand({
|
|
209
|
+
UserPoolId: userPoolId,
|
|
210
|
+
ProviderName: 'Google',
|
|
211
|
+
ProviderType: 'Google',
|
|
212
|
+
ProviderDetails: {
|
|
213
|
+
client_id: googleClientId,
|
|
214
|
+
client_secret: googleClientSecret,
|
|
215
|
+
authorize_scopes: 'openid email profile'
|
|
216
|
+
},
|
|
217
|
+
AttributeMapping: {
|
|
218
|
+
email: 'email',
|
|
219
|
+
name: 'name',
|
|
220
|
+
picture: 'picture',
|
|
221
|
+
username: 'sub'
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
await client.send(providerCommand);
|
|
226
|
+
console.log('✓ Added Google OAuth provider to Cognito User Pool');
|
|
227
|
+
supportedProviders.push('Google');
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.log('⚠ Could not add Google provider:', error.message);
|
|
230
|
+
console.log(' You can add it later via AWS Console');
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
233
|
+
console.log('⚠ Google OAuth credentials not provided');
|
|
234
|
+
console.log(' Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET to enable Google login');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Create app client
|
|
238
|
+
const clientCommand = new CreateUserPoolClientCommand({
|
|
239
|
+
UserPoolId: userPoolId,
|
|
240
|
+
ClientName: 'vibecodingmachine-client',
|
|
241
|
+
GenerateSecret: false, // Public client for PKCE
|
|
242
|
+
RefreshTokenValidity: 30,
|
|
243
|
+
AccessTokenValidity: 1,
|
|
244
|
+
IdTokenValidity: 1,
|
|
245
|
+
TokenValidityUnits: {
|
|
246
|
+
RefreshToken: 'days',
|
|
247
|
+
AccessToken: 'hours',
|
|
248
|
+
IdToken: 'hours'
|
|
249
|
+
},
|
|
250
|
+
ExplicitAuthFlows: [
|
|
251
|
+
'ALLOW_REFRESH_TOKEN_AUTH',
|
|
252
|
+
'ALLOW_USER_SRP_AUTH'
|
|
253
|
+
],
|
|
254
|
+
AllowedOAuthFlows: ['code'],
|
|
255
|
+
AllowedOAuthScopes: ['openid', 'email', 'profile'],
|
|
256
|
+
AllowedOAuthFlowsUserPoolClient: true,
|
|
257
|
+
SupportedIdentityProviders: supportedProviders,
|
|
258
|
+
CallbackURLs: [
|
|
259
|
+
'http://localhost:3000/callback',
|
|
260
|
+
'vibecodingmachine://callback'
|
|
261
|
+
],
|
|
262
|
+
LogoutURLs: [
|
|
263
|
+
'http://localhost:3000/logout',
|
|
264
|
+
'vibecodingmachine://logout'
|
|
265
|
+
]
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
const clientResponse = await client.send(clientCommand);
|
|
269
|
+
const appClientId = clientResponse.UserPoolClient.ClientId;
|
|
270
|
+
|
|
271
|
+
console.log(`✓ Created Cognito App Client: ${appClientId}`);
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
userPoolId,
|
|
275
|
+
appClientId,
|
|
276
|
+
status: 'created'
|
|
277
|
+
};
|
|
278
|
+
} catch (error) {
|
|
279
|
+
console.error('✗ Failed to create Cognito User Pool:', error.message);
|
|
280
|
+
throw error;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Create computers DynamoDB table
|
|
286
|
+
*/
|
|
287
|
+
async function createComputersTable() {
|
|
288
|
+
const client = new DynamoDBClient({ region });
|
|
289
|
+
const tableName = 'vibecodingmachine-computers';
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
// Check if table already exists
|
|
293
|
+
try {
|
|
294
|
+
const describeCommand = new DescribeTableCommand({ TableName: tableName });
|
|
295
|
+
await client.send(describeCommand);
|
|
296
|
+
console.log(`✓ Computers table '${tableName}' already exists`);
|
|
297
|
+
return { tableName, status: 'exists' };
|
|
298
|
+
} catch (error) {
|
|
299
|
+
if (error.name !== 'ResourceNotFoundException') {
|
|
300
|
+
throw error;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Create table
|
|
305
|
+
const command = new CreateTableCommand({
|
|
306
|
+
TableName: tableName,
|
|
307
|
+
KeySchema: [
|
|
308
|
+
{ AttributeName: 'computerId', KeyType: 'HASH' } // Partition key
|
|
309
|
+
],
|
|
310
|
+
AttributeDefinitions: [
|
|
311
|
+
{ AttributeName: 'computerId', AttributeType: 'S' }
|
|
312
|
+
],
|
|
313
|
+
BillingMode: 'PAY_PER_REQUEST',
|
|
314
|
+
Tags: [
|
|
315
|
+
{ Key: 'Application', Value: 'VibeCodingMachine' },
|
|
316
|
+
{ Key: 'Purpose', Value: 'ComputerRegistry' }
|
|
317
|
+
]
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
const response = await client.send(command);
|
|
321
|
+
console.log(`✓ Created computers table '${tableName}'`);
|
|
322
|
+
|
|
323
|
+
return {
|
|
324
|
+
tableName,
|
|
325
|
+
status: 'created',
|
|
326
|
+
arn: response.TableDescription.TableArn
|
|
327
|
+
};
|
|
328
|
+
} catch (error) {
|
|
329
|
+
console.error(`✗ Failed to create computers table:`, error.message);
|
|
330
|
+
throw error;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Create beta customers DynamoDB table
|
|
336
|
+
*/
|
|
337
|
+
async function createBetaCustomersTable() {
|
|
338
|
+
const client = new DynamoDBClient({ region });
|
|
339
|
+
const tableName = 'vibecodingmachine-beta-customers';
|
|
340
|
+
|
|
341
|
+
try {
|
|
342
|
+
// Check if table already exists
|
|
343
|
+
try {
|
|
344
|
+
const describeCommand = new DescribeTableCommand({ TableName: tableName });
|
|
345
|
+
await client.send(describeCommand);
|
|
346
|
+
console.log(`✓ Beta customers table '${tableName}' already exists`);
|
|
347
|
+
return { tableName, status: 'exists' };
|
|
348
|
+
} catch (error) {
|
|
349
|
+
if (error.name !== 'ResourceNotFoundException') {
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Create table
|
|
355
|
+
const command = new CreateTableCommand({
|
|
356
|
+
TableName: tableName,
|
|
357
|
+
KeySchema: [
|
|
358
|
+
{ AttributeName: 'email', KeyType: 'HASH' } // Partition key
|
|
359
|
+
],
|
|
360
|
+
AttributeDefinitions: [
|
|
361
|
+
{ AttributeName: 'email', AttributeType: 'S' }
|
|
362
|
+
],
|
|
363
|
+
BillingMode: 'PAY_PER_REQUEST',
|
|
364
|
+
Tags: [
|
|
365
|
+
{ Key: 'Application', Value: 'VibeCodingMachine' },
|
|
366
|
+
{ Key: 'Purpose', Value: 'BetaAccess' }
|
|
367
|
+
]
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
const response = await client.send(command);
|
|
371
|
+
console.log(`✓ Created beta customers table '${tableName}'`);
|
|
372
|
+
|
|
373
|
+
return {
|
|
374
|
+
tableName,
|
|
375
|
+
status: 'created',
|
|
376
|
+
arn: response.TableDescription.TableArn
|
|
377
|
+
};
|
|
378
|
+
} catch (error) {
|
|
379
|
+
console.error(`✗ Failed to create beta customers table:`, error.message);
|
|
380
|
+
throw error;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Main setup function
|
|
386
|
+
*/
|
|
387
|
+
async function setup() {
|
|
388
|
+
console.log('🚀 Setting up AWS infrastructure for Vibe Coding Machine\n');
|
|
389
|
+
|
|
390
|
+
try {
|
|
391
|
+
// 1. Create DynamoDB tables
|
|
392
|
+
console.log('1. Setting up DynamoDB tables...');
|
|
393
|
+
const requirementsTable = await createDynamoDBTable();
|
|
394
|
+
const computersTable = await createComputersTable();
|
|
395
|
+
const betaTable = await createBetaCustomersTable();
|
|
396
|
+
console.log('');
|
|
397
|
+
|
|
398
|
+
// 2. Setup Cognito with Google OAuth
|
|
399
|
+
console.log('2. Setting up Cognito with Google OAuth...');
|
|
400
|
+
const cognito = await setupCognitoWithGoogle();
|
|
401
|
+
console.log('');
|
|
402
|
+
|
|
403
|
+
// 3. Output configuration
|
|
404
|
+
console.log('✅ Setup complete!\n');
|
|
405
|
+
console.log('Configuration:');
|
|
406
|
+
console.log('─────────────────────────────────────────');
|
|
407
|
+
console.log(`AWS_REGION=${region}`);
|
|
408
|
+
console.log(`DYNAMODB_TABLE_NAME=${requirementsTable.tableName}`);
|
|
409
|
+
console.log(`DYNAMODB_COMPUTERS_TABLE_NAME=${computersTable.tableName}`);
|
|
410
|
+
console.log(`DYNAMODB_BETA_TABLE_NAME=${betaTable.tableName}`);
|
|
411
|
+
if (cognito.userPoolId) {
|
|
412
|
+
console.log(`COGNITO_USER_POOL_ID=${cognito.userPoolId}`);
|
|
413
|
+
}
|
|
414
|
+
if (cognito.appClientId) {
|
|
415
|
+
console.log(`COGNITO_APP_CLIENT_ID=${cognito.appClientId}`);
|
|
416
|
+
}
|
|
417
|
+
console.log('─────────────────────────────────────────\n');
|
|
418
|
+
|
|
419
|
+
console.log('Next steps:');
|
|
420
|
+
console.log('1. Add the above configuration to your .env file');
|
|
421
|
+
console.log('2. Set up Google OAuth credentials in Google Cloud Console');
|
|
422
|
+
console.log('3. Configure Cognito domain for OAuth flows');
|
|
423
|
+
console.log('4. Deploy Lambda functions for sync logic');
|
|
424
|
+
console.log('5. Set up API Gateway endpoints\n');
|
|
425
|
+
|
|
426
|
+
return {
|
|
427
|
+
requirementsTable,
|
|
428
|
+
computersTable,
|
|
429
|
+
betaTable,
|
|
430
|
+
cognito
|
|
431
|
+
};
|
|
432
|
+
} catch (error) {
|
|
433
|
+
console.error('\n❌ Setup failed:', error.message);
|
|
434
|
+
throw error;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Run setup if called directly
|
|
439
|
+
if (require.main === module) {
|
|
440
|
+
setup()
|
|
441
|
+
.then(() => process.exit(0))
|
|
442
|
+
.catch(() => process.exit(1));
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
module.exports = { setup, createDynamoDBTable, createComputersTable, setupCognitoWithGoogle, createBetaCustomersTable };
|