@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.
- package/dist/lib/api.d.ts +138 -0
- package/dist/lib/api.js +81 -0
- package/dist/mcp/server.js +378 -2
- package/package.json +1 -1
- package/src/lib/api.ts +255 -0
- package/src/mcp/server.ts +486 -0
package/dist/mcp/server.js
CHANGED
|
@@ -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:
|
|
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
|