codebakers 2.3.7 → 2.5.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.
- package/dist/{advisors-GGUCFS4E.js → advisors-3PWAN6UL.js} +1 -1
- package/dist/{chunk-YUSDTJD6.js → chunk-URNRSXPU.js} +2 -2
- package/dist/{chunk-ND6T4UDY.js → chunk-WZQNFV7Q.js} +3 -3
- package/dist/index.js +762 -441
- package/dist/{prd-AIEY63YY.js → prd-YAUSAL5V.js} +1 -1
- package/package.json +1 -1
- package/src/commands/advisors.ts +2 -2
- package/src/commands/build.ts +12 -7
- package/src/commands/code.ts +2 -2
- package/src/commands/deploy.ts +3 -3
- package/src/commands/init.ts +81 -38
- package/src/commands/prd-maker.ts +1 -1
- package/src/commands/prd.ts +3 -3
- package/src/commands/website.ts +139 -64
- package/src/index.ts +1 -1
- package/src/utils/display.ts +325 -0
- package/src/utils/updates.ts +2 -21
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
prdCommand
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WZQNFV7Q.js";
|
|
5
5
|
import {
|
|
6
6
|
advisorsCommand
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-URNRSXPU.js";
|
|
8
8
|
import {
|
|
9
9
|
Config
|
|
10
10
|
} from "./chunk-ASIJIQYC.js";
|
|
@@ -18,31 +18,13 @@ import gradient from "gradient-string";
|
|
|
18
18
|
import * as path16 from "path";
|
|
19
19
|
|
|
20
20
|
// src/utils/updates.ts
|
|
21
|
-
import chalk from "chalk";
|
|
22
|
-
var VERSION = "1.0.0";
|
|
23
21
|
async function checkForUpdates() {
|
|
24
|
-
|
|
25
|
-
const response = await fetch("https://registry.npmjs.org/codebakers/latest", {
|
|
26
|
-
signal: AbortSignal.timeout(3e3)
|
|
27
|
-
});
|
|
28
|
-
if (!response.ok) return;
|
|
29
|
-
const data = await response.json();
|
|
30
|
-
const latestVersion = data.version;
|
|
31
|
-
if (latestVersion && latestVersion !== VERSION) {
|
|
32
|
-
console.log(chalk.yellow(`
|
|
33
|
-
\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E
|
|
34
|
-
\u2502 Update available: ${VERSION} \u2192 ${latestVersion.padEnd(10)} \u2502
|
|
35
|
-
\u2502 Run: npm install -g codebakers \u2502
|
|
36
|
-
\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F
|
|
37
|
-
`));
|
|
38
|
-
}
|
|
39
|
-
} catch {
|
|
40
|
-
}
|
|
22
|
+
return;
|
|
41
23
|
}
|
|
42
24
|
|
|
43
25
|
// src/commands/setup.ts
|
|
44
26
|
import * as p from "@clack/prompts";
|
|
45
|
-
import
|
|
27
|
+
import chalk from "chalk";
|
|
46
28
|
import boxen from "boxen";
|
|
47
29
|
import open from "open";
|
|
48
30
|
var SERVICES = {
|
|
@@ -254,14 +236,14 @@ async function setupCommand() {
|
|
|
254
236
|
return;
|
|
255
237
|
}
|
|
256
238
|
console.log(boxen(
|
|
257
|
-
|
|
239
|
+
chalk.bold.cyan("Welcome to CodeBakers Setup!\n\n") + chalk.white("We need to connect a few services to get started.\n\n") + chalk.dim("Your credentials are stored locally on your computer\n") + chalk.dim("in ~/.codebakers/ and never sent to our servers.\n\n") + chalk.yellow("Required: ") + chalk.white("Anthropic API key (for AI)\n") + chalk.dim("Optional: GitHub, Vercel, Supabase (for full features)"),
|
|
258
240
|
{ padding: 1, borderColor: "cyan", borderStyle: "round" }
|
|
259
241
|
));
|
|
260
|
-
console.log(
|
|
261
|
-
console.log(
|
|
262
|
-
console.log(
|
|
263
|
-
console.log(
|
|
264
|
-
console.log(
|
|
242
|
+
console.log(chalk.bold.cyan("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
243
|
+
console.log(chalk.bold.cyan(" STEP 1 of 4: Anthropic API Key (Required)"));
|
|
244
|
+
console.log(chalk.bold.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
|
|
245
|
+
console.log(chalk.white(" Anthropic (Claude)"));
|
|
246
|
+
console.log(chalk.dim(" Powers the AI coding agent\n"));
|
|
265
247
|
const hasAccount = await p.select({
|
|
266
248
|
message: "Do you have an Anthropic account?",
|
|
267
249
|
options: [
|
|
@@ -273,27 +255,27 @@ async function setupCommand() {
|
|
|
273
255
|
return;
|
|
274
256
|
}
|
|
275
257
|
if (hasAccount === "no") {
|
|
276
|
-
console.log(
|
|
277
|
-
console.log(
|
|
278
|
-
console.log(
|
|
279
|
-
console.log(
|
|
280
|
-
console.log(
|
|
281
|
-
console.log(
|
|
282
|
-
console.log(
|
|
258
|
+
console.log(chalk.yellow("\n No problem! Let's get you signed up.\n"));
|
|
259
|
+
console.log(chalk.white(" Steps:"));
|
|
260
|
+
console.log(chalk.cyan(" 1. ") + 'Click "Sign Up" on the page that opens');
|
|
261
|
+
console.log(chalk.cyan(" 2. ") + "Create your account (email + password)");
|
|
262
|
+
console.log(chalk.cyan(" 3. ") + "Once logged in, go to Settings \u2192 API Keys");
|
|
263
|
+
console.log(chalk.cyan(" 4. ") + 'Click "Create Key"');
|
|
264
|
+
console.log(chalk.cyan(" 5. ") + "Copy the key and paste it here\n");
|
|
283
265
|
const openSignup = await p.confirm({
|
|
284
266
|
message: "Open Anthropic signup page?",
|
|
285
267
|
initialValue: true
|
|
286
268
|
});
|
|
287
269
|
if (openSignup && !p.isCancel(openSignup)) {
|
|
288
270
|
await open("https://console.anthropic.com/");
|
|
289
|
-
console.log(
|
|
271
|
+
console.log(chalk.dim("\n Take your time - come back when you have your API key.\n"));
|
|
290
272
|
}
|
|
291
273
|
} else {
|
|
292
|
-
console.log(
|
|
293
|
-
console.log(
|
|
294
|
-
console.log(
|
|
295
|
-
console.log(
|
|
296
|
-
console.log(
|
|
274
|
+
console.log(chalk.bold.white("\n Here's what to do:\n"));
|
|
275
|
+
console.log(chalk.cyan(" 1. ") + "Log in to Anthropic Console");
|
|
276
|
+
console.log(chalk.cyan(" 2. ") + "Go to Settings \u2192 API Keys");
|
|
277
|
+
console.log(chalk.cyan(" 3. ") + 'Click "Create Key"');
|
|
278
|
+
console.log(chalk.cyan(" 4. ") + "Copy the key (starts with sk-ant-)");
|
|
297
279
|
console.log("");
|
|
298
280
|
const openBrowser = await p.confirm({
|
|
299
281
|
message: "Open Anthropic Console?",
|
|
@@ -314,36 +296,36 @@ async function setupCommand() {
|
|
|
314
296
|
}
|
|
315
297
|
});
|
|
316
298
|
if (p.isCancel(apiKey) || !apiKey) {
|
|
317
|
-
console.log(
|
|
318
|
-
console.log(
|
|
299
|
+
console.log(chalk.red("\n \u274C Anthropic API key is required to use CodeBakers."));
|
|
300
|
+
console.log(chalk.dim(" Run `codebakers setup` when you're ready to try again.\n"));
|
|
319
301
|
return;
|
|
320
302
|
}
|
|
321
303
|
config.setCredentials("anthropic", { apiKey });
|
|
322
|
-
console.log(
|
|
323
|
-
console.log(
|
|
324
|
-
console.log(
|
|
325
|
-
console.log(
|
|
304
|
+
console.log(chalk.green("\n \u2713 Anthropic connected successfully!\n"));
|
|
305
|
+
console.log(chalk.bold.cyan("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
306
|
+
console.log(chalk.bold.cyan(" STEP 2 of 4: GitHub Token (Recommended)"));
|
|
307
|
+
console.log(chalk.bold.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
|
|
326
308
|
await connectServiceWithInstructions(config, SERVICES.github, false);
|
|
327
|
-
console.log(
|
|
328
|
-
console.log(
|
|
329
|
-
console.log(
|
|
309
|
+
console.log(chalk.bold.cyan("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
310
|
+
console.log(chalk.bold.cyan(" STEP 3 of 4: Vercel Token (Recommended)"));
|
|
311
|
+
console.log(chalk.bold.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
|
|
330
312
|
await connectServiceWithInstructions(config, SERVICES.vercel, false);
|
|
331
|
-
console.log(
|
|
332
|
-
console.log(
|
|
333
|
-
console.log(
|
|
313
|
+
console.log(chalk.bold.cyan("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
314
|
+
console.log(chalk.bold.cyan(" STEP 4 of 4: Supabase Token (Optional)"));
|
|
315
|
+
console.log(chalk.bold.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
|
|
334
316
|
await connectServiceWithInstructions(config, SERVICES.supabase, false);
|
|
335
317
|
const connectedServices = CORE_SERVICES.filter((key) => config.getCredentials(key)).map((key) => SERVICES[key].name);
|
|
336
318
|
console.log(boxen(
|
|
337
|
-
|
|
319
|
+
chalk.bold.green("\u2713 Setup Complete!\n\n") + chalk.white("Connected: ") + chalk.cyan(connectedServices.join(", ")) + "\n\n" + chalk.bold.white("What to do next:\n\n") + chalk.cyan("1. ") + chalk.white("Open a terminal and navigate to where you want to build:\n") + chalk.dim(" cd C:\\dev\\my-project\n") + chalk.dim(" (or any folder where you want to create your project)\n\n") + chalk.cyan("2. ") + chalk.white("Run CodeBakers:\n") + chalk.dim(" codebakers\n\n") + chalk.bold.white("Or try these commands directly:\n\n") + chalk.dim(" codebakers website ") + chalk.white("Build a website by describing it\n") + chalk.dim(" codebakers init ") + chalk.white("Create a new project from scratch\n") + chalk.dim(" codebakers help ") + chalk.white("See all available commands"),
|
|
338
320
|
{ padding: 1, borderColor: "green", borderStyle: "round" }
|
|
339
321
|
));
|
|
340
322
|
}
|
|
341
323
|
async function connectServiceWithInstructions(config, service, required) {
|
|
342
|
-
console.log(
|
|
343
|
-
console.log(
|
|
324
|
+
console.log(chalk.white(` ${service.name}`));
|
|
325
|
+
console.log(chalk.dim(` ${service.description}
|
|
344
326
|
`));
|
|
345
327
|
if (!required) {
|
|
346
|
-
console.log(
|
|
328
|
+
console.log(chalk.yellow(` ${service.whyNeeded}
|
|
347
329
|
`));
|
|
348
330
|
}
|
|
349
331
|
const action = await p.select({
|
|
@@ -357,15 +339,15 @@ async function connectServiceWithInstructions(config, service, required) {
|
|
|
357
339
|
});
|
|
358
340
|
if (p.isCancel(action) || action === "skip") {
|
|
359
341
|
if (!required) {
|
|
360
|
-
console.log(
|
|
342
|
+
console.log(chalk.dim(`
|
|
361
343
|
Skipped ${service.name}. You can add it later with: codebakers setup
|
|
362
344
|
`));
|
|
363
345
|
}
|
|
364
346
|
return false;
|
|
365
347
|
}
|
|
366
|
-
console.log(
|
|
348
|
+
console.log(chalk.bold.white("\n Here's what to do:\n"));
|
|
367
349
|
service.steps.forEach((step, i) => {
|
|
368
|
-
console.log(
|
|
350
|
+
console.log(chalk.cyan(` ${i + 1}. `) + chalk.white(step));
|
|
369
351
|
});
|
|
370
352
|
console.log("");
|
|
371
353
|
const openBrowser = await p.confirm({
|
|
@@ -373,28 +355,28 @@ async function connectServiceWithInstructions(config, service, required) {
|
|
|
373
355
|
initialValue: true
|
|
374
356
|
});
|
|
375
357
|
if (openBrowser && !p.isCancel(openBrowser)) {
|
|
376
|
-
console.log(
|
|
358
|
+
console.log(chalk.dim(`
|
|
377
359
|
Opening: ${service.url}
|
|
378
360
|
`));
|
|
379
361
|
await open(service.url);
|
|
380
|
-
console.log(
|
|
362
|
+
console.log(chalk.dim(" Complete the steps above, then paste your key below.\n"));
|
|
381
363
|
}
|
|
382
364
|
const credentials = {};
|
|
383
365
|
for (const field of service.fields) {
|
|
384
366
|
const value = await p.text({
|
|
385
|
-
message: field.label + (field.hint ?
|
|
367
|
+
message: field.label + (field.hint ? chalk.dim(` (${field.hint})`) : "") + ":",
|
|
386
368
|
placeholder: field.placeholder,
|
|
387
369
|
validate: field.validate
|
|
388
370
|
});
|
|
389
371
|
if (p.isCancel(value)) return false;
|
|
390
372
|
if (!value) {
|
|
391
373
|
if (required) {
|
|
392
|
-
console.log(
|
|
374
|
+
console.log(chalk.red(`
|
|
393
375
|
${field.label} is required.
|
|
394
376
|
`));
|
|
395
377
|
return false;
|
|
396
378
|
}
|
|
397
|
-
console.log(
|
|
379
|
+
console.log(chalk.dim(`
|
|
398
380
|
Skipped ${service.name}.
|
|
399
381
|
`));
|
|
400
382
|
return false;
|
|
@@ -402,24 +384,24 @@ async function connectServiceWithInstructions(config, service, required) {
|
|
|
402
384
|
credentials[field.key] = value;
|
|
403
385
|
}
|
|
404
386
|
config.setCredentials(service.key, credentials);
|
|
405
|
-
console.log(
|
|
387
|
+
console.log(chalk.green(`
|
|
406
388
|
\u2713 ${service.name} connected successfully!
|
|
407
389
|
`));
|
|
408
390
|
return true;
|
|
409
391
|
}
|
|
410
392
|
async function showManagementMenu(config) {
|
|
411
|
-
console.log(
|
|
393
|
+
console.log(chalk.bold.cyan("\n CodeBakers Settings\n"));
|
|
412
394
|
const allServices = [...CORE_SERVICES, ...OPTIONAL_SERVICES];
|
|
413
395
|
const connected = allServices.filter((key) => config.getCredentials(key));
|
|
414
396
|
const notConnected = allServices.filter((key) => !config.getCredentials(key));
|
|
415
|
-
console.log(
|
|
397
|
+
console.log(chalk.green(" Connected:"));
|
|
416
398
|
connected.forEach((key) => {
|
|
417
|
-
console.log(
|
|
399
|
+
console.log(chalk.green(` \u2713 ${SERVICES[key].name}`));
|
|
418
400
|
});
|
|
419
401
|
if (notConnected.length > 0) {
|
|
420
|
-
console.log(
|
|
402
|
+
console.log(chalk.dim("\n Not connected:"));
|
|
421
403
|
notConnected.forEach((key) => {
|
|
422
|
-
console.log(
|
|
404
|
+
console.log(chalk.dim(` \u25CB ${SERVICES[key].name}`));
|
|
423
405
|
});
|
|
424
406
|
}
|
|
425
407
|
console.log("");
|
|
@@ -451,7 +433,7 @@ async function addService(config) {
|
|
|
451
433
|
const allServices = [...CORE_SERVICES, ...OPTIONAL_SERVICES];
|
|
452
434
|
const unconnected = allServices.filter((key) => !config.getCredentials(key));
|
|
453
435
|
if (unconnected.length === 0) {
|
|
454
|
-
console.log(
|
|
436
|
+
console.log(chalk.green("\n All services are already connected!\n"));
|
|
455
437
|
return;
|
|
456
438
|
}
|
|
457
439
|
const selected = await p.select({
|
|
@@ -468,7 +450,7 @@ async function updateService(config) {
|
|
|
468
450
|
const allServices = [...CORE_SERVICES, ...OPTIONAL_SERVICES];
|
|
469
451
|
const connected = allServices.filter((key) => config.getCredentials(key));
|
|
470
452
|
if (connected.length === 0) {
|
|
471
|
-
console.log(
|
|
453
|
+
console.log(chalk.yellow("\n No services connected yet.\n"));
|
|
472
454
|
return;
|
|
473
455
|
}
|
|
474
456
|
const selected = await p.select({
|
|
@@ -482,26 +464,26 @@ async function updateService(config) {
|
|
|
482
464
|
await connectServiceWithInstructions(config, SERVICES[selected], false);
|
|
483
465
|
}
|
|
484
466
|
async function resetConfig(config) {
|
|
485
|
-
console.log(
|
|
467
|
+
console.log(chalk.yellow("\n \u26A0\uFE0F This will remove ALL your saved API keys.\n"));
|
|
486
468
|
const confirm13 = await p.confirm({
|
|
487
469
|
message: "Are you sure?",
|
|
488
470
|
initialValue: false
|
|
489
471
|
});
|
|
490
472
|
if (!confirm13 || p.isCancel(confirm13)) {
|
|
491
|
-
console.log(
|
|
473
|
+
console.log(chalk.dim("\n Cancelled.\n"));
|
|
492
474
|
return;
|
|
493
475
|
}
|
|
494
476
|
const allServices = [...CORE_SERVICES, ...OPTIONAL_SERVICES];
|
|
495
477
|
for (const key of allServices) {
|
|
496
478
|
config.setCredentials(key, null);
|
|
497
479
|
}
|
|
498
|
-
console.log(
|
|
499
|
-
console.log(
|
|
480
|
+
console.log(chalk.green("\n \u2713 All settings reset.\n"));
|
|
481
|
+
console.log(chalk.dim(" Run `codebakers setup` to configure again.\n"));
|
|
500
482
|
}
|
|
501
483
|
|
|
502
484
|
// src/commands/init.ts
|
|
503
485
|
import * as p2 from "@clack/prompts";
|
|
504
|
-
import
|
|
486
|
+
import chalk2 from "chalk";
|
|
505
487
|
import * as fs from "fs-extra";
|
|
506
488
|
import * as path from "path";
|
|
507
489
|
import { execa as execa3 } from "execa";
|
|
@@ -1002,7 +984,7 @@ async function initCommand(options = {}) {
|
|
|
1002
984
|
p2.log.error("Please run `codebakers setup` first.");
|
|
1003
985
|
return;
|
|
1004
986
|
}
|
|
1005
|
-
p2.intro(
|
|
987
|
+
p2.intro(chalk2.bgCyan.black(" Create New Project "));
|
|
1006
988
|
let projectName = options.name;
|
|
1007
989
|
if (!projectName) {
|
|
1008
990
|
const name = await p2.text({
|
|
@@ -1138,51 +1120,92 @@ Domain: ${domain || "Vercel default"}`,
|
|
|
1138
1120
|
await createLocalProject(projectPath, projectConfig);
|
|
1139
1121
|
spinner16.stop("Local project created");
|
|
1140
1122
|
spinner16.start("Installing dependencies...");
|
|
1123
|
+
let installSuccess = false;
|
|
1141
1124
|
try {
|
|
1142
|
-
await execa3("npm", ["install"], { cwd: projectPath });
|
|
1125
|
+
await execa3("npm", ["install"], { cwd: projectPath, stdio: "inherit" });
|
|
1126
|
+
installSuccess = true;
|
|
1143
1127
|
} catch {
|
|
1144
1128
|
try {
|
|
1145
|
-
await execa3("pnpm", ["install"], { cwd: projectPath });
|
|
1129
|
+
await execa3("pnpm", ["install"], { cwd: projectPath, stdio: "inherit" });
|
|
1130
|
+
installSuccess = true;
|
|
1146
1131
|
} catch {
|
|
1147
|
-
|
|
1132
|
+
try {
|
|
1133
|
+
await execa3("yarn", ["install"], { cwd: projectPath, stdio: "inherit" });
|
|
1134
|
+
installSuccess = true;
|
|
1135
|
+
} catch {
|
|
1136
|
+
}
|
|
1148
1137
|
}
|
|
1149
1138
|
}
|
|
1150
|
-
|
|
1139
|
+
if (installSuccess) {
|
|
1140
|
+
spinner16.stop("Dependencies installed");
|
|
1141
|
+
} else {
|
|
1142
|
+
spinner16.stop("Dependencies installation failed");
|
|
1143
|
+
console.log(chalk2.yellow(' \u26A0\uFE0F Run "npm install" manually in the project folder'));
|
|
1144
|
+
}
|
|
1151
1145
|
if (services.includes("github")) {
|
|
1152
1146
|
spinner16.start("Creating GitHub repository...");
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1147
|
+
try {
|
|
1148
|
+
const github = new GitHubService(config);
|
|
1149
|
+
const repo = await github.createRepo(projectName, { private: true });
|
|
1150
|
+
spinner16.stop(`GitHub repo created: ${repo.html_url}`);
|
|
1151
|
+
try {
|
|
1152
|
+
await execa3("git", ["init"], { cwd: projectPath });
|
|
1153
|
+
await execa3("git", ["add", "."], { cwd: projectPath });
|
|
1154
|
+
await execa3("git", ["commit", "-m", "Initial commit by CodeBakers"], { cwd: projectPath });
|
|
1155
|
+
await execa3("git", ["remote", "add", "origin", repo.clone_url], { cwd: projectPath });
|
|
1156
|
+
await execa3("git", ["push", "-u", "origin", "main"], { cwd: projectPath });
|
|
1157
|
+
} catch (gitError) {
|
|
1158
|
+
console.log(chalk2.yellow(" \u26A0\uFE0F Git push failed. You can push manually later."));
|
|
1159
|
+
}
|
|
1160
|
+
} catch (error) {
|
|
1161
|
+
spinner16.stop("GitHub setup failed");
|
|
1162
|
+
console.log(chalk2.yellow(" \u26A0\uFE0F Could not create GitHub repo. Check your GitHub token."));
|
|
1163
|
+
}
|
|
1161
1164
|
}
|
|
1162
1165
|
if (services.includes("supabase")) {
|
|
1163
1166
|
spinner16.start("Creating Supabase project...");
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1167
|
+
try {
|
|
1168
|
+
const supabase = new SupabaseService(config);
|
|
1169
|
+
const project = await supabase.createProject(projectName);
|
|
1170
|
+
spinner16.stop(`Supabase project created: ${project.name}`);
|
|
1171
|
+
await fs.writeJson(
|
|
1172
|
+
path.join(projectPath, ".codebakers", "supabase.json"),
|
|
1173
|
+
{ projectId: project.id, projectUrl: project.api_url },
|
|
1174
|
+
{ spaces: 2 }
|
|
1175
|
+
);
|
|
1176
|
+
} catch (error) {
|
|
1177
|
+
spinner16.stop("Supabase setup failed");
|
|
1178
|
+
console.log(chalk2.yellow(" \u26A0\uFE0F Could not create Supabase project. Check your Supabase token."));
|
|
1179
|
+
}
|
|
1172
1180
|
}
|
|
1173
1181
|
if (services.includes("vercel")) {
|
|
1174
1182
|
spinner16.start("Creating Vercel project...");
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1183
|
+
try {
|
|
1184
|
+
const vercel = new VercelService(config);
|
|
1185
|
+
const project = await vercel.createProject(projectName);
|
|
1186
|
+
spinner16.stop(`Vercel project created`);
|
|
1187
|
+
if (domain) {
|
|
1188
|
+
spinner16.start(`Configuring domain: ${domain}...`);
|
|
1189
|
+
try {
|
|
1190
|
+
await vercel.addDomain(projectName, domain);
|
|
1191
|
+
spinner16.stop("Domain configured");
|
|
1192
|
+
} catch {
|
|
1193
|
+
spinner16.stop("Domain configuration failed");
|
|
1194
|
+
console.log(chalk2.yellow(" \u26A0\uFE0F Could not configure domain. Add it manually in Vercel."));
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
spinner16.start("Deploying to Vercel...");
|
|
1198
|
+
try {
|
|
1199
|
+
const deployment = await vercel.deploy(projectPath);
|
|
1200
|
+
spinner16.stop(`Deployed: ${deployment.url}`);
|
|
1201
|
+
} catch {
|
|
1202
|
+
spinner16.stop("Deployment failed");
|
|
1203
|
+
console.log(chalk2.yellow(' \u26A0\uFE0F Could not deploy. Run "vercel" manually later.'));
|
|
1204
|
+
}
|
|
1205
|
+
} catch (error) {
|
|
1206
|
+
spinner16.stop("Vercel setup failed");
|
|
1207
|
+
console.log(chalk2.yellow(" \u26A0\uFE0F Could not create Vercel project. Check your Vercel token."));
|
|
1182
1208
|
}
|
|
1183
|
-
spinner16.start("Deploying to Vercel...");
|
|
1184
|
-
const deployment = await vercel.deploy(projectPath);
|
|
1185
|
-
spinner16.stop(`Deployed: ${deployment.url}`);
|
|
1186
1209
|
}
|
|
1187
1210
|
spinner16.start("Generating CLAUDE.md...");
|
|
1188
1211
|
const claudeMd = generateClaudeMd(projectConfig);
|
|
@@ -1196,18 +1219,18 @@ Domain: ${domain || "Vercel default"}`,
|
|
|
1196
1219
|
path: projectPath,
|
|
1197
1220
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1198
1221
|
});
|
|
1199
|
-
p2.outro(
|
|
1222
|
+
p2.outro(chalk2.green(`
|
|
1200
1223
|
\u2713 Project created!
|
|
1201
1224
|
|
|
1202
|
-
${
|
|
1203
|
-
${
|
|
1204
|
-
${
|
|
1225
|
+
${chalk2.bold("Your project is ready:")}
|
|
1226
|
+
${chalk2.cyan(`cd ${projectName}`)}
|
|
1227
|
+
${chalk2.cyan("codebakers code")}
|
|
1205
1228
|
|
|
1206
|
-
${
|
|
1207
|
-
${
|
|
1208
|
-
${
|
|
1209
|
-
${
|
|
1210
|
-
${
|
|
1229
|
+
${chalk2.dim("Shortcuts:")}
|
|
1230
|
+
${chalk2.cyan("codebakers")} \u2014 Interactive menu
|
|
1231
|
+
${chalk2.cyan("codebakers code")} \u2014 AI coding agent
|
|
1232
|
+
${chalk2.cyan("codebakers check")} \u2014 Pattern enforcement
|
|
1233
|
+
${chalk2.cyan("codebakers deploy")} \u2014 Deploy to production
|
|
1211
1234
|
`));
|
|
1212
1235
|
} catch (error) {
|
|
1213
1236
|
spinner16.stop("Error occurred");
|
|
@@ -1470,7 +1493,7 @@ echo "\u2713 CodeBakers check passed"
|
|
|
1470
1493
|
|
|
1471
1494
|
// src/commands/code.ts
|
|
1472
1495
|
import * as p6 from "@clack/prompts";
|
|
1473
|
-
import
|
|
1496
|
+
import chalk6 from "chalk";
|
|
1474
1497
|
import * as fs6 from "fs-extra";
|
|
1475
1498
|
import * as path5 from "path";
|
|
1476
1499
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -1778,7 +1801,7 @@ async function loadPatterns(config) {
|
|
|
1778
1801
|
|
|
1779
1802
|
// src/commands/check.ts
|
|
1780
1803
|
import * as p3 from "@clack/prompts";
|
|
1781
|
-
import
|
|
1804
|
+
import chalk3 from "chalk";
|
|
1782
1805
|
import * as fs3 from "fs-extra";
|
|
1783
1806
|
import * as path3 from "path";
|
|
1784
1807
|
import glob from "fast-glob";
|
|
@@ -1935,7 +1958,7 @@ async function checkCommand(options = {}) {
|
|
|
1935
1958
|
p3.log.error("Not in a CodeBakers project.");
|
|
1936
1959
|
return;
|
|
1937
1960
|
}
|
|
1938
|
-
p3.intro(
|
|
1961
|
+
p3.intro(chalk3.bgCyan.black(" CodeBakers Pattern Check "));
|
|
1939
1962
|
const spinner16 = p3.spinner();
|
|
1940
1963
|
spinner16.start("Analyzing code...");
|
|
1941
1964
|
const result = await runPatternCheck(options.fix || false);
|
|
@@ -1951,12 +1974,12 @@ async function checkCommand(options = {}) {
|
|
|
1951
1974
|
}
|
|
1952
1975
|
const errors = result.violations.filter((v) => v.severity === "error");
|
|
1953
1976
|
if (errors.length > 0) {
|
|
1954
|
-
p3.outro(
|
|
1977
|
+
p3.outro(chalk3.red(`\u274C ${errors.length} errors found. Fix before committing.`));
|
|
1955
1978
|
process.exit(1);
|
|
1956
1979
|
} else if (result.violations.length > 0) {
|
|
1957
|
-
p3.outro(
|
|
1980
|
+
p3.outro(chalk3.yellow(`\u26A0\uFE0F ${result.violations.length} warnings. Consider fixing.`));
|
|
1958
1981
|
} else {
|
|
1959
|
-
p3.outro(
|
|
1982
|
+
p3.outro(chalk3.green("\u2713 All patterns satisfied!"));
|
|
1960
1983
|
}
|
|
1961
1984
|
}
|
|
1962
1985
|
async function runPatternCheck(autoFix2) {
|
|
@@ -2012,11 +2035,11 @@ async function runPatternCheck(autoFix2) {
|
|
|
2012
2035
|
};
|
|
2013
2036
|
}
|
|
2014
2037
|
function displayResults(result) {
|
|
2015
|
-
console.log(
|
|
2038
|
+
console.log(chalk3.dim(`
|
|
2016
2039
|
Checked ${result.filesChecked} files
|
|
2017
2040
|
`));
|
|
2018
2041
|
if (result.violations.length === 0) {
|
|
2019
|
-
console.log(
|
|
2042
|
+
console.log(chalk3.green(" \u2713 No violations found\n"));
|
|
2020
2043
|
return;
|
|
2021
2044
|
}
|
|
2022
2045
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -2027,22 +2050,22 @@ Checked ${result.filesChecked} files
|
|
|
2027
2050
|
byFile.get(v.file).push(v);
|
|
2028
2051
|
}
|
|
2029
2052
|
for (const [file, fileViolations] of byFile) {
|
|
2030
|
-
console.log(
|
|
2053
|
+
console.log(chalk3.bold(file));
|
|
2031
2054
|
for (const v of fileViolations) {
|
|
2032
|
-
const icon = v.severity === "error" ?
|
|
2033
|
-
const fixable = v.autoFixable ?
|
|
2055
|
+
const icon = v.severity === "error" ? chalk3.red("\u2717") : chalk3.yellow("\u26A0");
|
|
2056
|
+
const fixable = v.autoFixable ? chalk3.dim(" (auto-fixable)") : "";
|
|
2034
2057
|
console.log(` ${icon} Line ${v.line}: ${v.message}${fixable}`);
|
|
2035
2058
|
}
|
|
2036
2059
|
console.log("");
|
|
2037
2060
|
}
|
|
2038
2061
|
const errors = result.violations.filter((v) => v.severity === "error").length;
|
|
2039
2062
|
const warnings = result.violations.filter((v) => v.severity === "warning").length;
|
|
2040
|
-
console.log(
|
|
2063
|
+
console.log(chalk3.bold("Summary:"));
|
|
2041
2064
|
if (errors > 0) {
|
|
2042
|
-
console.log(
|
|
2065
|
+
console.log(chalk3.red(` ${errors} error(s)`));
|
|
2043
2066
|
}
|
|
2044
2067
|
if (warnings > 0) {
|
|
2045
|
-
console.log(
|
|
2068
|
+
console.log(chalk3.yellow(` ${warnings} warning(s)`));
|
|
2046
2069
|
}
|
|
2047
2070
|
console.log("");
|
|
2048
2071
|
}
|
|
@@ -2076,7 +2099,7 @@ async function autoFix(violations) {
|
|
|
2076
2099
|
|
|
2077
2100
|
// src/utils/voice.ts
|
|
2078
2101
|
import * as p4 from "@clack/prompts";
|
|
2079
|
-
import
|
|
2102
|
+
import chalk4 from "chalk";
|
|
2080
2103
|
import * as fs4 from "fs-extra";
|
|
2081
2104
|
import { execa as execa4 } from "execa";
|
|
2082
2105
|
var voiceAvailable = null;
|
|
@@ -2104,7 +2127,7 @@ async function checkVoiceAvailability() {
|
|
|
2104
2127
|
}
|
|
2105
2128
|
async function textWithVoice(options) {
|
|
2106
2129
|
const hasVoice = await checkVoiceAvailability();
|
|
2107
|
-
const hint = hasVoice ?
|
|
2130
|
+
const hint = hasVoice ? chalk4.dim(' (type "v" for voice)') : "";
|
|
2108
2131
|
const result = await p4.text({
|
|
2109
2132
|
message: options.message + hint,
|
|
2110
2133
|
placeholder: options.placeholder,
|
|
@@ -2120,7 +2143,7 @@ async function textWithVoice(options) {
|
|
|
2120
2143
|
const val = result.toLowerCase().trim();
|
|
2121
2144
|
if (val === "v" || val === "voice") {
|
|
2122
2145
|
if (!hasVoice) {
|
|
2123
|
-
console.log(
|
|
2146
|
+
console.log(chalk4.yellow("Voice input not available on this system."));
|
|
2124
2147
|
return textWithVoice(options);
|
|
2125
2148
|
}
|
|
2126
2149
|
const voiceResult = await getVoiceInput(options.message);
|
|
@@ -2130,7 +2153,7 @@ async function textWithVoice(options) {
|
|
|
2130
2153
|
if (options.validate) {
|
|
2131
2154
|
const error = options.validate(voiceResult);
|
|
2132
2155
|
if (error) {
|
|
2133
|
-
console.log(
|
|
2156
|
+
console.log(chalk4.red(error));
|
|
2134
2157
|
return textWithVoice(options);
|
|
2135
2158
|
}
|
|
2136
2159
|
}
|
|
@@ -2139,9 +2162,9 @@ async function textWithVoice(options) {
|
|
|
2139
2162
|
return result;
|
|
2140
2163
|
}
|
|
2141
2164
|
async function getVoiceInput(prompt) {
|
|
2142
|
-
console.log(
|
|
2165
|
+
console.log(chalk4.cyan(`
|
|
2143
2166
|
\u{1F3A4} ${prompt}`));
|
|
2144
|
-
console.log(
|
|
2167
|
+
console.log(chalk4.dim(" Speak after the beep. Recording stops after silence.\n"));
|
|
2145
2168
|
const ready = await p4.confirm({
|
|
2146
2169
|
message: "Ready to record?",
|
|
2147
2170
|
initialValue: true
|
|
@@ -2163,7 +2186,7 @@ async function getVoiceInput(prompt) {
|
|
|
2163
2186
|
}
|
|
2164
2187
|
spinner16.stop("Recording complete");
|
|
2165
2188
|
if (transcription) {
|
|
2166
|
-
console.log(
|
|
2189
|
+
console.log(chalk4.green(`
|
|
2167
2190
|
\u2713 Heard: "${transcription}"
|
|
2168
2191
|
`));
|
|
2169
2192
|
const confirm13 = await p4.confirm({
|
|
@@ -2190,13 +2213,13 @@ async function getVoiceInput(prompt) {
|
|
|
2190
2213
|
}
|
|
2191
2214
|
}
|
|
2192
2215
|
} else {
|
|
2193
|
-
console.log(
|
|
2216
|
+
console.log(chalk4.yellow("\n No speech detected. Try again or type your response.\n"));
|
|
2194
2217
|
const text17 = await p4.text({ message: "Type instead:" });
|
|
2195
2218
|
return p4.isCancel(text17) ? null : text17;
|
|
2196
2219
|
}
|
|
2197
2220
|
} catch (error) {
|
|
2198
2221
|
spinner16.stop("Recording failed");
|
|
2199
|
-
console.log(
|
|
2222
|
+
console.log(chalk4.yellow("Voice input failed. Please type instead."));
|
|
2200
2223
|
const text17 = await p4.text({ message: prompt });
|
|
2201
2224
|
return p4.isCancel(text17) ? null : text17;
|
|
2202
2225
|
}
|
|
@@ -2345,7 +2368,7 @@ async function transcribeWithWhisper(audioFile) {
|
|
|
2345
2368
|
|
|
2346
2369
|
// src/utils/files.ts
|
|
2347
2370
|
import * as p5 from "@clack/prompts";
|
|
2348
|
-
import
|
|
2371
|
+
import chalk5 from "chalk";
|
|
2349
2372
|
import * as fs5 from "fs-extra";
|
|
2350
2373
|
import * as path4 from "path";
|
|
2351
2374
|
import { execa as execa5 } from "execa";
|
|
@@ -2382,7 +2405,7 @@ async function readFile5(filePath) {
|
|
|
2382
2405
|
}
|
|
2383
2406
|
const stats = await fs5.stat(cleanPath);
|
|
2384
2407
|
if (stats.size > 10 * 1024 * 1024) {
|
|
2385
|
-
console.log(
|
|
2408
|
+
console.log(chalk5.yellow("File too large (max 10MB)"));
|
|
2386
2409
|
return null;
|
|
2387
2410
|
}
|
|
2388
2411
|
const ext = path4.extname(cleanPath).toLowerCase();
|
|
@@ -2472,7 +2495,7 @@ async function readFile5(filePath) {
|
|
|
2472
2495
|
}
|
|
2473
2496
|
}
|
|
2474
2497
|
} catch (error) {
|
|
2475
|
-
console.log(
|
|
2498
|
+
console.log(chalk5.red(`Error reading file: ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
2476
2499
|
return null;
|
|
2477
2500
|
}
|
|
2478
2501
|
}
|
|
@@ -2528,9 +2551,9 @@ async function handlePastedContent(text17) {
|
|
|
2528
2551
|
if (!looksLikePaste(text17)) {
|
|
2529
2552
|
return null;
|
|
2530
2553
|
}
|
|
2531
|
-
console.log(
|
|
2554
|
+
console.log(chalk5.cyan("\n\u{1F4CB} Detected pasted content!\n"));
|
|
2532
2555
|
const preview = text17.length > 200 ? text17.slice(0, 200) + "..." : text17;
|
|
2533
|
-
console.log(
|
|
2556
|
+
console.log(chalk5.dim(preview));
|
|
2534
2557
|
console.log("");
|
|
2535
2558
|
const action = await p5.select({
|
|
2536
2559
|
message: "What should I do with this?",
|
|
@@ -2590,11 +2613,11 @@ ${text17}
|
|
|
2590
2613
|
async function codeCommand(prompt, options = {}) {
|
|
2591
2614
|
const config = new Config();
|
|
2592
2615
|
if (!config.isConfigured()) {
|
|
2593
|
-
console.log(
|
|
2616
|
+
console.log(chalk6.yellow(`
|
|
2594
2617
|
\u26A0\uFE0F CodeBakers isn't set up yet.
|
|
2595
2618
|
|
|
2596
2619
|
Run this first:
|
|
2597
|
-
${
|
|
2620
|
+
${chalk6.cyan("codebakers setup")}
|
|
2598
2621
|
|
|
2599
2622
|
This connects your API keys (Anthropic, GitHub, etc.)
|
|
2600
2623
|
so CodeBakers can generate code and deploy for you.
|
|
@@ -2602,28 +2625,28 @@ async function codeCommand(prompt, options = {}) {
|
|
|
2602
2625
|
return;
|
|
2603
2626
|
}
|
|
2604
2627
|
if (!config.isInProject()) {
|
|
2605
|
-
console.log(
|
|
2628
|
+
console.log(chalk6.yellow(`
|
|
2606
2629
|
\u26A0\uFE0F You're not in a CodeBakers project.
|
|
2607
2630
|
|
|
2608
2631
|
Options:
|
|
2609
|
-
${
|
|
2610
|
-
${
|
|
2611
|
-
${
|
|
2632
|
+
${chalk6.cyan("codebakers init")} Create a new project here
|
|
2633
|
+
${chalk6.cyan("codebakers website")} Build a website by describing it
|
|
2634
|
+
${chalk6.cyan("cd my-project")} Navigate to an existing project
|
|
2612
2635
|
`));
|
|
2613
2636
|
return;
|
|
2614
2637
|
}
|
|
2615
2638
|
const anthropicCreds = config.getCredentials("anthropic");
|
|
2616
2639
|
if (!anthropicCreds?.apiKey) {
|
|
2617
|
-
console.log(
|
|
2640
|
+
console.log(chalk6.yellow(`
|
|
2618
2641
|
\u26A0\uFE0F Anthropic API key not configured.
|
|
2619
2642
|
|
|
2620
2643
|
The AI coding agent needs Claude to work.
|
|
2621
2644
|
|
|
2622
2645
|
Run this to add your API key:
|
|
2623
|
-
${
|
|
2646
|
+
${chalk6.cyan("codebakers setup")}
|
|
2624
2647
|
|
|
2625
2648
|
Get an API key at:
|
|
2626
|
-
${
|
|
2649
|
+
${chalk6.dim("https://console.anthropic.com/settings/keys")}
|
|
2627
2650
|
`));
|
|
2628
2651
|
return;
|
|
2629
2652
|
}
|
|
@@ -2633,7 +2656,7 @@ async function codeCommand(prompt, options = {}) {
|
|
|
2633
2656
|
const projectContext = await loadProjectContext();
|
|
2634
2657
|
const patterns = await loadPatterns(config);
|
|
2635
2658
|
const systemPrompt = buildSystemPrompt(projectContext, patterns);
|
|
2636
|
-
console.log(
|
|
2659
|
+
console.log(chalk6.cyan(`
|
|
2637
2660
|
\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E
|
|
2638
2661
|
\u2502 \u{1F916} CodeBakers AI \u2502
|
|
2639
2662
|
\u2502 \u2502
|
|
@@ -2649,13 +2672,13 @@ async function codeCommand(prompt, options = {}) {
|
|
|
2649
2672
|
await processUserInput(prompt, messages, anthropic, systemPrompt, projectContext, config);
|
|
2650
2673
|
}
|
|
2651
2674
|
const hasVoice = await checkVoiceAvailability();
|
|
2652
|
-
console.log(
|
|
2675
|
+
console.log(chalk6.dim(" \u{1F4A1} Tips:"));
|
|
2653
2676
|
if (hasVoice) {
|
|
2654
|
-
console.log(
|
|
2677
|
+
console.log(chalk6.dim(' \u2022 Type "v" for voice input'));
|
|
2655
2678
|
}
|
|
2656
|
-
console.log(
|
|
2657
|
-
console.log(
|
|
2658
|
-
console.log(
|
|
2679
|
+
console.log(chalk6.dim(' \u2022 Type "clip" to read from clipboard'));
|
|
2680
|
+
console.log(chalk6.dim(" \u2022 Drag & drop files or paste file paths"));
|
|
2681
|
+
console.log(chalk6.dim(" \u2022 Paste code directly and I'll detect it\n"));
|
|
2659
2682
|
while (true) {
|
|
2660
2683
|
const input = await textWithVoice({
|
|
2661
2684
|
message: "",
|
|
@@ -2683,14 +2706,14 @@ async function codeCommand(prompt, options = {}) {
|
|
|
2683
2706
|
if (userInput.toLowerCase() === "clip" || userInput.toLowerCase() === "clipboard" || userInput.toLowerCase() === "paste") {
|
|
2684
2707
|
const clipContent = await readClipboard();
|
|
2685
2708
|
if (clipContent) {
|
|
2686
|
-
console.log(
|
|
2709
|
+
console.log(chalk6.green(`
|
|
2687
2710
|
\u{1F4CB} Read ${clipContent.length} characters from clipboard
|
|
2688
2711
|
`));
|
|
2689
2712
|
if (await fs6.pathExists(clipContent.trim())) {
|
|
2690
2713
|
const file = await readFile5(clipContent.trim());
|
|
2691
2714
|
if (file) {
|
|
2692
2715
|
fileContext = formatFilesForContext([file]);
|
|
2693
|
-
console.log(
|
|
2716
|
+
console.log(chalk6.green(`\u{1F4C4} Loaded file: ${file.name}
|
|
2694
2717
|
`));
|
|
2695
2718
|
const instruction = await p6.text({
|
|
2696
2719
|
message: `What should I do with ${file.name}?`,
|
|
@@ -2735,14 +2758,14 @@ ${clipContent}
|
|
|
2735
2758
|
}
|
|
2736
2759
|
}
|
|
2737
2760
|
} else {
|
|
2738
|
-
console.log(
|
|
2761
|
+
console.log(chalk6.yellow("Clipboard is empty"));
|
|
2739
2762
|
continue;
|
|
2740
2763
|
}
|
|
2741
2764
|
} else if (await fs6.pathExists(userInput)) {
|
|
2742
2765
|
const file = await readFile5(userInput);
|
|
2743
2766
|
if (file) {
|
|
2744
2767
|
fileContext = formatFilesForContext([file]);
|
|
2745
|
-
console.log(
|
|
2768
|
+
console.log(chalk6.green(`
|
|
2746
2769
|
\u{1F4C4} Loaded file: ${file.name}
|
|
2747
2770
|
`));
|
|
2748
2771
|
const instruction = await p6.text({
|
|
@@ -2773,7 +2796,7 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
|
|
|
2773
2796
|
try {
|
|
2774
2797
|
spinner16.start("Thinking...");
|
|
2775
2798
|
const response = await anthropic.messages.create({
|
|
2776
|
-
model: "claude-sonnet-4-
|
|
2799
|
+
model: "claude-sonnet-4-5-20250929",
|
|
2777
2800
|
max_tokens: 8192,
|
|
2778
2801
|
system: systemPrompt,
|
|
2779
2802
|
messages: messages.map((m) => ({
|
|
@@ -2786,9 +2809,9 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
|
|
|
2786
2809
|
messages.push({ role: "assistant", content: assistantMessage });
|
|
2787
2810
|
const actions = parseActions(assistantMessage);
|
|
2788
2811
|
if (actions.length > 0) {
|
|
2789
|
-
console.log(
|
|
2812
|
+
console.log(chalk6.cyan("\n\u{1F4CB} Plan:"));
|
|
2790
2813
|
actions.forEach((action, i) => {
|
|
2791
|
-
console.log(
|
|
2814
|
+
console.log(chalk6.dim(` ${i + 1}. ${action.description}`));
|
|
2792
2815
|
});
|
|
2793
2816
|
console.log("");
|
|
2794
2817
|
const proceed = await p6.confirm({
|
|
@@ -2801,10 +2824,10 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
|
|
|
2801
2824
|
await executeAction(action, spinner16);
|
|
2802
2825
|
}
|
|
2803
2826
|
spinner16.stop("Build complete");
|
|
2804
|
-
console.log(
|
|
2827
|
+
console.log(chalk6.dim("\n\u{1F50D} Running CodeBakers check..."));
|
|
2805
2828
|
const checkResult = await runPatternCheck(false);
|
|
2806
2829
|
if (checkResult.violations.length > 0) {
|
|
2807
|
-
console.log(
|
|
2830
|
+
console.log(chalk6.yellow(`
|
|
2808
2831
|
\u26A0\uFE0F ${checkResult.violations.length} pattern violations found`));
|
|
2809
2832
|
const autoFix2 = await p6.confirm({
|
|
2810
2833
|
message: "Auto-fix violations?",
|
|
@@ -2816,7 +2839,7 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
|
|
|
2816
2839
|
spinner16.stop("Violations fixed");
|
|
2817
2840
|
}
|
|
2818
2841
|
} else {
|
|
2819
|
-
console.log(
|
|
2842
|
+
console.log(chalk6.green("\u2713 All patterns satisfied"));
|
|
2820
2843
|
}
|
|
2821
2844
|
projectContext.recentChanges.push(...actions.map((a) => a.description));
|
|
2822
2845
|
}
|
|
@@ -2825,7 +2848,7 @@ async function processUserInput(userInput, messages, anthropic, systemPrompt, pr
|
|
|
2825
2848
|
}
|
|
2826
2849
|
} catch (error) {
|
|
2827
2850
|
spinner16.stop("Error");
|
|
2828
|
-
console.log(
|
|
2851
|
+
console.log(chalk6.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
2829
2852
|
}
|
|
2830
2853
|
}
|
|
2831
2854
|
function buildSystemPrompt(context, patterns) {
|
|
@@ -2996,7 +3019,7 @@ async function checkForWizard(input) {
|
|
|
2996
3019
|
return null;
|
|
2997
3020
|
}
|
|
2998
3021
|
async function runAuthWizard(originalInput) {
|
|
2999
|
-
console.log(
|
|
3022
|
+
console.log(chalk6.cyan("\n\u{1F510} Auth Wizard"));
|
|
3000
3023
|
const authType = await p6.select({
|
|
3001
3024
|
message: "What type of authentication?",
|
|
3002
3025
|
options: [
|
|
@@ -3033,7 +3056,7 @@ async function runAuthWizard(originalInput) {
|
|
|
3033
3056
|
- Follow all CodeBakers patterns`;
|
|
3034
3057
|
}
|
|
3035
3058
|
async function runPaymentWizard(originalInput) {
|
|
3036
|
-
console.log(
|
|
3059
|
+
console.log(chalk6.cyan("\n\u{1F4B3} Payment Wizard"));
|
|
3037
3060
|
const paymentType = await p6.select({
|
|
3038
3061
|
message: "What type of payment flow?",
|
|
3039
3062
|
options: [
|
|
@@ -3063,7 +3086,7 @@ async function runPaymentWizard(originalInput) {
|
|
|
3063
3086
|
- Follow all CodeBakers patterns`;
|
|
3064
3087
|
}
|
|
3065
3088
|
async function runFormWizard(originalInput) {
|
|
3066
|
-
console.log(
|
|
3089
|
+
console.log(chalk6.cyan("\n\u{1F4DD} Form Wizard"));
|
|
3067
3090
|
const formName = await p6.text({
|
|
3068
3091
|
message: "What is this form for?",
|
|
3069
3092
|
placeholder: "Contact form"
|
|
@@ -3079,7 +3102,7 @@ async function runFormWizard(originalInput) {
|
|
|
3079
3102
|
- Follow all CodeBakers patterns`;
|
|
3080
3103
|
}
|
|
3081
3104
|
async function runDashboardWizard(originalInput) {
|
|
3082
|
-
console.log(
|
|
3105
|
+
console.log(chalk6.cyan("\n\u{1F4CA} Dashboard Wizard"));
|
|
3083
3106
|
const components = await p6.multiselect({
|
|
3084
3107
|
message: "What components?",
|
|
3085
3108
|
options: [
|
|
@@ -3101,7 +3124,7 @@ async function runDashboardWizard(originalInput) {
|
|
|
3101
3124
|
- Follow all CodeBakers patterns`;
|
|
3102
3125
|
}
|
|
3103
3126
|
async function runAIWizard(originalInput) {
|
|
3104
|
-
console.log(
|
|
3127
|
+
console.log(chalk6.cyan("\n\u{1F916} AI Feature Wizard"));
|
|
3105
3128
|
const aiType = await p6.select({
|
|
3106
3129
|
message: "What AI feature?",
|
|
3107
3130
|
options: [
|
|
@@ -3128,14 +3151,14 @@ async function handleSlashCommand(command, context, config) {
|
|
|
3128
3151
|
const [cmd, ...args2] = command.slice(1).split(" ");
|
|
3129
3152
|
switch (cmd.toLowerCase()) {
|
|
3130
3153
|
case "deploy":
|
|
3131
|
-
console.log(
|
|
3154
|
+
console.log(chalk6.dim("Running deploy..."));
|
|
3132
3155
|
break;
|
|
3133
3156
|
case "check":
|
|
3134
|
-
console.log(
|
|
3157
|
+
console.log(chalk6.dim("Running pattern check..."));
|
|
3135
3158
|
await runPatternCheck(false);
|
|
3136
3159
|
break;
|
|
3137
3160
|
case "status":
|
|
3138
|
-
console.log(
|
|
3161
|
+
console.log(chalk6.cyan(`
|
|
3139
3162
|
Project: ${context.name}
|
|
3140
3163
|
Framework: ${context.framework}
|
|
3141
3164
|
UI: ${context.ui}
|
|
@@ -3143,17 +3166,17 @@ Files: ${context.existingFiles.length}
|
|
|
3143
3166
|
`));
|
|
3144
3167
|
break;
|
|
3145
3168
|
case "undo":
|
|
3146
|
-
console.log(
|
|
3169
|
+
console.log(chalk6.yellow("Undo not yet implemented"));
|
|
3147
3170
|
break;
|
|
3148
3171
|
case "help":
|
|
3149
3172
|
showHelp();
|
|
3150
3173
|
break;
|
|
3151
3174
|
default:
|
|
3152
|
-
console.log(
|
|
3175
|
+
console.log(chalk6.dim(`Unknown command: ${cmd}`));
|
|
3153
3176
|
}
|
|
3154
3177
|
}
|
|
3155
3178
|
function showHelp() {
|
|
3156
|
-
console.log(
|
|
3179
|
+
console.log(chalk6.cyan(`
|
|
3157
3180
|
Available commands:
|
|
3158
3181
|
|
|
3159
3182
|
/deploy Deploy to production
|
|
@@ -3190,7 +3213,7 @@ ${content}
|
|
|
3190
3213
|
|
|
3191
3214
|
Output only the fixed file content, no explanation.`;
|
|
3192
3215
|
const response = await anthropic.messages.create({
|
|
3193
|
-
model: "claude-sonnet-4-
|
|
3216
|
+
model: "claude-sonnet-4-5-20250929",
|
|
3194
3217
|
max_tokens: 8192,
|
|
3195
3218
|
system: systemPrompt,
|
|
3196
3219
|
messages: [{ role: "user", content: fixPrompt }]
|
|
@@ -3204,7 +3227,7 @@ Output only the fixed file content, no explanation.`;
|
|
|
3204
3227
|
|
|
3205
3228
|
// src/commands/deploy.ts
|
|
3206
3229
|
import * as p7 from "@clack/prompts";
|
|
3207
|
-
import
|
|
3230
|
+
import chalk7 from "chalk";
|
|
3208
3231
|
import { execa as execa7 } from "execa";
|
|
3209
3232
|
import * as fs7 from "fs-extra";
|
|
3210
3233
|
import * as path6 from "path";
|
|
@@ -3212,33 +3235,33 @@ import Anthropic2 from "@anthropic-ai/sdk";
|
|
|
3212
3235
|
async function deployCommand(options = {}) {
|
|
3213
3236
|
const config = new Config();
|
|
3214
3237
|
if (!config.isInProject()) {
|
|
3215
|
-
console.log(
|
|
3238
|
+
console.log(chalk7.yellow(`
|
|
3216
3239
|
\u26A0\uFE0F You're not in a CodeBakers project.
|
|
3217
3240
|
|
|
3218
3241
|
Navigate to your project first:
|
|
3219
|
-
${
|
|
3242
|
+
${chalk7.cyan("cd my-project")}
|
|
3220
3243
|
|
|
3221
3244
|
Or create a new one:
|
|
3222
|
-
${
|
|
3245
|
+
${chalk7.cyan("codebakers init")}
|
|
3223
3246
|
`));
|
|
3224
3247
|
return;
|
|
3225
3248
|
}
|
|
3226
3249
|
const vercelCreds = config.getCredentials("vercel");
|
|
3227
3250
|
if (!vercelCreds?.token) {
|
|
3228
|
-
console.log(
|
|
3251
|
+
console.log(chalk7.yellow(`
|
|
3229
3252
|
\u26A0\uFE0F Vercel isn't connected.
|
|
3230
3253
|
|
|
3231
3254
|
CodeBakers deploys to Vercel by default.
|
|
3232
3255
|
|
|
3233
3256
|
Run this to connect:
|
|
3234
|
-
${
|
|
3257
|
+
${chalk7.cyan("codebakers setup")}
|
|
3235
3258
|
|
|
3236
3259
|
Or deploy manually:
|
|
3237
|
-
${
|
|
3260
|
+
${chalk7.cyan("npx vercel")}
|
|
3238
3261
|
`));
|
|
3239
3262
|
return;
|
|
3240
3263
|
}
|
|
3241
|
-
p7.intro(
|
|
3264
|
+
p7.intro(chalk7.bgCyan.black(" Deploy to Production "));
|
|
3242
3265
|
const spinner16 = p7.spinner();
|
|
3243
3266
|
if (options.check !== false) {
|
|
3244
3267
|
spinner16.start("Running CodeBakers check...");
|
|
@@ -3254,7 +3277,7 @@ async function deployCommand(options = {}) {
|
|
|
3254
3277
|
});
|
|
3255
3278
|
if (showViolations && !p7.isCancel(showViolations)) {
|
|
3256
3279
|
for (const v of errors) {
|
|
3257
|
-
console.log(
|
|
3280
|
+
console.log(chalk7.red(` \u2717 ${v.file}:${v.line} - ${v.message}`));
|
|
3258
3281
|
}
|
|
3259
3282
|
}
|
|
3260
3283
|
const autoFix2 = await p7.confirm({
|
|
@@ -3262,7 +3285,7 @@ async function deployCommand(options = {}) {
|
|
|
3262
3285
|
initialValue: true
|
|
3263
3286
|
});
|
|
3264
3287
|
if (!autoFix2 || p7.isCancel(autoFix2)) {
|
|
3265
|
-
p7.outro(
|
|
3288
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3266
3289
|
return;
|
|
3267
3290
|
}
|
|
3268
3291
|
spinner16.start("Auto-fixing with AI...");
|
|
@@ -3271,7 +3294,7 @@ async function deployCommand(options = {}) {
|
|
|
3271
3294
|
const recheck = await runPatternCheck(false);
|
|
3272
3295
|
if (!recheck.passed) {
|
|
3273
3296
|
p7.log.error("Some violations remain. Manual fix required.");
|
|
3274
|
-
p7.outro(
|
|
3297
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3275
3298
|
return;
|
|
3276
3299
|
}
|
|
3277
3300
|
}
|
|
@@ -3294,11 +3317,11 @@ async function deployCommand(options = {}) {
|
|
|
3294
3317
|
const fixed = await fixTypeScriptErrors(config);
|
|
3295
3318
|
spinner16.stop(fixed ? "TypeScript errors fixed" : "Could not auto-fix all errors");
|
|
3296
3319
|
if (!fixed) {
|
|
3297
|
-
p7.outro(
|
|
3320
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3298
3321
|
return;
|
|
3299
3322
|
}
|
|
3300
3323
|
} else {
|
|
3301
|
-
p7.outro(
|
|
3324
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3302
3325
|
return;
|
|
3303
3326
|
}
|
|
3304
3327
|
}
|
|
@@ -3318,7 +3341,7 @@ async function deployCommand(options = {}) {
|
|
|
3318
3341
|
spinner16.stop("");
|
|
3319
3342
|
p7.log.error("Build failed.");
|
|
3320
3343
|
const errorOutput = error instanceof Error ? error.message : "Unknown error";
|
|
3321
|
-
console.log(
|
|
3344
|
+
console.log(chalk7.dim(errorOutput));
|
|
3322
3345
|
const fix = await p7.confirm({
|
|
3323
3346
|
message: "Attempt to fix build errors with AI?",
|
|
3324
3347
|
initialValue: true
|
|
@@ -3334,15 +3357,15 @@ async function deployCommand(options = {}) {
|
|
|
3334
3357
|
spinner16.stop("Build successful");
|
|
3335
3358
|
} catch {
|
|
3336
3359
|
spinner16.stop("Build still failing");
|
|
3337
|
-
p7.outro(
|
|
3360
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3338
3361
|
return;
|
|
3339
3362
|
}
|
|
3340
3363
|
} else {
|
|
3341
|
-
p7.outro(
|
|
3364
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3342
3365
|
return;
|
|
3343
3366
|
}
|
|
3344
3367
|
} else {
|
|
3345
|
-
p7.outro(
|
|
3368
|
+
p7.outro(chalk7.red("Deploy cancelled."));
|
|
3346
3369
|
return;
|
|
3347
3370
|
}
|
|
3348
3371
|
}
|
|
@@ -3378,14 +3401,14 @@ async function deployCommand(options = {}) {
|
|
|
3378
3401
|
const deployment = await vercel.deploy(process.cwd(), !options.preview);
|
|
3379
3402
|
spinner16.stop("Deployment complete!");
|
|
3380
3403
|
console.log(boxedOutput(`
|
|
3381
|
-
${
|
|
3404
|
+
${chalk7.green("\u2713")} Deployed successfully!
|
|
3382
3405
|
|
|
3383
|
-
${
|
|
3384
|
-
${
|
|
3385
|
-
${
|
|
3406
|
+
${chalk7.bold("URL:")} ${deployment.url}
|
|
3407
|
+
${chalk7.bold("Type:")} ${deployType}
|
|
3408
|
+
${chalk7.bold("Time:")} ${(/* @__PURE__ */ new Date()).toLocaleTimeString()}
|
|
3386
3409
|
|
|
3387
|
-
${
|
|
3388
|
-
${
|
|
3410
|
+
${chalk7.dim("View in Vercel Dashboard:")}
|
|
3411
|
+
${chalk7.dim(deployment.dashboardUrl || "https://vercel.com/dashboard")}
|
|
3389
3412
|
`));
|
|
3390
3413
|
} catch (error) {
|
|
3391
3414
|
spinner16.stop("");
|
|
@@ -3401,7 +3424,7 @@ ${chalk8.dim(deployment.dashboardUrl || "https://vercel.com/dashboard")}
|
|
|
3401
3424
|
spinner16.stop("Fix attempted");
|
|
3402
3425
|
}
|
|
3403
3426
|
}
|
|
3404
|
-
p7.outro(
|
|
3427
|
+
p7.outro(chalk7.red("Deploy failed."));
|
|
3405
3428
|
}
|
|
3406
3429
|
}
|
|
3407
3430
|
async function autoFixWithAI(config, violations) {
|
|
@@ -3434,7 +3457,7 @@ ${content}
|
|
|
3434
3457
|
|
|
3435
3458
|
Output ONLY the corrected file content, no explanations. Keep all existing functionality.`;
|
|
3436
3459
|
const response = await anthropic.messages.create({
|
|
3437
|
-
model: "claude-sonnet-4-
|
|
3460
|
+
model: "claude-sonnet-4-5-20250929",
|
|
3438
3461
|
max_tokens: 8192,
|
|
3439
3462
|
messages: [{ role: "user", content: prompt }]
|
|
3440
3463
|
});
|
|
@@ -3481,7 +3504,7 @@ ${content}
|
|
|
3481
3504
|
|
|
3482
3505
|
Output ONLY the corrected file content, no explanations.`;
|
|
3483
3506
|
const response = await anthropic.messages.create({
|
|
3484
|
-
model: "claude-sonnet-4-
|
|
3507
|
+
model: "claude-sonnet-4-5-20250929",
|
|
3485
3508
|
max_tokens: 8192,
|
|
3486
3509
|
messages: [{ role: "user", content: prompt }]
|
|
3487
3510
|
});
|
|
@@ -3526,7 +3549,7 @@ ${content}
|
|
|
3526
3549
|
Output ONLY the corrected file content, no explanations.`;
|
|
3527
3550
|
try {
|
|
3528
3551
|
const response = await anthropic.messages.create({
|
|
3529
|
-
model: "claude-sonnet-4-
|
|
3552
|
+
model: "claude-sonnet-4-5-20250929",
|
|
3530
3553
|
max_tokens: 8192,
|
|
3531
3554
|
messages: [{ role: "user", content: prompt }]
|
|
3532
3555
|
});
|
|
@@ -3559,25 +3582,25 @@ async function connectCommand(service) {
|
|
|
3559
3582
|
|
|
3560
3583
|
// src/commands/status.ts
|
|
3561
3584
|
import * as p8 from "@clack/prompts";
|
|
3562
|
-
import
|
|
3585
|
+
import chalk8 from "chalk";
|
|
3563
3586
|
import * as fs8 from "fs-extra";
|
|
3564
3587
|
import * as path7 from "path";
|
|
3565
3588
|
async function statusCommand() {
|
|
3566
3589
|
const config = new Config();
|
|
3567
3590
|
const cwd = process.cwd();
|
|
3568
|
-
p8.intro(
|
|
3591
|
+
p8.intro(chalk8.bgCyan.black(" Project Status "));
|
|
3569
3592
|
if (!config.isInProject()) {
|
|
3570
3593
|
const projects = config.getProjects();
|
|
3571
3594
|
if (projects.length === 0) {
|
|
3572
3595
|
p8.log.info("No projects found. Run `codebakers init` to create one.");
|
|
3573
3596
|
return;
|
|
3574
3597
|
}
|
|
3575
|
-
console.log(
|
|
3598
|
+
console.log(chalk8.bold("\nYour Projects:\n"));
|
|
3576
3599
|
for (const project of projects) {
|
|
3577
3600
|
const exists = await fs8.pathExists(project.path);
|
|
3578
|
-
const status = exists ?
|
|
3601
|
+
const status = exists ? chalk8.green("\u2713") : chalk8.red("\u2717");
|
|
3579
3602
|
console.log(` ${status} ${project.name}`);
|
|
3580
|
-
console.log(
|
|
3603
|
+
console.log(chalk8.dim(` ${project.path}`));
|
|
3581
3604
|
console.log("");
|
|
3582
3605
|
}
|
|
3583
3606
|
return;
|
|
@@ -3589,24 +3612,24 @@ async function statusCommand() {
|
|
|
3589
3612
|
path7.join(cwd, "package.json")
|
|
3590
3613
|
).catch(() => ({}));
|
|
3591
3614
|
console.log(`
|
|
3592
|
-
${
|
|
3593
|
-
${
|
|
3594
|
-
${
|
|
3595
|
-
|
|
3596
|
-
${
|
|
3597
|
-
${
|
|
3598
|
-
${
|
|
3599
|
-
${
|
|
3615
|
+
${chalk8.bold("Project:")} ${packageJson.name || path7.basename(cwd)}
|
|
3616
|
+
${chalk8.bold("Framework:")} ${projectConfig.framework || "unknown"}
|
|
3617
|
+
${chalk8.bold("UI:")} ${projectConfig.ui || "unknown"}
|
|
3618
|
+
|
|
3619
|
+
${chalk8.bold("Quick Actions:")}
|
|
3620
|
+
${chalk8.cyan("codebakers code")} \u2014 AI coding agent
|
|
3621
|
+
${chalk8.cyan("codebakers check")} \u2014 Pattern enforcement
|
|
3622
|
+
${chalk8.cyan("codebakers deploy")} \u2014 Deploy to production
|
|
3600
3623
|
`);
|
|
3601
3624
|
p8.outro("");
|
|
3602
3625
|
}
|
|
3603
3626
|
|
|
3604
3627
|
// src/commands/gateway.ts
|
|
3605
3628
|
import * as p9 from "@clack/prompts";
|
|
3606
|
-
import
|
|
3629
|
+
import chalk9 from "chalk";
|
|
3607
3630
|
async function gatewayCommand(options = {}) {
|
|
3608
3631
|
const config = new Config();
|
|
3609
|
-
p9.intro(
|
|
3632
|
+
p9.intro(chalk9.bgCyan.black(" Channel Gateway "));
|
|
3610
3633
|
if (options.start) {
|
|
3611
3634
|
await startAllChannels(config);
|
|
3612
3635
|
return;
|
|
@@ -3653,19 +3676,19 @@ async function gatewayCommand(options = {}) {
|
|
|
3653
3676
|
}
|
|
3654
3677
|
async function showGatewayStatus(config) {
|
|
3655
3678
|
const channels = await getChannelStatuses(config);
|
|
3656
|
-
console.log(
|
|
3679
|
+
console.log(chalk9.bold("\n\u{1F4F1} Channel Gateway Status\n"));
|
|
3657
3680
|
for (const channel of channels) {
|
|
3658
3681
|
const statusIcon = {
|
|
3659
|
-
running:
|
|
3660
|
-
stopped:
|
|
3661
|
-
error:
|
|
3662
|
-
connecting:
|
|
3682
|
+
running: chalk9.green("\u25CF"),
|
|
3683
|
+
stopped: chalk9.gray("\u25CB"),
|
|
3684
|
+
error: chalk9.red("\u2717"),
|
|
3685
|
+
connecting: chalk9.yellow("\u25D0")
|
|
3663
3686
|
}[channel.status];
|
|
3664
3687
|
const statusText = {
|
|
3665
|
-
running:
|
|
3666
|
-
stopped:
|
|
3667
|
-
error:
|
|
3668
|
-
connecting:
|
|
3688
|
+
running: chalk9.green("Running"),
|
|
3689
|
+
stopped: chalk9.gray("Stopped"),
|
|
3690
|
+
error: chalk9.red("Error"),
|
|
3691
|
+
connecting: chalk9.yellow("Connecting...")
|
|
3669
3692
|
}[channel.status];
|
|
3670
3693
|
console.log(` ${channel.icon} ${channel.name.padEnd(15)} ${statusIcon} ${statusText}`);
|
|
3671
3694
|
}
|
|
@@ -3751,8 +3774,8 @@ async function connectChannelWizard(config) {
|
|
|
3751
3774
|
}
|
|
3752
3775
|
}
|
|
3753
3776
|
async function connectWhatsApp(config) {
|
|
3754
|
-
p9.log.info(
|
|
3755
|
-
p9.log.info(
|
|
3777
|
+
p9.log.info(chalk9.bold("WhatsApp Setup"));
|
|
3778
|
+
p9.log.info(chalk9.dim(`
|
|
3756
3779
|
WhatsApp uses QR code authentication via Baileys library.
|
|
3757
3780
|
Your phone needs to scan a QR code to connect.
|
|
3758
3781
|
|
|
@@ -3768,7 +3791,7 @@ you'll need a Meta Business account.
|
|
|
3768
3791
|
spinner16.start("Generating QR code...");
|
|
3769
3792
|
try {
|
|
3770
3793
|
spinner16.stop("");
|
|
3771
|
-
console.log(
|
|
3794
|
+
console.log(chalk9.cyan(`
|
|
3772
3795
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
3773
3796
|
\u2551 \u2551
|
|
3774
3797
|
\u2551 \u2584\u2584\u2584\u2584\u2584\u2584\u2584 \u2584\u2584\u2584\u2584\u2584 \u2584\u2584\u2584\u2584\u2584\u2584\u2584 \u2551
|
|
@@ -3804,8 +3827,8 @@ Scan this QR code with WhatsApp:
|
|
|
3804
3827
|
}
|
|
3805
3828
|
}
|
|
3806
3829
|
async function connectTelegram(config) {
|
|
3807
|
-
p9.log.info(
|
|
3808
|
-
p9.log.info(
|
|
3830
|
+
p9.log.info(chalk9.bold("Telegram Bot Setup"));
|
|
3831
|
+
p9.log.info(chalk9.dim(`
|
|
3809
3832
|
To create a Telegram bot:
|
|
3810
3833
|
1. Open Telegram and search for @BotFather
|
|
3811
3834
|
2. Send /newbot
|
|
@@ -3851,8 +3874,8 @@ To create a Telegram bot:
|
|
|
3851
3874
|
}
|
|
3852
3875
|
}
|
|
3853
3876
|
async function connectDiscord(config) {
|
|
3854
|
-
p9.log.info(
|
|
3855
|
-
p9.log.info(
|
|
3877
|
+
p9.log.info(chalk9.bold("Discord Bot Setup"));
|
|
3878
|
+
p9.log.info(chalk9.dim(`
|
|
3856
3879
|
To create a Discord bot:
|
|
3857
3880
|
1. Go to Discord Developer Portal
|
|
3858
3881
|
2. Create a new application
|
|
@@ -3888,8 +3911,8 @@ To create a Discord bot:
|
|
|
3888
3911
|
p9.log.info(`Add bot to server: ${inviteUrl}`);
|
|
3889
3912
|
}
|
|
3890
3913
|
async function connectSlack(config) {
|
|
3891
|
-
p9.log.info(
|
|
3892
|
-
p9.log.info(
|
|
3914
|
+
p9.log.info(chalk9.bold("Slack App Setup"));
|
|
3915
|
+
p9.log.info(chalk9.dim(`
|
|
3893
3916
|
To create a Slack app:
|
|
3894
3917
|
1. Go to Slack API portal
|
|
3895
3918
|
2. Create a new app
|
|
@@ -3922,7 +3945,7 @@ To create a Slack app:
|
|
|
3922
3945
|
p9.log.success("Slack app configured!");
|
|
3923
3946
|
}
|
|
3924
3947
|
async function connectSMS(config) {
|
|
3925
|
-
p9.log.info(
|
|
3948
|
+
p9.log.info(chalk9.bold("SMS via Twilio"));
|
|
3926
3949
|
const twilioConfig = config.getCredentials("twilio");
|
|
3927
3950
|
if (twilioConfig?.accountSid) {
|
|
3928
3951
|
p9.log.info("Twilio is already configured.");
|
|
@@ -3969,7 +3992,7 @@ async function connectSMS(config) {
|
|
|
3969
3992
|
}
|
|
3970
3993
|
async function connectiMessage(config) {
|
|
3971
3994
|
p9.log.warn("iMessage support requires macOS and additional setup.");
|
|
3972
|
-
p9.log.info(
|
|
3995
|
+
p9.log.info(chalk9.dim(`
|
|
3973
3996
|
iMessage integration uses AppleScript on macOS.
|
|
3974
3997
|
This requires:
|
|
3975
3998
|
1. macOS with Messages app
|
|
@@ -3988,7 +4011,7 @@ async function startAllChannels(config) {
|
|
|
3988
4011
|
spinner16.start("Starting channel gateway...");
|
|
3989
4012
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
3990
4013
|
spinner16.stop("Gateway started");
|
|
3991
|
-
console.log(
|
|
4014
|
+
console.log(chalk9.green(`
|
|
3992
4015
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
3993
4016
|
\u2551 Gateway is running! \u2551
|
|
3994
4017
|
\u2551 \u2551
|
|
@@ -4007,7 +4030,7 @@ async function stopAllChannels(config) {
|
|
|
4007
4030
|
spinner16.stop("Gateway stopped");
|
|
4008
4031
|
}
|
|
4009
4032
|
async function deployGatewayWizard(config) {
|
|
4010
|
-
p9.log.info(
|
|
4033
|
+
p9.log.info(chalk9.bold("Deploy Gateway to Cloud"));
|
|
4011
4034
|
const platform = await p9.select({
|
|
4012
4035
|
message: "Where do you want to deploy?",
|
|
4013
4036
|
options: [
|
|
@@ -4020,14 +4043,14 @@ async function deployGatewayWizard(config) {
|
|
|
4020
4043
|
switch (platform) {
|
|
4021
4044
|
case "codebakers":
|
|
4022
4045
|
p9.log.info("CodeBakers Cloud coming soon!");
|
|
4023
|
-
p9.log.info(
|
|
4046
|
+
p9.log.info(chalk9.dim("Sign up at https://codebakers.dev/cloud"));
|
|
4024
4047
|
break;
|
|
4025
4048
|
case "vps":
|
|
4026
4049
|
await deployToVPS(config);
|
|
4027
4050
|
break;
|
|
4028
4051
|
case "local":
|
|
4029
4052
|
p9.log.info("Local deployment guide:");
|
|
4030
|
-
p9.log.info(
|
|
4053
|
+
p9.log.info(chalk9.dim(`
|
|
4031
4054
|
1. Install Node.js on your server
|
|
4032
4055
|
2. Clone your project
|
|
4033
4056
|
3. Run: npm install
|
|
@@ -4051,7 +4074,7 @@ async function deployToVPS(config) {
|
|
|
4051
4074
|
if (p9.isCancel(provider)) return;
|
|
4052
4075
|
if (provider === "digitalocean") {
|
|
4053
4076
|
p9.log.info("DigitalOcean auto-deploy:");
|
|
4054
|
-
p9.log.info(
|
|
4077
|
+
p9.log.info(chalk9.dim(`
|
|
4055
4078
|
1. Opening DigitalOcean login...
|
|
4056
4079
|
2. We'll create a $6/mo droplet
|
|
4057
4080
|
3. Install CodeBakers gateway
|
|
@@ -4066,7 +4089,7 @@ async function deployToVPS(config) {
|
|
|
4066
4089
|
await open3("https://cloud.digitalocean.com/");
|
|
4067
4090
|
}
|
|
4068
4091
|
} else {
|
|
4069
|
-
p9.log.info(
|
|
4092
|
+
p9.log.info(chalk9.dim(`
|
|
4070
4093
|
Manual VPS setup:
|
|
4071
4094
|
|
|
4072
4095
|
1. Create a VPS (Ubuntu 22.04 recommended)
|
|
@@ -4083,57 +4106,57 @@ Manual VPS setup:
|
|
|
4083
4106
|
|
|
4084
4107
|
// src/commands/learn.ts
|
|
4085
4108
|
import * as p10 from "@clack/prompts";
|
|
4086
|
-
import
|
|
4109
|
+
import chalk10 from "chalk";
|
|
4087
4110
|
async function learnCommand() {
|
|
4088
4111
|
const config = new Config();
|
|
4089
4112
|
const learning = config.getLearning();
|
|
4090
|
-
p10.intro(
|
|
4091
|
-
console.log(
|
|
4113
|
+
p10.intro(chalk10.bgCyan.black(" Learning Settings "));
|
|
4114
|
+
console.log(chalk10.bold("\n\u{1F9E0} What CodeBakers has learned about you:\n"));
|
|
4092
4115
|
const shortcuts = Object.entries(learning.shortcuts);
|
|
4093
4116
|
if (shortcuts.length > 0) {
|
|
4094
|
-
console.log(
|
|
4117
|
+
console.log(chalk10.bold("Shortcuts:"));
|
|
4095
4118
|
for (const [short, full] of shortcuts) {
|
|
4096
|
-
console.log(` ${
|
|
4119
|
+
console.log(` ${chalk10.cyan(short)} \u2192 ${full}`);
|
|
4097
4120
|
}
|
|
4098
4121
|
console.log("");
|
|
4099
4122
|
}
|
|
4100
4123
|
const prefs = Object.entries(learning.preferences);
|
|
4101
4124
|
if (prefs.length > 0) {
|
|
4102
|
-
console.log(
|
|
4125
|
+
console.log(chalk10.bold("Preferences:"));
|
|
4103
4126
|
for (const [key, value] of prefs) {
|
|
4104
|
-
console.log(` ${key}: ${
|
|
4127
|
+
console.log(` ${key}: ${chalk10.cyan(String(value))}`);
|
|
4105
4128
|
}
|
|
4106
4129
|
console.log("");
|
|
4107
4130
|
}
|
|
4108
4131
|
if (shortcuts.length === 0 && prefs.length === 0) {
|
|
4109
|
-
console.log(
|
|
4132
|
+
console.log(chalk10.dim(" Nothing learned yet. Use CodeBakers more!\n"));
|
|
4110
4133
|
}
|
|
4111
4134
|
p10.outro("");
|
|
4112
4135
|
}
|
|
4113
4136
|
|
|
4114
4137
|
// src/commands/security.ts
|
|
4115
4138
|
import * as p11 from "@clack/prompts";
|
|
4116
|
-
import
|
|
4139
|
+
import chalk11 from "chalk";
|
|
4117
4140
|
import * as fs9 from "fs-extra";
|
|
4118
4141
|
import glob2 from "fast-glob";
|
|
4119
4142
|
import * as path8 from "path";
|
|
4120
4143
|
async function securityCommand() {
|
|
4121
|
-
p11.intro(
|
|
4144
|
+
p11.intro(chalk11.bgCyan.black(" Security Audit "));
|
|
4122
4145
|
const spinner16 = p11.spinner();
|
|
4123
4146
|
spinner16.start("Scanning for security issues...");
|
|
4124
4147
|
const issues = await runSecurityScan();
|
|
4125
4148
|
spinner16.stop("Scan complete");
|
|
4126
4149
|
if (issues.length === 0) {
|
|
4127
|
-
console.log(
|
|
4150
|
+
console.log(chalk11.green("\n\u2713 No security issues found!\n"));
|
|
4128
4151
|
displaySecurityScore(100);
|
|
4129
4152
|
} else {
|
|
4130
|
-
console.log(
|
|
4153
|
+
console.log(chalk11.yellow(`
|
|
4131
4154
|
\u26A0\uFE0F ${issues.length} security issues found:
|
|
4132
4155
|
`));
|
|
4133
4156
|
for (const issue of issues) {
|
|
4134
|
-
const icon = issue.severity === "critical" ?
|
|
4135
|
-
console.log(`${icon} ${
|
|
4136
|
-
console.log(
|
|
4157
|
+
const icon = issue.severity === "critical" ? chalk11.red("\u{1F534}") : issue.severity === "high" ? chalk11.red("\u{1F7E0}") : chalk11.yellow("\u{1F7E1}");
|
|
4158
|
+
console.log(`${icon} ${chalk11.bold(issue.title)}`);
|
|
4159
|
+
console.log(chalk11.dim(` ${issue.file}:${issue.line}`));
|
|
4137
4160
|
console.log(` ${issue.description}
|
|
4138
4161
|
`);
|
|
4139
4162
|
}
|
|
@@ -4183,9 +4206,9 @@ async function runSecurityScan() {
|
|
|
4183
4206
|
return issues;
|
|
4184
4207
|
}
|
|
4185
4208
|
function displaySecurityScore(score) {
|
|
4186
|
-
const color = score >= 80 ?
|
|
4209
|
+
const color = score >= 80 ? chalk11.green : score >= 50 ? chalk11.yellow : chalk11.red;
|
|
4187
4210
|
const grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "F";
|
|
4188
|
-
console.log(
|
|
4211
|
+
console.log(chalk11.bold("Security Score:"));
|
|
4189
4212
|
console.log(color(`
|
|
4190
4213
|
${score}/100 Grade: ${grade}
|
|
4191
4214
|
`));
|
|
@@ -4193,11 +4216,11 @@ function displaySecurityScore(score) {
|
|
|
4193
4216
|
|
|
4194
4217
|
// src/commands/generate.ts
|
|
4195
4218
|
import * as p12 from "@clack/prompts";
|
|
4196
|
-
import
|
|
4219
|
+
import chalk12 from "chalk";
|
|
4197
4220
|
import * as fs10 from "fs-extra";
|
|
4198
4221
|
import * as path9 from "path";
|
|
4199
4222
|
async function generateCommand(type) {
|
|
4200
|
-
p12.intro(
|
|
4223
|
+
p12.intro(chalk12.bgCyan.black(" Generate "));
|
|
4201
4224
|
const generateType = type || await p12.select({
|
|
4202
4225
|
message: "What do you want to generate?",
|
|
4203
4226
|
options: [
|
|
@@ -4361,9 +4384,9 @@ export function ${name}Form({ onSuccess }: { onSuccess?: () => void }) {
|
|
|
4361
4384
|
|
|
4362
4385
|
// src/commands/fix.ts
|
|
4363
4386
|
import * as p13 from "@clack/prompts";
|
|
4364
|
-
import
|
|
4387
|
+
import chalk13 from "chalk";
|
|
4365
4388
|
async function fixCommand() {
|
|
4366
|
-
p13.intro(
|
|
4389
|
+
p13.intro(chalk13.bgCyan.black(" Auto-Fix "));
|
|
4367
4390
|
const spinner16 = p13.spinner();
|
|
4368
4391
|
spinner16.start("Analyzing code...");
|
|
4369
4392
|
const result = await runPatternCheck(true);
|
|
@@ -4372,12 +4395,12 @@ async function fixCommand() {
|
|
|
4372
4395
|
} else {
|
|
4373
4396
|
spinner16.stop(`Fixed ${result.violations.length} issues`);
|
|
4374
4397
|
}
|
|
4375
|
-
p13.outro(
|
|
4398
|
+
p13.outro(chalk13.green("Done!"));
|
|
4376
4399
|
}
|
|
4377
4400
|
|
|
4378
4401
|
// src/commands/design.ts
|
|
4379
4402
|
import * as p14 from "@clack/prompts";
|
|
4380
|
-
import
|
|
4403
|
+
import chalk14 from "chalk";
|
|
4381
4404
|
import * as fs11 from "fs-extra";
|
|
4382
4405
|
import * as path10 from "path";
|
|
4383
4406
|
var DESIGN_PROFILES = {
|
|
@@ -4436,7 +4459,7 @@ async function designCommand(subcommand) {
|
|
|
4436
4459
|
p14.log.error("Not in a CodeBakers project. Run `codebakers init` first.");
|
|
4437
4460
|
return;
|
|
4438
4461
|
}
|
|
4439
|
-
p14.intro(
|
|
4462
|
+
p14.intro(chalk14.bgCyan.black(" Design System "));
|
|
4440
4463
|
const action = subcommand || await p14.select({
|
|
4441
4464
|
message: "What do you want to do?",
|
|
4442
4465
|
options: [
|
|
@@ -4481,7 +4504,7 @@ async function setProfile() {
|
|
|
4481
4504
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4482
4505
|
}, { spaces: 2 });
|
|
4483
4506
|
p14.log.success(`Design profile set to ${selected.name}`);
|
|
4484
|
-
console.log(
|
|
4507
|
+
console.log(chalk14.dim(`
|
|
4485
4508
|
Fonts: ${selected.fonts.heading} / ${selected.fonts.body}
|
|
4486
4509
|
Corners: ${selected.corners}
|
|
4487
4510
|
Shadows: ${selected.shadows}
|
|
@@ -4511,10 +4534,10 @@ async function generatePalette() {
|
|
|
4511
4534
|
}, { spaces: 2 });
|
|
4512
4535
|
p14.log.success("Color palette generated!");
|
|
4513
4536
|
console.log(`
|
|
4514
|
-
${
|
|
4515
|
-
${
|
|
4516
|
-
${
|
|
4517
|
-
${
|
|
4537
|
+
${chalk14.bgHex(palette.brand[500]).black(" Brand ")} ${palette.brand[500]}
|
|
4538
|
+
${chalk14.bgHex(palette.brand[100]).black(" Light ")} ${palette.brand[100]}
|
|
4539
|
+
${chalk14.bgHex(palette.brand[900]).white(" Dark ")} ${palette.brand[900]}
|
|
4540
|
+
${chalk14.bgHex(palette.accent).black(" Accent ")} ${palette.accent}
|
|
4518
4541
|
`);
|
|
4519
4542
|
}
|
|
4520
4543
|
function generateColorPalette(hex) {
|
|
@@ -4600,13 +4623,13 @@ async function checkDesign() {
|
|
|
4600
4623
|
}
|
|
4601
4624
|
spinner16.stop("Check complete");
|
|
4602
4625
|
if (issues.length === 0) {
|
|
4603
|
-
console.log(
|
|
4626
|
+
console.log(chalk14.green("\n\u2713 No design issues found!\n"));
|
|
4604
4627
|
} else {
|
|
4605
|
-
console.log(
|
|
4628
|
+
console.log(chalk14.yellow(`
|
|
4606
4629
|
\u26A0\uFE0F ${issues.length} design issues found:
|
|
4607
4630
|
`));
|
|
4608
4631
|
for (const issue of issues) {
|
|
4609
|
-
console.log(
|
|
4632
|
+
console.log(chalk14.dim(` \u2022 ${issue}`));
|
|
4610
4633
|
}
|
|
4611
4634
|
console.log("");
|
|
4612
4635
|
}
|
|
@@ -4618,7 +4641,7 @@ async function viewSettings() {
|
|
|
4618
4641
|
return;
|
|
4619
4642
|
}
|
|
4620
4643
|
const config = await fs11.readJson(configPath);
|
|
4621
|
-
console.log(
|
|
4644
|
+
console.log(chalk14.bold("\nCurrent Design Settings:\n"));
|
|
4622
4645
|
console.log(` Profile: ${config.name || config.profile}`);
|
|
4623
4646
|
console.log(` Fonts: ${config.fonts?.heading} / ${config.fonts?.body}`);
|
|
4624
4647
|
console.log(` Corners: ${config.corners}`);
|
|
@@ -4633,7 +4656,7 @@ async function viewSettings() {
|
|
|
4633
4656
|
|
|
4634
4657
|
// src/commands/migrate.ts
|
|
4635
4658
|
import * as p15 from "@clack/prompts";
|
|
4636
|
-
import
|
|
4659
|
+
import chalk15 from "chalk";
|
|
4637
4660
|
import { execa as execa8 } from "execa";
|
|
4638
4661
|
import * as fs12 from "fs-extra";
|
|
4639
4662
|
import * as path11 from "path";
|
|
@@ -4643,7 +4666,7 @@ async function migrateCommand(options = {}) {
|
|
|
4643
4666
|
p15.log.error("Not in a CodeBakers project.");
|
|
4644
4667
|
return;
|
|
4645
4668
|
}
|
|
4646
|
-
p15.intro(
|
|
4669
|
+
p15.intro(chalk15.bgCyan.black(" Database Migrations "));
|
|
4647
4670
|
const migrationTool = await detectMigrationTool();
|
|
4648
4671
|
if (!migrationTool) {
|
|
4649
4672
|
p15.log.error("No migration tool detected. Supported: Drizzle, Prisma, Supabase CLI");
|
|
@@ -4713,10 +4736,10 @@ async function checkMigrationStatus(tool) {
|
|
|
4713
4736
|
}
|
|
4714
4737
|
spinner16.stop("Status check complete");
|
|
4715
4738
|
if (result?.stdout) {
|
|
4716
|
-
console.log(
|
|
4739
|
+
console.log(chalk15.dim(result.stdout));
|
|
4717
4740
|
}
|
|
4718
4741
|
if (result?.stderr) {
|
|
4719
|
-
console.log(
|
|
4742
|
+
console.log(chalk15.yellow(result.stderr));
|
|
4720
4743
|
}
|
|
4721
4744
|
} catch (error) {
|
|
4722
4745
|
spinner16.stop("Error checking status");
|
|
@@ -4747,7 +4770,7 @@ async function generateMigration(tool) {
|
|
|
4747
4770
|
}
|
|
4748
4771
|
spinner16.stop("Migration generated");
|
|
4749
4772
|
if (result?.stdout) {
|
|
4750
|
-
console.log(
|
|
4773
|
+
console.log(chalk15.dim(result.stdout));
|
|
4751
4774
|
}
|
|
4752
4775
|
} catch (error) {
|
|
4753
4776
|
spinner16.stop("Error generating migration");
|
|
@@ -4784,13 +4807,13 @@ async function pushMigration(tool) {
|
|
|
4784
4807
|
if (result?.exitCode !== 0) {
|
|
4785
4808
|
spinner16.stop("Migration push failed");
|
|
4786
4809
|
const errorOutput = result?.stderr || result?.stdout || "";
|
|
4787
|
-
console.log(
|
|
4788
|
-
console.log(
|
|
4810
|
+
console.log(chalk15.red("\nError:\n"));
|
|
4811
|
+
console.log(chalk15.dim(errorOutput));
|
|
4789
4812
|
migrationSql = await extractMigrationSQL(tool, errorOutput);
|
|
4790
4813
|
if (migrationSql) {
|
|
4791
4814
|
const copied = await copyToClipboard(migrationSql);
|
|
4792
4815
|
if (copied) {
|
|
4793
|
-
console.log(
|
|
4816
|
+
console.log(chalk15.green(`
|
|
4794
4817
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
4795
4818
|
\u2551 \u{1F4CB} MIGRATION SQL COPIED TO CLIPBOARD! \u2551
|
|
4796
4819
|
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
@@ -4810,24 +4833,24 @@ async function pushMigration(tool) {
|
|
|
4810
4833
|
initialValue: true
|
|
4811
4834
|
});
|
|
4812
4835
|
if (showSql && !p15.isCancel(showSql)) {
|
|
4813
|
-
console.log(
|
|
4836
|
+
console.log(chalk15.cyan("\n--- SQL Migration ---\n"));
|
|
4814
4837
|
console.log(migrationSql);
|
|
4815
|
-
console.log(
|
|
4838
|
+
console.log(chalk15.cyan("\n--- End SQL ---\n"));
|
|
4816
4839
|
}
|
|
4817
4840
|
} else {
|
|
4818
|
-
console.log(
|
|
4841
|
+
console.log(chalk15.yellow(`
|
|
4819
4842
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
4820
4843
|
\u2551 \u26A0\uFE0F Could not copy to clipboard \u2551
|
|
4821
4844
|
\u2551 \u2551
|
|
4822
4845
|
\u2551 Here's the SQL to run manually: \u2551
|
|
4823
4846
|
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
4824
4847
|
`));
|
|
4825
|
-
console.log(
|
|
4848
|
+
console.log(chalk15.cyan(migrationSql));
|
|
4826
4849
|
}
|
|
4827
4850
|
const sqlPath = path11.join(process.cwd(), ".codebakers", "failed-migration.sql");
|
|
4828
4851
|
await fs12.ensureDir(path11.dirname(sqlPath));
|
|
4829
4852
|
await fs12.writeFile(sqlPath, migrationSql);
|
|
4830
|
-
console.log(
|
|
4853
|
+
console.log(chalk15.dim(`
|
|
4831
4854
|
Also saved to: ${sqlPath}
|
|
4832
4855
|
`));
|
|
4833
4856
|
} else {
|
|
@@ -4837,7 +4860,7 @@ Also saved to: ${sqlPath}
|
|
|
4837
4860
|
}
|
|
4838
4861
|
spinner16.stop("Migration pushed successfully!");
|
|
4839
4862
|
if (result?.stdout) {
|
|
4840
|
-
console.log(
|
|
4863
|
+
console.log(chalk15.dim(result.stdout));
|
|
4841
4864
|
}
|
|
4842
4865
|
p15.log.success("Database updated!");
|
|
4843
4866
|
} catch (error) {
|
|
@@ -4847,8 +4870,8 @@ Also saved to: ${sqlPath}
|
|
|
4847
4870
|
const migrationSql = await extractMigrationSQL(tool, errorMsg);
|
|
4848
4871
|
if (migrationSql) {
|
|
4849
4872
|
await copyToClipboard(migrationSql);
|
|
4850
|
-
console.log(
|
|
4851
|
-
console.log(
|
|
4873
|
+
console.log(chalk15.green("\n\u{1F4CB} Migration SQL copied to clipboard!\n"));
|
|
4874
|
+
console.log(chalk15.cyan(migrationSql));
|
|
4852
4875
|
}
|
|
4853
4876
|
}
|
|
4854
4877
|
}
|
|
@@ -4870,7 +4893,7 @@ async function pullSchema(tool) {
|
|
|
4870
4893
|
}
|
|
4871
4894
|
spinner16.stop("Schema pulled");
|
|
4872
4895
|
if (result?.stdout) {
|
|
4873
|
-
console.log(
|
|
4896
|
+
console.log(chalk15.dim(result.stdout));
|
|
4874
4897
|
}
|
|
4875
4898
|
} catch (error) {
|
|
4876
4899
|
spinner16.stop("Error pulling schema");
|
|
@@ -4961,7 +4984,7 @@ async function copyToClipboard(text17) {
|
|
|
4961
4984
|
|
|
4962
4985
|
// src/commands/prd-maker.ts
|
|
4963
4986
|
import * as p16 from "@clack/prompts";
|
|
4964
|
-
import
|
|
4987
|
+
import chalk16 from "chalk";
|
|
4965
4988
|
import * as fs13 from "fs-extra";
|
|
4966
4989
|
import * as path12 from "path";
|
|
4967
4990
|
import Anthropic3 from "@anthropic-ai/sdk";
|
|
@@ -4976,7 +4999,7 @@ async function prdMakerCommand() {
|
|
|
4976
4999
|
p16.log.error("Anthropic API key not configured.");
|
|
4977
5000
|
return;
|
|
4978
5001
|
}
|
|
4979
|
-
console.log(
|
|
5002
|
+
console.log(chalk16.cyan(`
|
|
4980
5003
|
\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E
|
|
4981
5004
|
\u2502 \u2502
|
|
4982
5005
|
\u2502 \u{1F4DD} CODEBAKERS PRD MAKER \u2502
|
|
@@ -5020,7 +5043,7 @@ async function prdMakerCommand() {
|
|
|
5020
5043
|
await fs13.writeFile(filepath, prd);
|
|
5021
5044
|
const jsonPath = filepath.replace(".md", ".json");
|
|
5022
5045
|
await fs13.writeJson(jsonPath, input, { spaces: 2 });
|
|
5023
|
-
console.log(
|
|
5046
|
+
console.log(chalk16.green(`
|
|
5024
5047
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
5025
5048
|
\u2551 \u2713 PRD Generated Successfully! \u2551
|
|
5026
5049
|
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
@@ -5042,9 +5065,9 @@ async function prdMakerCommand() {
|
|
|
5042
5065
|
initialValue: true
|
|
5043
5066
|
});
|
|
5044
5067
|
if (preview && !p16.isCancel(preview)) {
|
|
5045
|
-
console.log(
|
|
5068
|
+
console.log(chalk16.cyan("\n" + "\u2550".repeat(60) + "\n"));
|
|
5046
5069
|
console.log(prd);
|
|
5047
|
-
console.log(
|
|
5070
|
+
console.log(chalk16.cyan("\n" + "\u2550".repeat(60) + "\n"));
|
|
5048
5071
|
}
|
|
5049
5072
|
const nextStep = await p16.select({
|
|
5050
5073
|
message: "What would you like to do next?",
|
|
@@ -5059,10 +5082,10 @@ async function prdMakerCommand() {
|
|
|
5059
5082
|
return;
|
|
5060
5083
|
}
|
|
5061
5084
|
if (nextStep === "build") {
|
|
5062
|
-
const { prdCommand: prdCommand2 } = await import("./prd-
|
|
5085
|
+
const { prdCommand: prdCommand2 } = await import("./prd-YAUSAL5V.js");
|
|
5063
5086
|
await prdCommand2(filepath);
|
|
5064
5087
|
} else if (nextStep === "advisors") {
|
|
5065
|
-
const { advisorsCommand: advisorsCommand2 } = await import("./advisors-
|
|
5088
|
+
const { advisorsCommand: advisorsCommand2 } = await import("./advisors-3PWAN6UL.js");
|
|
5066
5089
|
await advisorsCommand2();
|
|
5067
5090
|
}
|
|
5068
5091
|
}
|
|
@@ -5090,7 +5113,7 @@ async function conductPRDInterview(inputMethod) {
|
|
|
5090
5113
|
if (p16.isCancel(response)) return null;
|
|
5091
5114
|
return response;
|
|
5092
5115
|
};
|
|
5093
|
-
console.log(
|
|
5116
|
+
console.log(chalk16.bold("\n\u{1F4CB} Let's build your PRD!\n"));
|
|
5094
5117
|
const projectName = await getInput(
|
|
5095
5118
|
"What's your project/product name?",
|
|
5096
5119
|
"My Awesome App"
|
|
@@ -5106,8 +5129,8 @@ async function conductPRDInterview(inputMethod) {
|
|
|
5106
5129
|
"Marketing managers at companies with 10-50 employees..."
|
|
5107
5130
|
);
|
|
5108
5131
|
if (!targetUsers) return null;
|
|
5109
|
-
console.log(
|
|
5110
|
-
console.log(
|
|
5132
|
+
console.log(chalk16.bold("\n\u{1F3AF} Core Features\n"));
|
|
5133
|
+
console.log(chalk16.dim('List the main features. Type each one and press Enter. Type "done" when finished.\n'));
|
|
5111
5134
|
const coreFeatures = [];
|
|
5112
5135
|
while (true) {
|
|
5113
5136
|
const feature = await getInput(
|
|
@@ -5118,8 +5141,8 @@ async function conductPRDInterview(inputMethod) {
|
|
|
5118
5141
|
if (feature.toLowerCase() === "done") break;
|
|
5119
5142
|
coreFeatures.push(feature);
|
|
5120
5143
|
}
|
|
5121
|
-
console.log(
|
|
5122
|
-
console.log(
|
|
5144
|
+
console.log(chalk16.bold("\n\u{1F464} User Stories\n"));
|
|
5145
|
+
console.log(chalk16.dim('Describe key user journeys. Type "done" when finished.\n'));
|
|
5123
5146
|
const userStories = [];
|
|
5124
5147
|
while (true) {
|
|
5125
5148
|
const story = await getInput(
|
|
@@ -5211,9 +5234,9 @@ async function checkVoiceAvailability2() {
|
|
|
5211
5234
|
return false;
|
|
5212
5235
|
}
|
|
5213
5236
|
async function getVoiceInput2(prompt) {
|
|
5214
|
-
console.log(
|
|
5237
|
+
console.log(chalk16.cyan(`
|
|
5215
5238
|
\u{1F3A4} ${prompt}`));
|
|
5216
|
-
console.log(
|
|
5239
|
+
console.log(chalk16.dim(" Press Enter to start recording, then speak. Press Enter again to stop.\n"));
|
|
5217
5240
|
const ready = await p16.confirm({
|
|
5218
5241
|
message: "Ready to record?",
|
|
5219
5242
|
initialValue: true
|
|
@@ -5235,7 +5258,7 @@ async function getVoiceInput2(prompt) {
|
|
|
5235
5258
|
}
|
|
5236
5259
|
spinner16.stop("Recording complete");
|
|
5237
5260
|
if (transcription) {
|
|
5238
|
-
console.log(
|
|
5261
|
+
console.log(chalk16.green(`
|
|
5239
5262
|
Heard: "${transcription}"
|
|
5240
5263
|
`));
|
|
5241
5264
|
const confirm13 = await p16.confirm({
|
|
@@ -5263,7 +5286,7 @@ async function getVoiceInput2(prompt) {
|
|
|
5263
5286
|
}
|
|
5264
5287
|
} catch (error) {
|
|
5265
5288
|
spinner16.stop("Recording failed");
|
|
5266
|
-
console.log(
|
|
5289
|
+
console.log(chalk16.yellow("Voice input failed. Falling back to text."));
|
|
5267
5290
|
}
|
|
5268
5291
|
const text17 = await p16.text({ message: prompt });
|
|
5269
5292
|
return p16.isCancel(text17) ? null : text17;
|
|
@@ -5291,7 +5314,7 @@ if ($result) { Write-Output $result.Text }
|
|
|
5291
5314
|
async function recordWithMacOS2() {
|
|
5292
5315
|
const tempFile = `/tmp/codebakers-voice-${Date.now()}.wav`;
|
|
5293
5316
|
try {
|
|
5294
|
-
console.log(
|
|
5317
|
+
console.log(chalk16.dim(" Recording for up to 10 seconds..."));
|
|
5295
5318
|
await execa("sox", [
|
|
5296
5319
|
"-d",
|
|
5297
5320
|
// default input device
|
|
@@ -5385,7 +5408,7 @@ async function recordWithLinux2() {
|
|
|
5385
5408
|
}
|
|
5386
5409
|
async function generatePRD(anthropic, input) {
|
|
5387
5410
|
const response = await anthropic.messages.create({
|
|
5388
|
-
model: "claude-sonnet-4-
|
|
5411
|
+
model: "claude-sonnet-4-5-20250929",
|
|
5389
5412
|
max_tokens: 8192,
|
|
5390
5413
|
messages: [{
|
|
5391
5414
|
role: "user",
|
|
@@ -5465,7 +5488,7 @@ Make it professional, detailed, and actionable. This should be ready to hand off
|
|
|
5465
5488
|
|
|
5466
5489
|
// src/commands/build.ts
|
|
5467
5490
|
import * as p17 from "@clack/prompts";
|
|
5468
|
-
import
|
|
5491
|
+
import chalk17 from "chalk";
|
|
5469
5492
|
import * as fs14 from "fs-extra";
|
|
5470
5493
|
import * as path13 from "path";
|
|
5471
5494
|
import Anthropic4 from "@anthropic-ai/sdk";
|
|
@@ -5474,33 +5497,33 @@ var displayPaused = false;
|
|
|
5474
5497
|
async function buildCommand(prdPath, options = {}) {
|
|
5475
5498
|
const config = new Config();
|
|
5476
5499
|
if (!config.isConfigured()) {
|
|
5477
|
-
console.log(
|
|
5500
|
+
console.log(chalk17.yellow(`
|
|
5478
5501
|
\u26A0\uFE0F CodeBakers isn't set up yet.
|
|
5479
5502
|
|
|
5480
5503
|
Run this first:
|
|
5481
|
-
${
|
|
5504
|
+
${chalk17.cyan("codebakers setup")}
|
|
5482
5505
|
`));
|
|
5483
5506
|
return;
|
|
5484
5507
|
}
|
|
5485
5508
|
const anthropicCreds = config.getCredentials("anthropic");
|
|
5486
5509
|
if (!anthropicCreds?.apiKey) {
|
|
5487
|
-
console.log(
|
|
5510
|
+
console.log(chalk17.yellow(`
|
|
5488
5511
|
\u26A0\uFE0F Anthropic API key not configured.
|
|
5489
5512
|
|
|
5490
5513
|
The parallel build needs Claude AI to work.
|
|
5491
5514
|
|
|
5492
5515
|
Run this to add your API key:
|
|
5493
|
-
${
|
|
5516
|
+
${chalk17.cyan("codebakers setup")}
|
|
5494
5517
|
`));
|
|
5495
5518
|
return;
|
|
5496
5519
|
}
|
|
5497
5520
|
let prdFile = prdPath;
|
|
5498
5521
|
if (!prdFile) {
|
|
5499
|
-
console.log(
|
|
5522
|
+
console.log(chalk17.dim(`
|
|
5500
5523
|
A PRD (Product Requirements Document) describes what you want to build.
|
|
5501
5524
|
|
|
5502
5525
|
Don't have one? Create one with:
|
|
5503
|
-
${
|
|
5526
|
+
${chalk17.cyan("codebakers prd-maker")}
|
|
5504
5527
|
`));
|
|
5505
5528
|
const file = await p17.text({
|
|
5506
5529
|
message: "Path to PRD file:",
|
|
@@ -5511,16 +5534,16 @@ async function buildCommand(prdPath, options = {}) {
|
|
|
5511
5534
|
prdFile = file;
|
|
5512
5535
|
}
|
|
5513
5536
|
if (!await fs14.pathExists(prdFile)) {
|
|
5514
|
-
console.log(
|
|
5537
|
+
console.log(chalk17.red(`
|
|
5515
5538
|
\u274C PRD file not found: ${prdFile}
|
|
5516
5539
|
|
|
5517
5540
|
Make sure the file exists, or create one:
|
|
5518
|
-
${
|
|
5541
|
+
${chalk17.cyan("codebakers prd-maker")}
|
|
5519
5542
|
`));
|
|
5520
5543
|
return;
|
|
5521
5544
|
}
|
|
5522
5545
|
const prdContent = await fs14.readFile(prdFile, "utf-8");
|
|
5523
|
-
console.log(
|
|
5546
|
+
console.log(chalk17.cyan(`
|
|
5524
5547
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
5525
5548
|
\u2551 \u{1F680} CODEBAKERS PARALLEL BUILD \u2551
|
|
5526
5549
|
\u2551 \u2551
|
|
@@ -5541,7 +5564,7 @@ async function buildCommand(prdPath, options = {}) {
|
|
|
5541
5564
|
const totalAgents = buildPlan.waves.reduce((sum, w) => sum + w.agents.length, 0);
|
|
5542
5565
|
const useParallel = !options.sequential && totalAgents > 2;
|
|
5543
5566
|
if (!useParallel) {
|
|
5544
|
-
console.log(
|
|
5567
|
+
console.log(chalk17.dim("\nUsing sequential build (parallel not needed for small projects)\n"));
|
|
5545
5568
|
}
|
|
5546
5569
|
const proceed = await p17.confirm({
|
|
5547
5570
|
message: `Start ${useParallel ? "parallel" : "sequential"} build?`,
|
|
@@ -5574,12 +5597,17 @@ async function buildCommand(prdPath, options = {}) {
|
|
|
5574
5597
|
}
|
|
5575
5598
|
await runIntegrationPhase(anthropic, buildPlan, projectPath);
|
|
5576
5599
|
spinner16.start("Installing dependencies...");
|
|
5577
|
-
|
|
5578
|
-
|
|
5600
|
+
try {
|
|
5601
|
+
await execa9("npm", ["install"], { cwd: projectPath, stdio: "inherit" });
|
|
5602
|
+
spinner16.stop("Dependencies installed");
|
|
5603
|
+
} catch (error) {
|
|
5604
|
+
spinner16.stop("Dependencies installation failed");
|
|
5605
|
+
console.log(chalk17.yellow(' \u26A0\uFE0F Run "npm install" manually in the project folder'));
|
|
5606
|
+
}
|
|
5579
5607
|
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
5580
5608
|
const minutes = Math.floor(elapsed / 60);
|
|
5581
5609
|
const seconds = elapsed % 60;
|
|
5582
|
-
console.log(
|
|
5610
|
+
console.log(chalk17.green(`
|
|
5583
5611
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
5584
5612
|
\u2551 \u2705 BUILD COMPLETE \u2551
|
|
5585
5613
|
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
@@ -5597,7 +5625,7 @@ async function buildCommand(prdPath, options = {}) {
|
|
|
5597
5625
|
}
|
|
5598
5626
|
async function analyzePRD(anthropic, prdContent) {
|
|
5599
5627
|
const response = await anthropic.messages.create({
|
|
5600
|
-
model: "claude-sonnet-4-
|
|
5628
|
+
model: "claude-sonnet-4-5-20250929",
|
|
5601
5629
|
max_tokens: 4096,
|
|
5602
5630
|
messages: [{
|
|
5603
5631
|
role: "user",
|
|
@@ -5665,24 +5693,24 @@ Think about:
|
|
|
5665
5693
|
return plan;
|
|
5666
5694
|
}
|
|
5667
5695
|
function displayBuildPlan(plan) {
|
|
5668
|
-
console.log(
|
|
5696
|
+
console.log(chalk17.bold(`
|
|
5669
5697
|
\u{1F4CB} Build Plan: ${plan.projectName}
|
|
5670
5698
|
`));
|
|
5671
|
-
console.log(
|
|
5699
|
+
console.log(chalk17.dim(` ${plan.description}
|
|
5672
5700
|
`));
|
|
5673
5701
|
for (const wave of plan.waves) {
|
|
5674
5702
|
const parallel = wave.parallel && wave.agents.length > 1;
|
|
5675
|
-
const mode = parallel ?
|
|
5676
|
-
console.log(
|
|
5703
|
+
const mode = parallel ? chalk17.green("parallel") : chalk17.yellow("sequential");
|
|
5704
|
+
console.log(chalk17.bold(` Wave ${wave.wave} (${mode}):`));
|
|
5677
5705
|
for (const agent of wave.agents) {
|
|
5678
|
-
const deps = agent.dependencies.length > 0 ?
|
|
5706
|
+
const deps = agent.dependencies.length > 0 ? chalk17.dim(` \u2190 needs: ${agent.dependencies.join(", ")}`) : "";
|
|
5679
5707
|
console.log(` \u2022 ${agent.name} ${deps}`);
|
|
5680
5708
|
}
|
|
5681
5709
|
console.log("");
|
|
5682
5710
|
}
|
|
5683
5711
|
const totalAgents = plan.waves.reduce((sum, w) => sum + w.agents.length, 0);
|
|
5684
5712
|
const parallelWaves = plan.waves.filter((w) => w.parallel && w.agents.length > 1).length;
|
|
5685
|
-
console.log(
|
|
5713
|
+
console.log(chalk17.dim(` Total: ${totalAgents} features, ${plan.waves.length} waves, ${parallelWaves} parallel
|
|
5686
5714
|
`));
|
|
5687
5715
|
}
|
|
5688
5716
|
async function runSetupPhase(anthropic, plan, projectPath) {
|
|
@@ -5695,7 +5723,7 @@ async function runSetupPhase(anthropic, plan, projectPath) {
|
|
|
5695
5723
|
await fs14.ensureDir(path13.join(projectPath, "src/features"));
|
|
5696
5724
|
await fs14.ensureDir(path13.join(projectPath, ".codebakers"));
|
|
5697
5725
|
const setupResponse = await anthropic.messages.create({
|
|
5698
|
-
model: "claude-sonnet-4-
|
|
5726
|
+
model: "claude-sonnet-4-5-20250929",
|
|
5699
5727
|
max_tokens: 8192,
|
|
5700
5728
|
messages: [{
|
|
5701
5729
|
role: "user",
|
|
@@ -5735,14 +5763,14 @@ Use TypeScript. Include all necessary imports.`
|
|
|
5735
5763
|
}
|
|
5736
5764
|
async function executeParallelBuild(anthropic, plan, projectPath, config) {
|
|
5737
5765
|
for (const wave of plan.waves) {
|
|
5738
|
-
console.log(
|
|
5766
|
+
console.log(chalk17.bold(`
|
|
5739
5767
|
\u{1F3D7}\uFE0F Wave ${wave.wave} of ${plan.waves.length}`));
|
|
5740
5768
|
if (wave.parallel && wave.agents.length > 1) {
|
|
5741
|
-
console.log(
|
|
5769
|
+
console.log(chalk17.dim(` Running ${wave.agents.length} agents in parallel
|
|
5742
5770
|
`));
|
|
5743
5771
|
await executeWaveParallel(anthropic, wave.agents, projectPath, plan);
|
|
5744
5772
|
} else {
|
|
5745
|
-
console.log(
|
|
5773
|
+
console.log(chalk17.dim(` Running sequentially
|
|
5746
5774
|
`));
|
|
5747
5775
|
for (const agent of wave.agents) {
|
|
5748
5776
|
await executeAgent(anthropic, agent, projectPath, plan);
|
|
@@ -5887,7 +5915,7 @@ Start with the index.ts that exports everything.`
|
|
|
5887
5915
|
while (iteration < maxIterations) {
|
|
5888
5916
|
iteration++;
|
|
5889
5917
|
const response = await anthropic.messages.create({
|
|
5890
|
-
model: "claude-sonnet-4-
|
|
5918
|
+
model: "claude-sonnet-4-5-20250929",
|
|
5891
5919
|
max_tokens: 8192,
|
|
5892
5920
|
messages
|
|
5893
5921
|
});
|
|
@@ -5943,11 +5971,11 @@ async function askUserQuestion(agent, question, onProgress) {
|
|
|
5943
5971
|
agent.status = "asking";
|
|
5944
5972
|
if (onProgress) onProgress(agent.progress, "Waiting for your input...");
|
|
5945
5973
|
console.log("\n");
|
|
5946
|
-
console.log(
|
|
5947
|
-
console.log(
|
|
5948
|
-
console.log(
|
|
5974
|
+
console.log(chalk17.cyan(` \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
|
|
5975
|
+
console.log(chalk17.cyan(` \u2502 \u{1F916} ${agent.name} needs your input`));
|
|
5976
|
+
console.log(chalk17.cyan(` \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
|
|
5949
5977
|
if (question.context) {
|
|
5950
|
-
console.log(
|
|
5978
|
+
console.log(chalk17.dim(` ${question.context}
|
|
5951
5979
|
`));
|
|
5952
5980
|
}
|
|
5953
5981
|
const answer = await p17.select({
|
|
@@ -5955,12 +5983,12 @@ async function askUserQuestion(agent, question, onProgress) {
|
|
|
5955
5983
|
options: question.options.map((o) => ({ value: o, label: o }))
|
|
5956
5984
|
});
|
|
5957
5985
|
if (p17.isCancel(answer)) {
|
|
5958
|
-
console.log(
|
|
5986
|
+
console.log(chalk17.yellow(` Using default: ${question.options[0]}`));
|
|
5959
5987
|
agent.status = previousStatus;
|
|
5960
5988
|
displayPaused = false;
|
|
5961
5989
|
return question.options[0];
|
|
5962
5990
|
}
|
|
5963
|
-
console.log(
|
|
5991
|
+
console.log(chalk17.green(` \u2713 Got it: ${answer}
|
|
5964
5992
|
`));
|
|
5965
5993
|
agent.status = previousStatus;
|
|
5966
5994
|
displayPaused = false;
|
|
@@ -5968,7 +5996,7 @@ async function askUserQuestion(agent, question, onProgress) {
|
|
|
5968
5996
|
}
|
|
5969
5997
|
async function healerAgent(anthropic, agent, error, projectPath, plan) {
|
|
5970
5998
|
const response = await anthropic.messages.create({
|
|
5971
|
-
model: "claude-sonnet-4-
|
|
5999
|
+
model: "claude-sonnet-4-5-20250929",
|
|
5972
6000
|
max_tokens: 4096,
|
|
5973
6001
|
messages: [{
|
|
5974
6002
|
role: "user",
|
|
@@ -6022,7 +6050,7 @@ async function runIntegrationPhase(anthropic, plan, projectPath) {
|
|
|
6022
6050
|
spinner16.start("Running integration...");
|
|
6023
6051
|
const features = plan.waves.flatMap((w) => w.agents);
|
|
6024
6052
|
const response = await anthropic.messages.create({
|
|
6025
|
-
model: "claude-sonnet-4-
|
|
6053
|
+
model: "claude-sonnet-4-5-20250929",
|
|
6026
6054
|
max_tokens: 8192,
|
|
6027
6055
|
messages: [{
|
|
6028
6056
|
role: "user",
|
|
@@ -6059,7 +6087,7 @@ async function mergeWaveBranches(agents, projectPath) {
|
|
|
6059
6087
|
await execa9("git", ["merge", agent.branch, "--no-edit"], { cwd: projectPath });
|
|
6060
6088
|
await execa9("git", ["branch", "-d", agent.branch], { cwd: projectPath, reject: false });
|
|
6061
6089
|
} catch (error) {
|
|
6062
|
-
console.log(
|
|
6090
|
+
console.log(chalk17.yellow(` Warning: Merge issue with ${agent.name}, continuing...`));
|
|
6063
6091
|
await execa9("git", ["merge", "--abort"], { cwd: projectPath, reject: false });
|
|
6064
6092
|
}
|
|
6065
6093
|
}
|
|
@@ -6108,7 +6136,7 @@ var ProgressDisplay = class {
|
|
|
6108
6136
|
for (const agent of this.agents) {
|
|
6109
6137
|
const icon = this.getStatusIcon(agent.status);
|
|
6110
6138
|
const bar = this.getProgressBar(agent.progress);
|
|
6111
|
-
const action = agent.currentAction ?
|
|
6139
|
+
const action = agent.currentAction ? chalk17.dim(` ${agent.currentAction}`) : "";
|
|
6112
6140
|
console.log(` ${icon} ${agent.name.padEnd(15)} ${bar} ${agent.progress.toString().padStart(3)}%${action}`);
|
|
6113
6141
|
}
|
|
6114
6142
|
console.log("");
|
|
@@ -6117,17 +6145,17 @@ var ProgressDisplay = class {
|
|
|
6117
6145
|
getStatusIcon(status) {
|
|
6118
6146
|
switch (status) {
|
|
6119
6147
|
case "waiting":
|
|
6120
|
-
return
|
|
6148
|
+
return chalk17.gray("\u25CB");
|
|
6121
6149
|
case "running":
|
|
6122
|
-
return
|
|
6150
|
+
return chalk17.blue("\u25CF");
|
|
6123
6151
|
case "healing":
|
|
6124
|
-
return
|
|
6152
|
+
return chalk17.yellow("\u2695");
|
|
6125
6153
|
case "asking":
|
|
6126
|
-
return
|
|
6154
|
+
return chalk17.magenta("?");
|
|
6127
6155
|
case "done":
|
|
6128
|
-
return
|
|
6156
|
+
return chalk17.green("\u2713");
|
|
6129
6157
|
case "error":
|
|
6130
|
-
return
|
|
6158
|
+
return chalk17.red("\u2717");
|
|
6131
6159
|
default:
|
|
6132
6160
|
return "?";
|
|
6133
6161
|
}
|
|
@@ -6136,7 +6164,7 @@ var ProgressDisplay = class {
|
|
|
6136
6164
|
const width = 20;
|
|
6137
6165
|
const filled = Math.round(progress / 100 * width);
|
|
6138
6166
|
const empty = width - filled;
|
|
6139
|
-
return
|
|
6167
|
+
return chalk17.green("\u2588".repeat(filled)) + chalk17.gray("\u2591".repeat(empty));
|
|
6140
6168
|
}
|
|
6141
6169
|
};
|
|
6142
6170
|
async function writeFilesFromResponse(text17, projectPath) {
|
|
@@ -6158,7 +6186,7 @@ function sleep(ms) {
|
|
|
6158
6186
|
|
|
6159
6187
|
// src/commands/integrate.ts
|
|
6160
6188
|
import * as p18 from "@clack/prompts";
|
|
6161
|
-
import
|
|
6189
|
+
import chalk18 from "chalk";
|
|
6162
6190
|
import * as fs15 from "fs-extra";
|
|
6163
6191
|
import * as path14 from "path";
|
|
6164
6192
|
import open2 from "open";
|
|
@@ -6695,7 +6723,7 @@ var INTEGRATIONS = [
|
|
|
6695
6723
|
}
|
|
6696
6724
|
];
|
|
6697
6725
|
async function integrateCommand(integrationId) {
|
|
6698
|
-
console.log(
|
|
6726
|
+
console.log(chalk18.cyan(`
|
|
6699
6727
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
6700
6728
|
\u2551 \u{1F50C} ONE-CLICK INTEGRATIONS \u2551
|
|
6701
6729
|
\u2551 \u2551
|
|
@@ -6706,7 +6734,7 @@ async function integrateCommand(integrationId) {
|
|
|
6706
6734
|
const integration2 = INTEGRATIONS.find((i) => i.id === integrationId);
|
|
6707
6735
|
if (!integration2) {
|
|
6708
6736
|
p18.log.error(`Unknown integration: ${integrationId}`);
|
|
6709
|
-
console.log(
|
|
6737
|
+
console.log(chalk18.dim(`
|
|
6710
6738
|
Available: ${INTEGRATIONS.map((i) => i.id).join(", ")}`));
|
|
6711
6739
|
return;
|
|
6712
6740
|
}
|
|
@@ -6771,7 +6799,7 @@ Available: ${INTEGRATIONS.map((i) => i.id).join(", ")}`));
|
|
|
6771
6799
|
await installIntegration(integration);
|
|
6772
6800
|
}
|
|
6773
6801
|
async function installIntegration(integration) {
|
|
6774
|
-
console.log(
|
|
6802
|
+
console.log(chalk18.cyan(`
|
|
6775
6803
|
\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
6776
6804
|
\u2502 ${integration.icon} Installing ${integration.name}
|
|
6777
6805
|
\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
@@ -6784,21 +6812,21 @@ async function installIntegration(integration) {
|
|
|
6784
6812
|
cwd: process.cwd(),
|
|
6785
6813
|
reject: false
|
|
6786
6814
|
});
|
|
6787
|
-
spinner17.stop(
|
|
6815
|
+
spinner17.stop(chalk18.green("\u2713 Packages installed"));
|
|
6788
6816
|
} catch {
|
|
6789
|
-
spinner17.stop(
|
|
6817
|
+
spinner17.stop(chalk18.yellow("\u26A0 Package install had issues (may already be installed)"));
|
|
6790
6818
|
}
|
|
6791
6819
|
}
|
|
6792
6820
|
if (integration.envVars.length > 0) {
|
|
6793
|
-
console.log(
|
|
6821
|
+
console.log(chalk18.cyan(`
|
|
6794
6822
|
\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
6795
6823
|
\u2502 \u{1F4CB} HOW TO GET YOUR API KEYS
|
|
6796
6824
|
\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
6797
6825
|
`));
|
|
6798
6826
|
integration.steps.forEach((step, i) => {
|
|
6799
|
-
console.log(
|
|
6827
|
+
console.log(chalk18.white(` ${i + 1}. ${step}`));
|
|
6800
6828
|
});
|
|
6801
|
-
console.log(
|
|
6829
|
+
console.log(chalk18.dim(`
|
|
6802
6830
|
Dashboard: ${integration.dashboardUrl}
|
|
6803
6831
|
Docs: ${integration.docs}
|
|
6804
6832
|
`));
|
|
@@ -6808,19 +6836,19 @@ async function installIntegration(integration) {
|
|
|
6808
6836
|
});
|
|
6809
6837
|
if (openDashboard && !p18.isCancel(openDashboard)) {
|
|
6810
6838
|
await open2(integration.dashboardUrl);
|
|
6811
|
-
console.log(
|
|
6839
|
+
console.log(chalk18.dim(`
|
|
6812
6840
|
\u2713 Browser opened! Get your keys and come back.
|
|
6813
6841
|
`));
|
|
6814
6842
|
await sleep2(2e3);
|
|
6815
6843
|
}
|
|
6816
|
-
console.log(
|
|
6844
|
+
console.log(chalk18.cyan(`
|
|
6817
6845
|
Enter your credentials:
|
|
6818
6846
|
`));
|
|
6819
6847
|
const credentials = {};
|
|
6820
6848
|
for (const envVar of integration.envVars) {
|
|
6821
6849
|
const hint = integration.envVarHints?.[envVar] || "Paste here...";
|
|
6822
6850
|
const isPublic = envVar.startsWith("NEXT_PUBLIC_");
|
|
6823
|
-
const label = isPublic ?
|
|
6851
|
+
const label = isPublic ? chalk18.yellow("(public)") : chalk18.green("(secret)");
|
|
6824
6852
|
const value = await p18.text({
|
|
6825
6853
|
message: `${envVar} ${label}`,
|
|
6826
6854
|
placeholder: hint,
|
|
@@ -6830,15 +6858,15 @@ async function installIntegration(integration) {
|
|
|
6830
6858
|
credentials[envVar] = value;
|
|
6831
6859
|
}
|
|
6832
6860
|
await saveEnvVars(credentials);
|
|
6833
|
-
console.log(
|
|
6861
|
+
console.log(chalk18.green(`
|
|
6834
6862
|
\u2713 Saved to .env.local
|
|
6835
6863
|
`));
|
|
6836
6864
|
}
|
|
6837
6865
|
const spinner16 = p18.spinner();
|
|
6838
6866
|
spinner16.start("Creating setup file...");
|
|
6839
6867
|
await generateSetupCode(integration);
|
|
6840
|
-
spinner16.stop(
|
|
6841
|
-
console.log(
|
|
6868
|
+
spinner16.stop(chalk18.green("\u2713 Setup complete"));
|
|
6869
|
+
console.log(chalk18.green(`
|
|
6842
6870
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
6843
6871
|
\u2551 \u2705 ${integration.name} installed!
|
|
6844
6872
|
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
@@ -6951,6 +6979,233 @@ import * as fs16 from "fs-extra";
|
|
|
6951
6979
|
import * as path15 from "path";
|
|
6952
6980
|
import Anthropic5 from "@anthropic-ai/sdk";
|
|
6953
6981
|
import { execa as execa11 } from "execa";
|
|
6982
|
+
|
|
6983
|
+
// src/utils/display.ts
|
|
6984
|
+
import chalk19 from "chalk";
|
|
6985
|
+
var StepTracker = class {
|
|
6986
|
+
steps;
|
|
6987
|
+
currentIndex = -1;
|
|
6988
|
+
startTime = Date.now();
|
|
6989
|
+
constructor(stepNames) {
|
|
6990
|
+
this.steps = stepNames.map((name) => ({ name, status: "pending" }));
|
|
6991
|
+
}
|
|
6992
|
+
start(index) {
|
|
6993
|
+
if (index !== void 0) {
|
|
6994
|
+
this.currentIndex = index;
|
|
6995
|
+
} else {
|
|
6996
|
+
this.currentIndex++;
|
|
6997
|
+
}
|
|
6998
|
+
if (this.currentIndex < this.steps.length) {
|
|
6999
|
+
this.steps[this.currentIndex].status = "running";
|
|
7000
|
+
}
|
|
7001
|
+
this.render();
|
|
7002
|
+
}
|
|
7003
|
+
complete() {
|
|
7004
|
+
if (this.currentIndex >= 0 && this.currentIndex < this.steps.length) {
|
|
7005
|
+
this.steps[this.currentIndex].status = "done";
|
|
7006
|
+
}
|
|
7007
|
+
this.render();
|
|
7008
|
+
}
|
|
7009
|
+
error() {
|
|
7010
|
+
if (this.currentIndex >= 0 && this.currentIndex < this.steps.length) {
|
|
7011
|
+
this.steps[this.currentIndex].status = "error";
|
|
7012
|
+
}
|
|
7013
|
+
this.render();
|
|
7014
|
+
}
|
|
7015
|
+
skip() {
|
|
7016
|
+
if (this.currentIndex >= 0 && this.currentIndex < this.steps.length) {
|
|
7017
|
+
this.steps[this.currentIndex].status = "skipped";
|
|
7018
|
+
}
|
|
7019
|
+
this.render();
|
|
7020
|
+
}
|
|
7021
|
+
render() {
|
|
7022
|
+
const output = [];
|
|
7023
|
+
output.push("");
|
|
7024
|
+
for (let i = 0; i < this.steps.length; i++) {
|
|
7025
|
+
const step = this.steps[i];
|
|
7026
|
+
const icon = this.getIcon(step.status);
|
|
7027
|
+
const color = this.getColor(step.status);
|
|
7028
|
+
const suffix = step.status === "running" ? chalk19.dim(" ...") : "";
|
|
7029
|
+
output.push(` ${icon} ${color(step.name)}${suffix}`);
|
|
7030
|
+
}
|
|
7031
|
+
const completed = this.steps.filter((s) => s.status === "done").length;
|
|
7032
|
+
const total = this.steps.length;
|
|
7033
|
+
const percent = Math.round(completed / total * 100);
|
|
7034
|
+
const barWidth = 30;
|
|
7035
|
+
const filled = Math.round(completed / total * barWidth);
|
|
7036
|
+
const empty = barWidth - filled;
|
|
7037
|
+
output.push("");
|
|
7038
|
+
output.push(` ${chalk19.green("\u2588".repeat(filled))}${chalk19.gray("\u2591".repeat(empty))} ${percent}%`);
|
|
7039
|
+
output.push("");
|
|
7040
|
+
console.log(output.join("\n"));
|
|
7041
|
+
}
|
|
7042
|
+
getIcon(status) {
|
|
7043
|
+
switch (status) {
|
|
7044
|
+
case "pending":
|
|
7045
|
+
return chalk19.gray("\u25CB");
|
|
7046
|
+
case "running":
|
|
7047
|
+
return chalk19.blue("\u25CF");
|
|
7048
|
+
case "done":
|
|
7049
|
+
return chalk19.green("\u2713");
|
|
7050
|
+
case "error":
|
|
7051
|
+
return chalk19.red("\u2717");
|
|
7052
|
+
case "skipped":
|
|
7053
|
+
return chalk19.yellow("\u2298");
|
|
7054
|
+
}
|
|
7055
|
+
}
|
|
7056
|
+
getColor(status) {
|
|
7057
|
+
switch (status) {
|
|
7058
|
+
case "pending":
|
|
7059
|
+
return chalk19.gray;
|
|
7060
|
+
case "running":
|
|
7061
|
+
return chalk19.white;
|
|
7062
|
+
case "done":
|
|
7063
|
+
return chalk19.green;
|
|
7064
|
+
case "error":
|
|
7065
|
+
return chalk19.red;
|
|
7066
|
+
case "skipped":
|
|
7067
|
+
return chalk19.yellow;
|
|
7068
|
+
}
|
|
7069
|
+
}
|
|
7070
|
+
getElapsedTime() {
|
|
7071
|
+
const elapsed = Math.round((Date.now() - this.startTime) / 1e3);
|
|
7072
|
+
const minutes = Math.floor(elapsed / 60);
|
|
7073
|
+
const seconds = elapsed % 60;
|
|
7074
|
+
return minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
|
|
7075
|
+
}
|
|
7076
|
+
};
|
|
7077
|
+
function showError(error) {
|
|
7078
|
+
console.log("");
|
|
7079
|
+
console.log(chalk19.red(` \u274C ${error.title}`));
|
|
7080
|
+
console.log("");
|
|
7081
|
+
console.log(chalk19.white(` What went wrong:`));
|
|
7082
|
+
console.log(chalk19.gray(` ${error.message}`));
|
|
7083
|
+
if (error.fixes && error.fixes.length > 0) {
|
|
7084
|
+
console.log("");
|
|
7085
|
+
console.log(chalk19.white(` Possible fixes:`));
|
|
7086
|
+
error.fixes.forEach((fix, i) => {
|
|
7087
|
+
console.log(chalk19.gray(` ${i + 1}. ${fix}`));
|
|
7088
|
+
});
|
|
7089
|
+
}
|
|
7090
|
+
if (error.command) {
|
|
7091
|
+
console.log("");
|
|
7092
|
+
console.log(chalk19.white(` Try running:`));
|
|
7093
|
+
console.log(chalk19.cyan(` ${error.command}`));
|
|
7094
|
+
}
|
|
7095
|
+
if (error.docs) {
|
|
7096
|
+
console.log("");
|
|
7097
|
+
console.log(chalk19.dim(` Docs: ${error.docs}`));
|
|
7098
|
+
}
|
|
7099
|
+
console.log("");
|
|
7100
|
+
}
|
|
7101
|
+
function showSuccess(success) {
|
|
7102
|
+
console.log("");
|
|
7103
|
+
console.log(chalk19.green(` \u2705 ${success.title}`));
|
|
7104
|
+
if (success.message) {
|
|
7105
|
+
console.log(chalk19.gray(` ${success.message}`));
|
|
7106
|
+
}
|
|
7107
|
+
if (success.stats && success.stats.length > 0) {
|
|
7108
|
+
console.log("");
|
|
7109
|
+
console.log(chalk19.white(` \u{1F4CA} Summary:`));
|
|
7110
|
+
success.stats.forEach((stat2) => {
|
|
7111
|
+
console.log(chalk19.gray(` ${stat2.label}: ${chalk19.white(stat2.value)}`));
|
|
7112
|
+
});
|
|
7113
|
+
}
|
|
7114
|
+
if (success.nextSteps && success.nextSteps.length > 0) {
|
|
7115
|
+
console.log("");
|
|
7116
|
+
console.log(chalk19.white(` Next steps:`));
|
|
7117
|
+
success.nextSteps.forEach((step) => {
|
|
7118
|
+
console.log(chalk19.cyan(` ${step}`));
|
|
7119
|
+
});
|
|
7120
|
+
}
|
|
7121
|
+
if (success.command) {
|
|
7122
|
+
console.log("");
|
|
7123
|
+
console.log(chalk19.white(` Quick start:`));
|
|
7124
|
+
console.log(chalk19.cyan(` ${success.command}`));
|
|
7125
|
+
}
|
|
7126
|
+
console.log("");
|
|
7127
|
+
}
|
|
7128
|
+
function showFileList(title, files) {
|
|
7129
|
+
console.log("");
|
|
7130
|
+
console.log(chalk19.white(` \u{1F4C1} ${title}`));
|
|
7131
|
+
files.forEach((file, i) => {
|
|
7132
|
+
const isLast = i === files.length - 1;
|
|
7133
|
+
const prefix = isLast ? "\u2514\u2500\u2500" : "\u251C\u2500\u2500";
|
|
7134
|
+
const icon = getFileIcon(file);
|
|
7135
|
+
console.log(chalk19.gray(` ${prefix} ${icon} ${file}`));
|
|
7136
|
+
});
|
|
7137
|
+
console.log("");
|
|
7138
|
+
}
|
|
7139
|
+
function getFileIcon(filename) {
|
|
7140
|
+
const ext = filename.split(".").pop()?.toLowerCase();
|
|
7141
|
+
const icons = {
|
|
7142
|
+
"tsx": "\u269B\uFE0F",
|
|
7143
|
+
"ts": "\u{1F4D8}",
|
|
7144
|
+
"js": "\u{1F4D2}",
|
|
7145
|
+
"jsx": "\u269B\uFE0F",
|
|
7146
|
+
"css": "\u{1F3A8}",
|
|
7147
|
+
"json": "\u{1F4CB}",
|
|
7148
|
+
"md": "\u{1F4DD}",
|
|
7149
|
+
"html": "\u{1F310}"
|
|
7150
|
+
};
|
|
7151
|
+
return icons[ext || ""] || "\u{1F4C4}";
|
|
7152
|
+
}
|
|
7153
|
+
var ERRORS = {
|
|
7154
|
+
nodeNotInstalled: {
|
|
7155
|
+
title: "Node.js not found",
|
|
7156
|
+
message: "Node.js 18 or higher is required",
|
|
7157
|
+
fixes: [
|
|
7158
|
+
"Install Node.js from https://nodejs.org",
|
|
7159
|
+
"Use nvm to install: nvm install 18",
|
|
7160
|
+
"Restart your terminal after installing"
|
|
7161
|
+
],
|
|
7162
|
+
docs: "https://nodejs.org/en/download"
|
|
7163
|
+
},
|
|
7164
|
+
npmFailed: {
|
|
7165
|
+
title: "Package installation failed",
|
|
7166
|
+
message: "npm install encountered an error",
|
|
7167
|
+
fixes: [
|
|
7168
|
+
"Check your internet connection",
|
|
7169
|
+
"Clear npm cache: npm cache clean --force",
|
|
7170
|
+
"Delete node_modules and try again",
|
|
7171
|
+
"Try using yarn instead: yarn install"
|
|
7172
|
+
]
|
|
7173
|
+
},
|
|
7174
|
+
createNextAppFailed: {
|
|
7175
|
+
title: "Project creation failed",
|
|
7176
|
+
message: "create-next-app could not complete",
|
|
7177
|
+
fixes: [
|
|
7178
|
+
"Make sure Node.js 18+ is installed",
|
|
7179
|
+
"Check your internet connection",
|
|
7180
|
+
"Try running manually: npx create-next-app@latest"
|
|
7181
|
+
]
|
|
7182
|
+
},
|
|
7183
|
+
apiKeyMissing: {
|
|
7184
|
+
title: "API key not configured",
|
|
7185
|
+
message: "Anthropic API key is required for AI features",
|
|
7186
|
+
fixes: [
|
|
7187
|
+
"Run: codebakers setup",
|
|
7188
|
+
"Get an API key at: https://console.anthropic.com"
|
|
7189
|
+
],
|
|
7190
|
+
command: "codebakers setup"
|
|
7191
|
+
},
|
|
7192
|
+
notConfigured: {
|
|
7193
|
+
title: "CodeBakers not configured",
|
|
7194
|
+
message: "Run setup before using this command",
|
|
7195
|
+
command: "codebakers setup"
|
|
7196
|
+
},
|
|
7197
|
+
notInProject: {
|
|
7198
|
+
title: "Not in a project folder",
|
|
7199
|
+
message: "This command must be run inside a project",
|
|
7200
|
+
fixes: [
|
|
7201
|
+
"Navigate to your project: cd my-project",
|
|
7202
|
+
"Create a new project: codebakers init",
|
|
7203
|
+
"Or build a website: codebakers website"
|
|
7204
|
+
]
|
|
7205
|
+
}
|
|
7206
|
+
};
|
|
7207
|
+
|
|
7208
|
+
// src/commands/website.ts
|
|
6954
7209
|
var TEMPLATES = [
|
|
6955
7210
|
{
|
|
6956
7211
|
id: "landing",
|
|
@@ -7140,7 +7395,7 @@ async function describeWebsite(anthropic) {
|
|
|
7140
7395
|
const spinner16 = p19.spinner();
|
|
7141
7396
|
spinner16.start("Understanding your vision...");
|
|
7142
7397
|
const response = await anthropic.messages.create({
|
|
7143
|
-
model: "claude-sonnet-4-
|
|
7398
|
+
model: "claude-sonnet-4-5-20250929",
|
|
7144
7399
|
max_tokens: 2048,
|
|
7145
7400
|
messages: [{
|
|
7146
7401
|
role: "user",
|
|
@@ -7216,7 +7471,7 @@ async function templateWebsite(anthropic) {
|
|
|
7216
7471
|
const spinner16 = p19.spinner();
|
|
7217
7472
|
spinner16.start("Customizing template...");
|
|
7218
7473
|
const response = await anthropic.messages.create({
|
|
7219
|
-
model: "claude-sonnet-4-
|
|
7474
|
+
model: "claude-sonnet-4-5-20250929",
|
|
7220
7475
|
max_tokens: 2048,
|
|
7221
7476
|
messages: [{
|
|
7222
7477
|
role: "user",
|
|
@@ -7280,7 +7535,7 @@ async function cloneDesign(anthropic) {
|
|
|
7280
7535
|
const spinner16 = p19.spinner();
|
|
7281
7536
|
spinner16.start("Analyzing design inspiration...");
|
|
7282
7537
|
const response = await anthropic.messages.create({
|
|
7283
|
-
model: "claude-sonnet-4-
|
|
7538
|
+
model: "claude-sonnet-4-5-20250929",
|
|
7284
7539
|
max_tokens: 2048,
|
|
7285
7540
|
messages: [{
|
|
7286
7541
|
role: "user",
|
|
@@ -7333,36 +7588,95 @@ async function buildWebsite(anthropic, spec, config) {
|
|
|
7333
7588
|
await fs16.remove(projectPath);
|
|
7334
7589
|
}
|
|
7335
7590
|
console.log(chalk20.cyan(`
|
|
7336
|
-
\u{1F3D7}\uFE0F Building ${spec.name}
|
|
7591
|
+
\u{1F3D7}\uFE0F Building ${chalk20.bold(spec.name)}
|
|
7337
7592
|
`));
|
|
7338
|
-
const
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
"
|
|
7342
|
-
|
|
7343
|
-
"
|
|
7344
|
-
"
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
"
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7593
|
+
const steps = new StepTracker([
|
|
7594
|
+
"Create project structure",
|
|
7595
|
+
"Install dependencies",
|
|
7596
|
+
"Set up UI components",
|
|
7597
|
+
"Generate website code",
|
|
7598
|
+
"Create additional pages",
|
|
7599
|
+
"Initialize git repository"
|
|
7600
|
+
]);
|
|
7601
|
+
const createdFiles = [];
|
|
7602
|
+
steps.start();
|
|
7603
|
+
try {
|
|
7604
|
+
await execa11("npx", [
|
|
7605
|
+
"create-next-app@latest",
|
|
7606
|
+
spec.name,
|
|
7607
|
+
"--typescript",
|
|
7608
|
+
"--tailwind",
|
|
7609
|
+
"--eslint",
|
|
7610
|
+
"--app",
|
|
7611
|
+
"--src-dir",
|
|
7612
|
+
"--import-alias",
|
|
7613
|
+
"@/*",
|
|
7614
|
+
"--no-git",
|
|
7615
|
+
"--yes"
|
|
7616
|
+
], {
|
|
7617
|
+
cwd: process.cwd(),
|
|
7618
|
+
stdio: "pipe"
|
|
7619
|
+
// Hide output for cleaner display
|
|
7620
|
+
});
|
|
7621
|
+
steps.complete();
|
|
7622
|
+
} catch (error) {
|
|
7623
|
+
steps.error();
|
|
7624
|
+
showError({
|
|
7625
|
+
title: "Project creation failed",
|
|
7626
|
+
message: "create-next-app could not complete",
|
|
7627
|
+
fixes: [
|
|
7628
|
+
"Make sure Node.js 18+ is installed",
|
|
7629
|
+
"Check your internet connection",
|
|
7630
|
+
"Try running manually: npx create-next-app@latest " + spec.name
|
|
7631
|
+
],
|
|
7632
|
+
command: "npx create-next-app@latest " + spec.name
|
|
7633
|
+
});
|
|
7634
|
+
return;
|
|
7635
|
+
}
|
|
7636
|
+
if (!await fs16.pathExists(projectPath)) {
|
|
7637
|
+
steps.error();
|
|
7638
|
+
showError({
|
|
7639
|
+
title: "Project folder not created",
|
|
7640
|
+
message: "The project directory was not found after creation",
|
|
7641
|
+
fixes: [
|
|
7642
|
+
"Check if you have write permissions in this folder",
|
|
7643
|
+
"Try creating the project in a different location"
|
|
7644
|
+
]
|
|
7645
|
+
});
|
|
7646
|
+
return;
|
|
7647
|
+
}
|
|
7648
|
+
steps.start();
|
|
7649
|
+
try {
|
|
7650
|
+
await execa11("npm", ["install", "lucide-react"], {
|
|
7651
|
+
cwd: projectPath,
|
|
7652
|
+
stdio: "pipe"
|
|
7653
|
+
});
|
|
7654
|
+
steps.complete();
|
|
7655
|
+
} catch (error) {
|
|
7656
|
+
steps.error();
|
|
7657
|
+
showError({
|
|
7658
|
+
...ERRORS.npmFailed,
|
|
7659
|
+
command: `cd ${spec.name} && npm install`
|
|
7660
|
+
});
|
|
7661
|
+
return;
|
|
7662
|
+
}
|
|
7663
|
+
steps.start();
|
|
7664
|
+
try {
|
|
7665
|
+
await execa11("npx", ["shadcn@latest", "init", "-y", "-d"], {
|
|
7666
|
+
cwd: projectPath,
|
|
7667
|
+
stdio: "pipe"
|
|
7668
|
+
});
|
|
7669
|
+
await execa11("npx", ["shadcn@latest", "add", "button", "card", "input", "badge", "-y"], {
|
|
7670
|
+
cwd: projectPath,
|
|
7671
|
+
stdio: "pipe"
|
|
7672
|
+
});
|
|
7673
|
+
steps.complete();
|
|
7674
|
+
} catch (error) {
|
|
7675
|
+
steps.skip();
|
|
7676
|
+
}
|
|
7677
|
+
steps.start();
|
|
7364
7678
|
const response = await anthropic.messages.create({
|
|
7365
|
-
model: "claude-sonnet-4-
|
|
7679
|
+
model: "claude-sonnet-4-5-20250929",
|
|
7366
7680
|
max_tokens: 16e3,
|
|
7367
7681
|
messages: [{
|
|
7368
7682
|
role: "user",
|
|
@@ -7417,39 +7731,46 @@ Make it production-quality and visually impressive.`
|
|
|
7417
7731
|
const text17 = response.content[0].type === "text" ? response.content[0].text : "";
|
|
7418
7732
|
const fileRegex = /<<<FILE:\s*(.+?)>>>([\s\S]*?)<<<END_FILE>>>/g;
|
|
7419
7733
|
let match;
|
|
7420
|
-
let fileCount = 0;
|
|
7421
7734
|
while ((match = fileRegex.exec(text17)) !== null) {
|
|
7422
7735
|
const filePath = path15.join(projectPath, match[1].trim());
|
|
7423
7736
|
const content = match[2].trim();
|
|
7424
7737
|
await fs16.ensureDir(path15.dirname(filePath));
|
|
7425
7738
|
await fs16.writeFile(filePath, content);
|
|
7426
|
-
|
|
7427
|
-
}
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7739
|
+
createdFiles.push(match[1].trim());
|
|
7740
|
+
}
|
|
7741
|
+
steps.complete();
|
|
7742
|
+
steps.start();
|
|
7743
|
+
steps.complete();
|
|
7744
|
+
steps.start();
|
|
7745
|
+
try {
|
|
7746
|
+
await execa11("git", ["init"], { cwd: projectPath, stdio: "pipe" });
|
|
7747
|
+
await execa11("git", ["add", "."], { cwd: projectPath, stdio: "pipe" });
|
|
7748
|
+
await execa11("git", ["commit", "-m", "Initial website build by CodeBakers"], { cwd: projectPath, stdio: "pipe" });
|
|
7749
|
+
steps.complete();
|
|
7750
|
+
} catch (error) {
|
|
7751
|
+
steps.skip();
|
|
7752
|
+
}
|
|
7753
|
+
if (createdFiles.length > 0) {
|
|
7754
|
+
showFileList("Files created", createdFiles.slice(0, 10));
|
|
7755
|
+
if (createdFiles.length > 10) {
|
|
7756
|
+
console.log(chalk20.dim(` ... and ${createdFiles.length - 10} more files`));
|
|
7757
|
+
}
|
|
7758
|
+
}
|
|
7759
|
+
showSuccess({
|
|
7760
|
+
title: "Website built successfully!",
|
|
7761
|
+
message: spec.description,
|
|
7762
|
+
stats: [
|
|
7763
|
+
{ label: "Project", value: spec.name },
|
|
7764
|
+
{ label: "Files created", value: createdFiles.length.toString() },
|
|
7765
|
+
{ label: "Sections", value: spec.sections.length.toString() },
|
|
7766
|
+
{ label: "Build time", value: steps.getElapsedTime() }
|
|
7767
|
+
],
|
|
7768
|
+
nextSteps: [
|
|
7769
|
+
`cd ${spec.name}`,
|
|
7770
|
+
"npm run dev"
|
|
7771
|
+
],
|
|
7772
|
+
command: `cd ${spec.name} && npm run dev`
|
|
7773
|
+
});
|
|
7453
7774
|
const openDev = await p19.confirm({
|
|
7454
7775
|
message: "Start development server now?",
|
|
7455
7776
|
initialValue: true
|
|
@@ -7632,7 +7953,7 @@ If unclear between multiple commands, use the most likely one with lower confide
|
|
|
7632
7953
|
}
|
|
7633
7954
|
|
|
7634
7955
|
// src/index.ts
|
|
7635
|
-
var
|
|
7956
|
+
var VERSION = "2.5.0";
|
|
7636
7957
|
var logo = `
|
|
7637
7958
|
\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
7638
7959
|
\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2554\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D
|
|
@@ -7644,7 +7965,7 @@ var logo = `
|
|
|
7644
7965
|
async function showMainMenu() {
|
|
7645
7966
|
const config = new Config();
|
|
7646
7967
|
console.log(gradient.pastel.multiline(logo));
|
|
7647
|
-
console.log(chalk21.dim(` v${
|
|
7968
|
+
console.log(chalk21.dim(` v${VERSION} \u2014 AI dev team that follows the rules
|
|
7648
7969
|
`));
|
|
7649
7970
|
const hasAnthropic = !!config.getCredentials("anthropic")?.apiKey;
|
|
7650
7971
|
if (!hasAnthropic) {
|
|
@@ -7891,7 +8212,7 @@ function showPostBuildInstructions(projectName, projectPath) {
|
|
|
7891
8212
|
}
|
|
7892
8213
|
function showHelp2() {
|
|
7893
8214
|
console.log(boxen2(`
|
|
7894
|
-
${chalk21.bold("CodeBakers CLI v" +
|
|
8215
|
+
${chalk21.bold("CodeBakers CLI v" + VERSION)} \u2014 AI dev team that follows the rules
|
|
7895
8216
|
|
|
7896
8217
|
${chalk21.bold.cyan("Getting Started:")}
|
|
7897
8218
|
${chalk21.cyan("codebakers")} Interactive menu
|
|
@@ -7918,7 +8239,7 @@ ${chalk21.bold("Docs:")} ${chalk21.dim("https://codebakers.dev/docs")}
|
|
|
7918
8239
|
`, { padding: 1, borderColor: "cyan", borderStyle: "round" }));
|
|
7919
8240
|
}
|
|
7920
8241
|
var program = new Command();
|
|
7921
|
-
program.name("codebakers").description("AI dev team that follows the rules").version(
|
|
8242
|
+
program.name("codebakers").description("AI dev team that follows the rules").version(VERSION).action(showMainMenu);
|
|
7922
8243
|
program.command("setup").description("Configure CodeBakers (API keys)").action(setupCommand);
|
|
7923
8244
|
program.command("init").description("Create a new project").option("-n, --name <n>", "Project name").option("-t, --template <t>", "Template").action(initCommand);
|
|
7924
8245
|
program.command("code [prompt]").description("Start AI coding session").option("-w, --watch", "Watch mode").action(codeCommand);
|