codebakers 1.0.45 → 2.0.1

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 (82) hide show
  1. package/README.md +275 -60
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.js +4260 -0
  4. package/install.bat +9 -0
  5. package/package.json +71 -115
  6. package/src/channels/discord.ts +5 -0
  7. package/src/channels/slack.ts +5 -0
  8. package/src/channels/sms.ts +4 -0
  9. package/src/channels/telegram.ts +5 -0
  10. package/src/channels/whatsapp.ts +7 -0
  11. package/src/commands/check.ts +365 -0
  12. package/src/commands/code.ts +684 -0
  13. package/src/commands/connect.ts +12 -0
  14. package/src/commands/deploy.ts +414 -0
  15. package/src/commands/design.ts +298 -0
  16. package/src/commands/fix.ts +20 -0
  17. package/src/commands/gateway.ts +604 -0
  18. package/src/commands/generate.ts +178 -0
  19. package/src/commands/init.ts +574 -0
  20. package/src/commands/learn.ts +36 -0
  21. package/src/commands/security.ts +102 -0
  22. package/src/commands/setup.ts +448 -0
  23. package/src/commands/status.ts +56 -0
  24. package/src/index.ts +278 -0
  25. package/src/patterns/loader.ts +337 -0
  26. package/src/services/github.ts +61 -0
  27. package/src/services/supabase.ts +147 -0
  28. package/src/services/vercel.ts +61 -0
  29. package/src/utils/claude-md.ts +287 -0
  30. package/src/utils/config.ts +282 -0
  31. package/src/utils/updates.ts +27 -0
  32. package/tsconfig.json +17 -10
  33. package/.vscodeignore +0 -18
  34. package/LICENSE +0 -21
  35. package/codebakers-1.0.0.vsix +0 -0
  36. package/codebakers-1.0.10.vsix +0 -0
  37. package/codebakers-1.0.11.vsix +0 -0
  38. package/codebakers-1.0.12.vsix +0 -0
  39. package/codebakers-1.0.13.vsix +0 -0
  40. package/codebakers-1.0.14.vsix +0 -0
  41. package/codebakers-1.0.15.vsix +0 -0
  42. package/codebakers-1.0.16.vsix +0 -0
  43. package/codebakers-1.0.17.vsix +0 -0
  44. package/codebakers-1.0.18.vsix +0 -0
  45. package/codebakers-1.0.19.vsix +0 -0
  46. package/codebakers-1.0.20.vsix +0 -0
  47. package/codebakers-1.0.21.vsix +0 -0
  48. package/codebakers-1.0.22.vsix +0 -0
  49. package/codebakers-1.0.23.vsix +0 -0
  50. package/codebakers-1.0.24.vsix +0 -0
  51. package/codebakers-1.0.25.vsix +0 -0
  52. package/codebakers-1.0.26.vsix +0 -0
  53. package/codebakers-1.0.27.vsix +0 -0
  54. package/codebakers-1.0.28.vsix +0 -0
  55. package/codebakers-1.0.29.vsix +0 -0
  56. package/codebakers-1.0.30.vsix +0 -0
  57. package/codebakers-1.0.31.vsix +0 -0
  58. package/codebakers-1.0.32.vsix +0 -0
  59. package/codebakers-1.0.35.vsix +0 -0
  60. package/codebakers-1.0.36.vsix +0 -0
  61. package/codebakers-1.0.37.vsix +0 -0
  62. package/codebakers-1.0.38.vsix +0 -0
  63. package/codebakers-1.0.39.vsix +0 -0
  64. package/codebakers-1.0.40.vsix +0 -0
  65. package/codebakers-1.0.41.vsix +0 -0
  66. package/codebakers-1.0.42.vsix +0 -0
  67. package/codebakers-1.0.43.vsix +0 -0
  68. package/codebakers-1.0.44.vsix +0 -0
  69. package/codebakers-1.0.45.vsix +0 -0
  70. package/dist/extension.js +0 -1394
  71. package/esbuild.js +0 -63
  72. package/media/icon.png +0 -0
  73. package/media/icon.svg +0 -7
  74. package/nul +0 -1
  75. package/preview.html +0 -547
  76. package/src/ChatPanelProvider.ts +0 -1815
  77. package/src/ChatViewProvider.ts +0 -749
  78. package/src/CodeBakersClient.ts +0 -1146
  79. package/src/CodeValidator.ts +0 -645
  80. package/src/FileOperations.ts +0 -410
  81. package/src/ProjectContext.ts +0 -526
  82. package/src/extension.ts +0 -332
@@ -0,0 +1,448 @@
1
+ import * as p from '@clack/prompts';
2
+ import chalk from 'chalk';
3
+ import open from 'open';
4
+ import { Config } from '../utils/config.js';
5
+
6
+ export async function setupCommand(): Promise<void> {
7
+ const config = new Config();
8
+
9
+ p.intro(chalk.bgCyan.black(' CodeBakers Setup '));
10
+
11
+ // Check if already configured
12
+ if (config.isConfigured()) {
13
+ const action = await p.select({
14
+ message: 'CodeBakers is already configured. What do you want to do?',
15
+ options: [
16
+ { value: 'view', label: '👀 View connected services' },
17
+ { value: 'add', label: '➕ Add another service' },
18
+ { value: 'update', label: '🔄 Update credentials' },
19
+ { value: 'reset', label: '🗑️ Reset all configuration' },
20
+ { value: 'back', label: '← Back' },
21
+ ],
22
+ });
23
+
24
+ if (p.isCancel(action) || action === 'back') {
25
+ return;
26
+ }
27
+
28
+ if (action === 'view') {
29
+ showConnectedServices(config);
30
+ return;
31
+ }
32
+
33
+ if (action === 'reset') {
34
+ const confirm = await p.confirm({
35
+ message: 'Are you sure? This will remove all credentials and settings.',
36
+ });
37
+ if (confirm) {
38
+ // Reset config - in real implementation would clear the config
39
+ p.outro(chalk.yellow('Configuration reset. Run `codebakers setup` again.'));
40
+ }
41
+ return;
42
+ }
43
+
44
+ if (action === 'add') {
45
+ await addService(config);
46
+ return;
47
+ }
48
+ }
49
+
50
+ // First-time setup
51
+ p.note(
52
+ `Let's connect your accounts. This only takes a few minutes.
53
+
54
+ ${chalk.dim('Your credentials are stored locally in ~/.codebakers/')}
55
+ ${chalk.dim('and are never sent to our servers.')}`,
56
+ 'Welcome to CodeBakers!'
57
+ );
58
+
59
+ // Required services
60
+ const requiredServices = [
61
+ { name: 'GitHub', key: 'github', required: true },
62
+ { name: 'Vercel', key: 'vercel', required: true },
63
+ { name: 'Supabase', key: 'supabase', required: true },
64
+ { name: 'Anthropic (Claude)', key: 'anthropic', required: true },
65
+ ];
66
+
67
+ // Optional services
68
+ const optionalServices = [
69
+ { name: 'OpenAI', key: 'openai' },
70
+ { name: 'Stripe', key: 'stripe' },
71
+ { name: 'Twilio', key: 'twilio' },
72
+ { name: 'VAPI', key: 'vapi' },
73
+ { name: 'Resend', key: 'resend' },
74
+ { name: 'ElevenLabs', key: 'elevenLabs' },
75
+ { name: 'Microsoft Graph', key: 'microsoft' },
76
+ { name: 'Google APIs', key: 'google' },
77
+ ];
78
+
79
+ p.log.step('Connecting required services...');
80
+
81
+ // Connect required services
82
+ for (const service of requiredServices) {
83
+ await connectService(config, service.key, service.name, true);
84
+ }
85
+
86
+ // Ask about optional services
87
+ const addOptional = await p.confirm({
88
+ message: 'Do you want to connect optional services? (Stripe, Twilio, etc.)',
89
+ initialValue: false,
90
+ });
91
+
92
+ if (addOptional && !p.isCancel(addOptional)) {
93
+ const selected = await p.multiselect({
94
+ message: 'Select services to connect:',
95
+ options: optionalServices.map(s => ({
96
+ value: s.key,
97
+ label: s.name,
98
+ })),
99
+ required: false,
100
+ });
101
+
102
+ if (!p.isCancel(selected)) {
103
+ for (const serviceKey of selected) {
104
+ const service = optionalServices.find(s => s.key === serviceKey);
105
+ if (service) {
106
+ await connectService(config, service.key, service.name, false);
107
+ }
108
+ }
109
+ }
110
+ }
111
+
112
+ // Copy patterns
113
+ p.log.step('Installing CodeBakers patterns...');
114
+ await installPatterns(config);
115
+
116
+ p.outro(chalk.green('✓ Setup complete! Run `codebakers init` to create your first project.'));
117
+ }
118
+
119
+ async function connectService(
120
+ config: Config,
121
+ serviceKey: string,
122
+ serviceName: string,
123
+ required: boolean
124
+ ): Promise<boolean> {
125
+ const spinner = p.spinner();
126
+
127
+ switch (serviceKey) {
128
+ case 'github': {
129
+ p.log.info(`${chalk.bold('GitHub')} - Opens browser for OAuth authorization`);
130
+
131
+ const proceed = await p.confirm({
132
+ message: 'Open browser to authorize GitHub?',
133
+ initialValue: true,
134
+ });
135
+
136
+ if (p.isCancel(proceed) || !proceed) {
137
+ if (required) {
138
+ p.log.warn('GitHub is required. Skipping for now.');
139
+ }
140
+ return false;
141
+ }
142
+
143
+ // In real implementation, this would:
144
+ // 1. Start local server for OAuth callback
145
+ // 2. Open GitHub OAuth URL
146
+ // 3. Handle callback and save token
147
+ p.log.info(chalk.dim('Opening browser...'));
148
+ await open('https://github.com/login/oauth/authorize?client_id=YOUR_CLIENT_ID&scope=repo,user');
149
+
150
+ const token = await p.text({
151
+ message: 'Paste your GitHub token (or press Enter if OAuth completed):',
152
+ placeholder: 'ghp_...',
153
+ });
154
+
155
+ if (!p.isCancel(token) && token) {
156
+ config.setCredentials('github', { token: token as string });
157
+ p.log.success('GitHub connected!');
158
+ return true;
159
+ }
160
+ break;
161
+ }
162
+
163
+ case 'vercel': {
164
+ p.log.info(`${chalk.bold('Vercel')} - Opens browser for OAuth authorization`);
165
+
166
+ const proceed = await p.confirm({
167
+ message: 'Open browser to authorize Vercel?',
168
+ initialValue: true,
169
+ });
170
+
171
+ if (p.isCancel(proceed) || !proceed) {
172
+ if (required) {
173
+ p.log.warn('Vercel is required. Skipping for now.');
174
+ }
175
+ return false;
176
+ }
177
+
178
+ p.log.info(chalk.dim('Opening browser...'));
179
+ await open('https://vercel.com/account/tokens');
180
+
181
+ const token = await p.text({
182
+ message: 'Paste your Vercel token:',
183
+ placeholder: 'vercel_...',
184
+ });
185
+
186
+ if (!p.isCancel(token) && token) {
187
+ config.setCredentials('vercel', { token: token as string });
188
+ p.log.success('Vercel connected!');
189
+ return true;
190
+ }
191
+ break;
192
+ }
193
+
194
+ case 'supabase': {
195
+ p.log.info(`${chalk.bold('Supabase')} - Opens browser for OAuth authorization`);
196
+
197
+ const proceed = await p.confirm({
198
+ message: 'Open browser to authorize Supabase?',
199
+ initialValue: true,
200
+ });
201
+
202
+ if (p.isCancel(proceed) || !proceed) {
203
+ if (required) {
204
+ p.log.warn('Supabase is required. Skipping for now.');
205
+ }
206
+ return false;
207
+ }
208
+
209
+ p.log.info(chalk.dim('Opening browser...'));
210
+ await open('https://supabase.com/dashboard/account/tokens');
211
+
212
+ const token = await p.text({
213
+ message: 'Paste your Supabase access token:',
214
+ placeholder: 'sbp_...',
215
+ });
216
+
217
+ if (!p.isCancel(token) && token) {
218
+ config.setCredentials('supabase', { accessToken: token as string });
219
+ p.log.success('Supabase connected!');
220
+ return true;
221
+ }
222
+ break;
223
+ }
224
+
225
+ case 'anthropic': {
226
+ p.log.info(`${chalk.bold('Anthropic (Claude)')} - Powers the AI coding agent`);
227
+
228
+ const openBrowser = await p.confirm({
229
+ message: 'Open browser to get API key?',
230
+ initialValue: true,
231
+ });
232
+
233
+ if (openBrowser && !p.isCancel(openBrowser)) {
234
+ await open('https://console.anthropic.com/settings/keys');
235
+ }
236
+
237
+ const apiKey = await p.text({
238
+ message: 'Paste your Anthropic API key:',
239
+ placeholder: 'sk-ant-...',
240
+ validate: (value) => {
241
+ if (!value && required) return 'API key is required';
242
+ if (value && !value.startsWith('sk-ant-')) return 'Invalid API key format';
243
+ return undefined;
244
+ },
245
+ });
246
+
247
+ if (!p.isCancel(apiKey) && apiKey) {
248
+ config.setCredentials('anthropic', { apiKey: apiKey as string });
249
+ p.log.success('Anthropic connected!');
250
+ return true;
251
+ }
252
+ break;
253
+ }
254
+
255
+ case 'openai': {
256
+ const openBrowser = await p.confirm({
257
+ message: 'Open browser to get OpenAI API key?',
258
+ initialValue: true,
259
+ });
260
+
261
+ if (openBrowser && !p.isCancel(openBrowser)) {
262
+ await open('https://platform.openai.com/api-keys');
263
+ }
264
+
265
+ const apiKey = await p.text({
266
+ message: 'Paste your OpenAI API key:',
267
+ placeholder: 'sk-...',
268
+ });
269
+
270
+ if (!p.isCancel(apiKey) && apiKey) {
271
+ config.setCredentials('openai', { apiKey: apiKey as string });
272
+ p.log.success('OpenAI connected!');
273
+ return true;
274
+ }
275
+ break;
276
+ }
277
+
278
+ case 'stripe': {
279
+ const openBrowser = await p.confirm({
280
+ message: 'Open browser to get Stripe API keys?',
281
+ initialValue: true,
282
+ });
283
+
284
+ if (openBrowser && !p.isCancel(openBrowser)) {
285
+ await open('https://dashboard.stripe.com/apikeys');
286
+ }
287
+
288
+ const secretKey = await p.text({
289
+ message: 'Paste your Stripe secret key:',
290
+ placeholder: 'sk_live_... or sk_test_...',
291
+ });
292
+
293
+ if (!p.isCancel(secretKey) && secretKey) {
294
+ config.setCredentials('stripe', { secretKey: secretKey as string });
295
+ p.log.success('Stripe connected!');
296
+ return true;
297
+ }
298
+ break;
299
+ }
300
+
301
+ case 'twilio': {
302
+ const openBrowser = await p.confirm({
303
+ message: 'Open browser to get Twilio credentials?',
304
+ initialValue: true,
305
+ });
306
+
307
+ if (openBrowser && !p.isCancel(openBrowser)) {
308
+ await open('https://console.twilio.com/');
309
+ }
310
+
311
+ const accountSid = await p.text({
312
+ message: 'Paste your Twilio Account SID:',
313
+ placeholder: 'AC...',
314
+ });
315
+
316
+ const authToken = await p.text({
317
+ message: 'Paste your Twilio Auth Token:',
318
+ placeholder: '...',
319
+ });
320
+
321
+ if (!p.isCancel(accountSid) && !p.isCancel(authToken) && accountSid && authToken) {
322
+ config.setCredentials('twilio', {
323
+ accountSid: accountSid as string,
324
+ authToken: authToken as string
325
+ });
326
+ p.log.success('Twilio connected!');
327
+ return true;
328
+ }
329
+ break;
330
+ }
331
+
332
+ case 'vapi': {
333
+ const openBrowser = await p.confirm({
334
+ message: 'Open browser to get VAPI API key?',
335
+ initialValue: true,
336
+ });
337
+
338
+ if (openBrowser && !p.isCancel(openBrowser)) {
339
+ await open('https://dashboard.vapi.ai/');
340
+ }
341
+
342
+ const apiKey = await p.text({
343
+ message: 'Paste your VAPI API key:',
344
+ placeholder: '...',
345
+ });
346
+
347
+ if (!p.isCancel(apiKey) && apiKey) {
348
+ config.setCredentials('vapi', { apiKey: apiKey as string });
349
+ p.log.success('VAPI connected!');
350
+ return true;
351
+ }
352
+ break;
353
+ }
354
+
355
+ case 'resend': {
356
+ const openBrowser = await p.confirm({
357
+ message: 'Open browser to get Resend API key?',
358
+ initialValue: true,
359
+ });
360
+
361
+ if (openBrowser && !p.isCancel(openBrowser)) {
362
+ await open('https://resend.com/api-keys');
363
+ }
364
+
365
+ const apiKey = await p.text({
366
+ message: 'Paste your Resend API key:',
367
+ placeholder: 're_...',
368
+ });
369
+
370
+ if (!p.isCancel(apiKey) && apiKey) {
371
+ config.setCredentials('resend', { apiKey: apiKey as string });
372
+ p.log.success('Resend connected!');
373
+ return true;
374
+ }
375
+ break;
376
+ }
377
+
378
+ default:
379
+ p.log.warn(`Service ${serviceName} not yet implemented`);
380
+ return false;
381
+ }
382
+
383
+ return false;
384
+ }
385
+
386
+ async function addService(config: Config): Promise<void> {
387
+ const services = [
388
+ { value: 'github', label: 'GitHub' },
389
+ { value: 'vercel', label: 'Vercel' },
390
+ { value: 'supabase', label: 'Supabase' },
391
+ { value: 'anthropic', label: 'Anthropic (Claude)' },
392
+ { value: 'openai', label: 'OpenAI' },
393
+ { value: 'stripe', label: 'Stripe' },
394
+ { value: 'twilio', label: 'Twilio' },
395
+ { value: 'vapi', label: 'VAPI' },
396
+ { value: 'resend', label: 'Resend' },
397
+ { value: 'elevenLabs', label: 'ElevenLabs' },
398
+ { value: 'microsoft', label: 'Microsoft Graph' },
399
+ { value: 'google', label: 'Google APIs' },
400
+ ];
401
+
402
+ const service = await p.select({
403
+ message: 'Which service do you want to connect?',
404
+ options: services,
405
+ });
406
+
407
+ if (!p.isCancel(service)) {
408
+ const serviceInfo = services.find(s => s.value === service);
409
+ if (serviceInfo) {
410
+ await connectService(config, serviceInfo.value, serviceInfo.label, false);
411
+ }
412
+ }
413
+ }
414
+
415
+ function showConnectedServices(config: Config): void {
416
+ const services = [
417
+ { key: 'github', name: 'GitHub' },
418
+ { key: 'vercel', name: 'Vercel' },
419
+ { key: 'supabase', name: 'Supabase' },
420
+ { key: 'anthropic', name: 'Anthropic' },
421
+ { key: 'openai', name: 'OpenAI' },
422
+ { key: 'stripe', name: 'Stripe' },
423
+ { key: 'twilio', name: 'Twilio' },
424
+ { key: 'vapi', name: 'VAPI' },
425
+ { key: 'resend', name: 'Resend' },
426
+ { key: 'elevenLabs', name: 'ElevenLabs' },
427
+ { key: 'microsoft', name: 'Microsoft' },
428
+ { key: 'google', name: 'Google' },
429
+ ];
430
+
431
+ console.log('\n' + chalk.bold('Connected Services:') + '\n');
432
+
433
+ for (const service of services) {
434
+ const creds = config.getCredentials(service.key);
435
+ const isConnected = creds && Object.values(creds).some(v => v);
436
+ const status = isConnected ? chalk.green('✓ Connected') : chalk.dim('○ Not connected');
437
+ console.log(` ${service.name.padEnd(15)} ${status}`);
438
+ }
439
+
440
+ console.log('');
441
+ }
442
+
443
+ async function installPatterns(config: Config): Promise<void> {
444
+ // In real implementation, this would copy the pattern files
445
+ // from the bundled templates to ~/.codebakers/patterns/
446
+ const patternsDir = config.getPatternsDir();
447
+ p.log.info(chalk.dim(`Patterns installed to ${patternsDir}`));
448
+ }
@@ -0,0 +1,56 @@
1
+ // src/commands/status.ts
2
+ import * as p from '@clack/prompts';
3
+ import chalk from 'chalk';
4
+ import * as fs from 'fs-extra';
5
+ import * as path from 'path';
6
+ import { Config } from '../utils/config.js';
7
+
8
+ export async function statusCommand(): Promise<void> {
9
+ const config = new Config();
10
+ const cwd = process.cwd();
11
+
12
+ p.intro(chalk.bgCyan.black(' Project Status '));
13
+
14
+ if (!config.isInProject()) {
15
+ // Show all projects
16
+ const projects = config.getProjects();
17
+
18
+ if (projects.length === 0) {
19
+ p.log.info('No projects found. Run `codebakers init` to create one.');
20
+ return;
21
+ }
22
+
23
+ console.log(chalk.bold('\nYour Projects:\n'));
24
+
25
+ for (const project of projects) {
26
+ const exists = await fs.pathExists(project.path);
27
+ const status = exists ? chalk.green('✓') : chalk.red('✗');
28
+ console.log(` ${status} ${project.name}`);
29
+ console.log(chalk.dim(` ${project.path}`));
30
+ console.log('');
31
+ }
32
+ return;
33
+ }
34
+
35
+ // Show current project status
36
+ const projectConfig = await fs.readJson(
37
+ path.join(cwd, '.codebakers', 'config.json')
38
+ ).catch(() => ({}));
39
+
40
+ const packageJson = await fs.readJson(
41
+ path.join(cwd, 'package.json')
42
+ ).catch(() => ({}));
43
+
44
+ console.log(`
45
+ ${chalk.bold('Project:')} ${packageJson.name || path.basename(cwd)}
46
+ ${chalk.bold('Framework:')} ${projectConfig.framework || 'unknown'}
47
+ ${chalk.bold('UI:')} ${projectConfig.ui || 'unknown'}
48
+
49
+ ${chalk.bold('Quick Actions:')}
50
+ ${chalk.cyan('codebakers code')} — AI coding agent
51
+ ${chalk.cyan('codebakers check')} — Pattern enforcement
52
+ ${chalk.cyan('codebakers deploy')} — Deploy to production
53
+ `);
54
+
55
+ p.outro('');
56
+ }