@codebakers/cli 3.3.11 โ†’ 3.3.13

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.
@@ -57,6 +57,9 @@ class CodeBakersServer {
57
57
  authMode;
58
58
  autoUpdateChecked = false;
59
59
  autoUpdateInProgress = false;
60
+ pendingUpdate = null;
61
+ lastUpdateCheck = 0;
62
+ updateCheckInterval = 60 * 60 * 1000; // Check every hour
60
63
  constructor() {
61
64
  this.apiKey = (0, config_js_1.getApiKey)();
62
65
  this.apiUrl = (0, config_js_1.getApiUrl)();
@@ -79,12 +82,30 @@ class CodeBakersServer {
79
82
  this.checkCliVersion().catch(() => {
80
83
  // Silently ignore errors
81
84
  });
85
+ // Start periodic update checks (every hour)
86
+ setInterval(() => {
87
+ this.checkCliVersion().catch(() => { });
88
+ }, this.updateCheckInterval);
89
+ }
90
+ /**
91
+ * Get update notice if a newer version is available
92
+ */
93
+ getUpdateNotice() {
94
+ if (this.pendingUpdate) {
95
+ return `\n\n---\n๐Ÿ†• **CodeBakers Update Available:** v${this.pendingUpdate.current} โ†’ v${this.pendingUpdate.latest}\nRestart Cursor/Claude Code to get new features!`;
96
+ }
97
+ return '';
82
98
  }
83
99
  /**
84
100
  * Check if a newer CLI version is available and notify user
85
101
  */
86
102
  async checkCliVersion() {
87
103
  try {
104
+ // Rate limit checks
105
+ const now = Date.now();
106
+ if (now - this.lastUpdateCheck < 5 * 60 * 1000)
107
+ return; // Min 5 minutes between checks
108
+ this.lastUpdateCheck = now;
88
109
  const currentVersion = (0, api_js_1.getCliVersion)();
89
110
  // Fetch latest version from npm
90
111
  const response = await fetch('https://registry.npmjs.org/@codebakers/cli/latest', {
@@ -102,12 +123,22 @@ class CodeBakersServer {
102
123
  (latest[0] === current[0] && latest[1] > current[1]) ||
103
124
  (latest[0] === current[0] && latest[1] === current[1] && latest[2] > current[2]);
104
125
  if (isNewer) {
126
+ // Store pending update for inclusion in tool responses
127
+ this.pendingUpdate = { current: currentVersion, latest: latestVersion };
128
+ // Also log to stderr for immediate visibility
105
129
  console.error(`\nโ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—`);
106
130
  console.error(`โ•‘ ๐Ÿ†• CodeBakers CLI Update Available: v${currentVersion} โ†’ v${latestVersion.padEnd(10)}โ•‘`);
107
131
  console.error(`โ•‘ โ•‘`);
108
132
  console.error(`โ•‘ Restart Cursor/Claude Code to get the latest features! โ•‘`);
109
133
  console.error(`โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•\n`);
110
134
  }
135
+ else {
136
+ // No update available
137
+ this.pendingUpdate = null;
138
+ }
139
+ }
140
+ else {
141
+ this.pendingUpdate = null;
111
142
  }
112
143
  }
113
144
  catch {
@@ -1246,6 +1277,124 @@ class CodeBakersServer {
1246
1277
  properties: {},
1247
1278
  },
1248
1279
  },
1280
+ // ============================================
1281
+ // PROJECT TRACKING - Server-Side Dashboard
1282
+ // ============================================
1283
+ {
1284
+ name: 'project_sync',
1285
+ description: 'Sync project progress to the CodeBakers server for dashboard visualization. Call this after completing builds, features, tests, or other significant milestones. Data appears on the web dashboard at codebakers.ai/projects.',
1286
+ inputSchema: {
1287
+ type: 'object',
1288
+ properties: {
1289
+ projectStatus: {
1290
+ type: 'string',
1291
+ enum: ['discovery', 'planning', 'building', 'testing', 'completed', 'paused', 'failed'],
1292
+ description: 'Current project status',
1293
+ },
1294
+ overallProgress: {
1295
+ type: 'number',
1296
+ description: 'Overall progress percentage (0-100)',
1297
+ },
1298
+ phases: {
1299
+ type: 'array',
1300
+ items: {
1301
+ type: 'object',
1302
+ properties: {
1303
+ phaseNumber: { type: 'number' },
1304
+ phaseName: { type: 'string' },
1305
+ phaseDescription: { type: 'string' },
1306
+ status: { type: 'string', enum: ['pending', 'in_progress', 'completed', 'skipped', 'failed'] },
1307
+ progress: { type: 'number' },
1308
+ aiConfidence: { type: 'number' },
1309
+ },
1310
+ },
1311
+ description: 'Build phases to sync',
1312
+ },
1313
+ events: {
1314
+ type: 'array',
1315
+ items: {
1316
+ type: 'object',
1317
+ properties: {
1318
+ eventType: { type: 'string' },
1319
+ eventTitle: { type: 'string' },
1320
+ eventDescription: { type: 'string' },
1321
+ filePath: { type: 'string' },
1322
+ fileAction: { type: 'string' },
1323
+ linesChanged: { type: 'number' },
1324
+ riskLevel: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] },
1325
+ },
1326
+ },
1327
+ description: 'Timeline events to record',
1328
+ },
1329
+ testRuns: {
1330
+ type: 'array',
1331
+ items: {
1332
+ type: 'object',
1333
+ properties: {
1334
+ testType: { type: 'string' },
1335
+ testCommand: { type: 'string' },
1336
+ passed: { type: 'boolean' },
1337
+ totalTests: { type: 'number' },
1338
+ passedTests: { type: 'number' },
1339
+ failedTests: { type: 'number' },
1340
+ skippedTests: { type: 'number' },
1341
+ durationMs: { type: 'number' },
1342
+ },
1343
+ },
1344
+ description: 'Test run results to sync',
1345
+ },
1346
+ riskFlags: {
1347
+ type: 'array',
1348
+ items: {
1349
+ type: 'object',
1350
+ properties: {
1351
+ riskLevel: { type: 'string', enum: ['low', 'medium', 'high', 'critical'] },
1352
+ riskCategory: { type: 'string' },
1353
+ riskTitle: { type: 'string' },
1354
+ riskDescription: { type: 'string' },
1355
+ triggerFile: { type: 'string' },
1356
+ aiRecommendation: { type: 'string' },
1357
+ },
1358
+ },
1359
+ description: 'Risk flags to create',
1360
+ },
1361
+ resources: {
1362
+ type: 'array',
1363
+ items: {
1364
+ type: 'object',
1365
+ properties: {
1366
+ resourceType: { type: 'string' },
1367
+ inputTokens: { type: 'number' },
1368
+ outputTokens: { type: 'number' },
1369
+ totalTokens: { type: 'number' },
1370
+ durationMs: { type: 'number' },
1371
+ estimatedCostMillicents: { type: 'number' },
1372
+ },
1373
+ },
1374
+ description: 'Resource usage to track (API calls, tokens, etc.)',
1375
+ },
1376
+ createSnapshot: {
1377
+ type: 'object',
1378
+ properties: {
1379
+ snapshotName: { type: 'string' },
1380
+ snapshotDescription: { type: 'string' },
1381
+ isAutomatic: { type: 'boolean' },
1382
+ gitCommitHash: { type: 'string' },
1383
+ gitBranch: { type: 'string' },
1384
+ },
1385
+ description: 'Create a rollback snapshot',
1386
+ },
1387
+ },
1388
+ },
1389
+ },
1390
+ {
1391
+ name: 'project_dashboard_url',
1392
+ description: 'Get the URL to view the project dashboard on codebakers.ai. Use when user says "show dashboard", "view progress online", or "open project page".',
1393
+ inputSchema: {
1394
+ type: 'object',
1395
+ properties: {},
1396
+ },
1397
+ },
1249
1398
  ],
1250
1399
  }));
1251
1400
  // Handle tool calls
@@ -1365,6 +1514,11 @@ class CodeBakersServer {
1365
1514
  return this.handleGuardianVerify(args);
1366
1515
  case 'guardian_status':
1367
1516
  return this.handleGuardianStatus();
1517
+ // Project Tracking - Server-Side Dashboard
1518
+ case 'project_sync':
1519
+ return this.handleProjectSync(args);
1520
+ case 'project_dashboard_url':
1521
+ return this.handleProjectDashboardUrl();
1368
1522
  default:
1369
1523
  throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
1370
1524
  }
@@ -2403,6 +2557,8 @@ phase: development
2403
2557
  if (!args.auto && result.errors.some(e => e.autoFixable && !e.fixed)) {
2404
2558
  response += `---\n\n*Run with \`auto: true\` to automatically apply safe fixes.*`;
2405
2559
  }
2560
+ // Add CLI update notice if available
2561
+ response += this.getUpdateNotice();
2406
2562
  return {
2407
2563
  content: [{
2408
2564
  type: 'text',
@@ -2415,7 +2571,7 @@ phase: development
2415
2571
  return {
2416
2572
  content: [{
2417
2573
  type: 'text',
2418
- text: `# โŒ Healing Failed\n\nError: ${message}`,
2574
+ text: `# โŒ Healing Failed\n\nError: ${message}${this.getUpdateNotice()}`,
2419
2575
  }],
2420
2576
  };
2421
2577
  }
@@ -2466,10 +2622,12 @@ Just describe what you want to build! I'll automatically:
2466
2622
 
2467
2623
  ---
2468
2624
  *CodeBakers is providing AI-assisted development patterns for this project.*`;
2625
+ // Add CLI update notice if available
2626
+ const statusWithNotice = statusText + this.getUpdateNotice();
2469
2627
  return {
2470
2628
  content: [{
2471
2629
  type: 'text',
2472
- text: statusText,
2630
+ text: statusWithNotice,
2473
2631
  }],
2474
2632
  };
2475
2633
  }
@@ -4920,6 +5078,7 @@ ${handlers.join('\n')}
4920
5078
  response += `โœ… **Already up to date!**\n\n`;
4921
5079
  response += `Your patterns are current (v${latestVersion} with ${latestModuleCount} modules).\n`;
4922
5080
  response += `Use \`force: true\` to re-download anyway.\n`;
5081
+ response += this.getUpdateNotice();
4923
5082
  return {
4924
5083
  content: [{
4925
5084
  type: 'text',
@@ -4987,6 +5146,8 @@ ${handlers.join('\n')}
4987
5146
  response += `Please try again or run \`codebakers upgrade\` in terminal.\n`;
4988
5147
  }
4989
5148
  }
5149
+ // Add CLI update notice if available
5150
+ response += this.getUpdateNotice();
4990
5151
  return {
4991
5152
  content: [{
4992
5153
  type: 'text',
@@ -6218,8 +6379,223 @@ ${events.includes('call-started') ? ` case 'call-started':
6218
6379
  response += `## โš ๏ธ State Corrupted\n\n`;
6219
6380
  response += `Could not read guardian state. Run \`guardian_analyze\` to rebuild.\n`;
6220
6381
  }
6382
+ // Add update notice if available
6383
+ response += this.getUpdateNotice();
6221
6384
  return { content: [{ type: 'text', text: response }] };
6222
6385
  }
6386
+ // ============================================================================
6387
+ // PROJECT TRACKING - Server-Side Dashboard
6388
+ // ============================================================================
6389
+ /**
6390
+ * Sync project progress to the CodeBakers server
6391
+ */
6392
+ async handleProjectSync(args) {
6393
+ const cwd = process.cwd();
6394
+ try {
6395
+ // Import API functions dynamically
6396
+ const apiModule = await import('../lib/api.js');
6397
+ const { getOrCreateProject, syncProjectData, createProjectHash } = apiModule;
6398
+ // Read package.json for project info
6399
+ let projectName = path.basename(cwd);
6400
+ let packageName;
6401
+ const packageJsonPath = path.join(cwd, 'package.json');
6402
+ if (fs.existsSync(packageJsonPath)) {
6403
+ try {
6404
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
6405
+ projectName = packageJson.name || projectName;
6406
+ packageName = packageJson.name;
6407
+ }
6408
+ catch {
6409
+ // Ignore parse errors
6410
+ }
6411
+ }
6412
+ // Create project hash
6413
+ const projectHash = createProjectHash(cwd, packageName);
6414
+ // Read .codebakers.json for detected stack
6415
+ let detectedStack;
6416
+ const codebakersPath = path.join(cwd, '.codebakers.json');
6417
+ if (fs.existsSync(codebakersPath)) {
6418
+ try {
6419
+ const codebakersState = JSON.parse(fs.readFileSync(codebakersPath, 'utf-8'));
6420
+ if (codebakersState.stack) {
6421
+ detectedStack = codebakersState.stack;
6422
+ }
6423
+ }
6424
+ catch {
6425
+ // Ignore parse errors
6426
+ }
6427
+ }
6428
+ // Get or create project on server
6429
+ const authHeaders = this.getAuthHeaders();
6430
+ const { projectId, isNew } = await getOrCreateProject(projectHash, projectName, undefined, detectedStack, authHeaders);
6431
+ // Build sync data
6432
+ const syncData = {};
6433
+ // Add project status if provided
6434
+ if (args.projectStatus || args.overallProgress !== undefined) {
6435
+ const projectUpdate = {};
6436
+ if (args.projectStatus) {
6437
+ projectUpdate.status = args.projectStatus;
6438
+ }
6439
+ if (args.overallProgress !== undefined) {
6440
+ projectUpdate.overallProgress = args.overallProgress;
6441
+ }
6442
+ syncData.project = projectUpdate;
6443
+ }
6444
+ // Add phases if provided
6445
+ if (args.phases && args.phases.length > 0) {
6446
+ syncData.phases = args.phases.map(p => ({
6447
+ phaseNumber: p.phaseNumber,
6448
+ phaseName: p.phaseName,
6449
+ phaseDescription: p.phaseDescription,
6450
+ status: p.status,
6451
+ progress: p.progress,
6452
+ aiConfidence: p.aiConfidence,
6453
+ }));
6454
+ }
6455
+ // Add events if provided
6456
+ if (args.events && args.events.length > 0) {
6457
+ syncData.events = args.events.map(e => ({
6458
+ eventType: e.eventType,
6459
+ eventTitle: e.eventTitle,
6460
+ eventDescription: e.eventDescription,
6461
+ filePath: e.filePath,
6462
+ fileAction: e.fileAction,
6463
+ linesChanged: e.linesChanged,
6464
+ riskLevel: e.riskLevel,
6465
+ }));
6466
+ }
6467
+ // Add test runs if provided
6468
+ if (args.testRuns && args.testRuns.length > 0) {
6469
+ syncData.testRuns = args.testRuns;
6470
+ }
6471
+ // Add risk flags if provided
6472
+ if (args.riskFlags && args.riskFlags.length > 0) {
6473
+ syncData.riskFlags = args.riskFlags.map(r => ({
6474
+ riskLevel: r.riskLevel,
6475
+ riskCategory: r.riskCategory,
6476
+ riskTitle: r.riskTitle,
6477
+ riskDescription: r.riskDescription,
6478
+ triggerFile: r.triggerFile,
6479
+ aiRecommendation: r.aiRecommendation,
6480
+ }));
6481
+ }
6482
+ // Add resources if provided
6483
+ if (args.resources && args.resources.length > 0) {
6484
+ syncData.resources = args.resources;
6485
+ }
6486
+ // Add snapshot if provided
6487
+ if (args.createSnapshot) {
6488
+ // Get git info if available
6489
+ let gitCommitHash;
6490
+ let gitBranch;
6491
+ try {
6492
+ gitCommitHash = (0, child_process_1.execSync)('git rev-parse HEAD', { cwd, encoding: 'utf-8' }).trim();
6493
+ gitBranch = (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', { cwd, encoding: 'utf-8' }).trim();
6494
+ }
6495
+ catch {
6496
+ // Git not available or not a repo
6497
+ }
6498
+ syncData.createSnapshot = {
6499
+ snapshotName: args.createSnapshot.snapshotName,
6500
+ snapshotDescription: args.createSnapshot.snapshotDescription,
6501
+ isAutomatic: args.createSnapshot.isAutomatic,
6502
+ gitCommitHash: args.createSnapshot.gitCommitHash || gitCommitHash,
6503
+ gitBranch: args.createSnapshot.gitBranch || gitBranch,
6504
+ };
6505
+ }
6506
+ // Sync to server
6507
+ const result = await syncProjectData(projectId, syncData, authHeaders);
6508
+ // Build response
6509
+ let response = `# ๐Ÿ“Š Project Synced to Dashboard\n\n`;
6510
+ if (isNew) {
6511
+ response += `โœจ **New project registered:** ${projectName}\n\n`;
6512
+ }
6513
+ response += `**Project ID:** \`${projectId}\`\n\n`;
6514
+ response += `## Synced Data\n\n`;
6515
+ const synced = result.synced;
6516
+ if (synced.project)
6517
+ response += `- โœ… Project status updated\n`;
6518
+ if (synced.phases > 0)
6519
+ response += `- โœ… ${synced.phases} phase(s) synced\n`;
6520
+ if (synced.events > 0)
6521
+ response += `- โœ… ${synced.events} event(s) recorded\n`;
6522
+ if (synced.testRuns > 0)
6523
+ response += `- โœ… ${synced.testRuns} test run(s) logged\n`;
6524
+ if (synced.riskFlags > 0)
6525
+ response += `- โœ… ${synced.riskFlags} risk flag(s) created\n`;
6526
+ if (synced.resources > 0)
6527
+ response += `- โœ… ${synced.resources} resource record(s) added\n`;
6528
+ if (synced.snapshot)
6529
+ response += `- โœ… Rollback snapshot created\n`;
6530
+ response += `\n---\n\n`;
6531
+ response += `๐Ÿ“ˆ **View Dashboard:** https://codebakers.ai/projects/${projectId}\n`;
6532
+ // Add update notice if available
6533
+ response += this.getUpdateNotice();
6534
+ return { content: [{ type: 'text', text: response }] };
6535
+ }
6536
+ catch (error) {
6537
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
6538
+ let response = `# โŒ Sync Failed\n\n`;
6539
+ response += `Could not sync project to server.\n\n`;
6540
+ response += `**Error:** ${errorMessage}\n\n`;
6541
+ response += `This may be due to:\n`;
6542
+ response += `- Network connectivity issues\n`;
6543
+ response += `- Invalid API key or expired trial\n`;
6544
+ response += `- Server maintenance\n\n`;
6545
+ response += `Your local project is unaffected. Try again later.\n`;
6546
+ return { content: [{ type: 'text', text: response }] };
6547
+ }
6548
+ }
6549
+ /**
6550
+ * Get the URL to view the project dashboard
6551
+ */
6552
+ async handleProjectDashboardUrl() {
6553
+ const cwd = process.cwd();
6554
+ try {
6555
+ const { getOrCreateProject, createProjectHash } = await import('../lib/api.js');
6556
+ // Read package.json for project info
6557
+ let projectName = path.basename(cwd);
6558
+ let packageName;
6559
+ const packageJsonPath = path.join(cwd, 'package.json');
6560
+ if (fs.existsSync(packageJsonPath)) {
6561
+ try {
6562
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
6563
+ projectName = packageJson.name || projectName;
6564
+ packageName = packageJson.name;
6565
+ }
6566
+ catch {
6567
+ // Ignore parse errors
6568
+ }
6569
+ }
6570
+ // Create project hash
6571
+ const projectHash = createProjectHash(cwd, packageName);
6572
+ // Get or create project on server (this ensures the project exists)
6573
+ const authHeaders = this.getAuthHeaders();
6574
+ const { projectId } = await getOrCreateProject(projectHash, projectName, undefined, undefined, authHeaders);
6575
+ const dashboardUrl = `https://codebakers.ai/projects/${projectId}`;
6576
+ let response = `# ๐Ÿ“Š Project Dashboard\n\n`;
6577
+ response += `**Project:** ${projectName}\n\n`;
6578
+ response += `**Dashboard URL:**\n${dashboardUrl}\n\n`;
6579
+ response += `Open this URL in your browser to view:\n`;
6580
+ response += `- ๐Ÿ“ˆ Build progress and phases\n`;
6581
+ response += `- ๐Ÿงช Test run history and results\n`;
6582
+ response += `- ๐Ÿ“ File tree evolution\n`;
6583
+ response += `- ๐Ÿ”— Dependency graph\n`;
6584
+ response += `- โš ๏ธ Risk flags and recommendations\n`;
6585
+ response += `- ๐Ÿ’ฐ Resource usage (tokens, API calls)\n`;
6586
+ response += `- ๐Ÿ“ธ Rollback snapshots\n`;
6587
+ // Add update notice if available
6588
+ response += this.getUpdateNotice();
6589
+ return { content: [{ type: 'text', text: response }] };
6590
+ }
6591
+ catch (error) {
6592
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
6593
+ let response = `# โŒ Could Not Get Dashboard URL\n\n`;
6594
+ response += `**Error:** ${errorMessage}\n\n`;
6595
+ response += `Make sure you are logged in with a valid API key or trial.\n`;
6596
+ return { content: [{ type: 'text', text: response }] };
6597
+ }
6598
+ }
6223
6599
  /**
6224
6600
  * Ripple Check - Detect all files affected by a change to a type/schema/function
6225
6601
  * Searches the codebase for imports and usages of the entity
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebakers/cli",
3
- "version": "3.3.11",
3
+ "version": "3.3.13",
4
4
  "description": "CodeBakers CLI - Production patterns for AI-assisted development",
5
5
  "main": "dist/index.js",
6
6
  "bin": {