@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/src/lib/api.ts
CHANGED
|
@@ -260,3 +260,258 @@ export async function reportCliError(
|
|
|
260
260
|
// Never fail on error reporting
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
|
+
|
|
264
|
+
// ============================================================================
|
|
265
|
+
// PROJECT TRACKING API
|
|
266
|
+
// ============================================================================
|
|
267
|
+
|
|
268
|
+
export interface ProjectSyncData {
|
|
269
|
+
// Project updates
|
|
270
|
+
project?: {
|
|
271
|
+
status?: 'discovery' | 'planning' | 'building' | 'testing' | 'completed' | 'paused' | 'failed';
|
|
272
|
+
overallProgress?: number;
|
|
273
|
+
prdContent?: string;
|
|
274
|
+
discoveryAnswers?: Record<string, unknown>;
|
|
275
|
+
patternsUsed?: string[];
|
|
276
|
+
detectedStack?: Record<string, string>;
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// Phases to sync
|
|
280
|
+
phases?: Array<{
|
|
281
|
+
id?: string;
|
|
282
|
+
phaseNumber: number;
|
|
283
|
+
phaseName: string;
|
|
284
|
+
phaseDescription?: string;
|
|
285
|
+
status?: 'pending' | 'in_progress' | 'completed' | 'skipped' | 'failed';
|
|
286
|
+
progress?: number;
|
|
287
|
+
requiredPatterns?: string[];
|
|
288
|
+
aiConfidence?: number;
|
|
289
|
+
aiNotes?: string;
|
|
290
|
+
alternativesConsidered?: string[];
|
|
291
|
+
requiresApproval?: boolean;
|
|
292
|
+
}>;
|
|
293
|
+
|
|
294
|
+
// Events to record
|
|
295
|
+
events?: Array<{
|
|
296
|
+
eventType: string;
|
|
297
|
+
eventTitle: string;
|
|
298
|
+
eventDescription?: string;
|
|
299
|
+
eventData?: Record<string, unknown>;
|
|
300
|
+
phaseId?: string;
|
|
301
|
+
featureId?: string;
|
|
302
|
+
filePath?: string;
|
|
303
|
+
fileAction?: string;
|
|
304
|
+
linesChanged?: number;
|
|
305
|
+
aiConfidence?: number;
|
|
306
|
+
riskLevel?: 'low' | 'medium' | 'high' | 'critical';
|
|
307
|
+
riskReason?: string;
|
|
308
|
+
}>;
|
|
309
|
+
|
|
310
|
+
// Test runs to record
|
|
311
|
+
testRuns?: Array<{
|
|
312
|
+
testType: string;
|
|
313
|
+
testCommand?: string;
|
|
314
|
+
passed: boolean;
|
|
315
|
+
totalTests: number;
|
|
316
|
+
passedTests: number;
|
|
317
|
+
failedTests: number;
|
|
318
|
+
skippedTests: number;
|
|
319
|
+
durationMs?: number;
|
|
320
|
+
phaseId?: string;
|
|
321
|
+
featureId?: string;
|
|
322
|
+
}>;
|
|
323
|
+
|
|
324
|
+
// Files to track
|
|
325
|
+
files?: Array<{
|
|
326
|
+
filePath: string;
|
|
327
|
+
fileName: string;
|
|
328
|
+
fileType?: string;
|
|
329
|
+
lineCount?: number;
|
|
330
|
+
complexity?: number;
|
|
331
|
+
parentPath?: string;
|
|
332
|
+
depth?: number;
|
|
333
|
+
status?: 'active' | 'deleted' | 'renamed';
|
|
334
|
+
featureId?: string;
|
|
335
|
+
}>;
|
|
336
|
+
|
|
337
|
+
// Dependencies to track
|
|
338
|
+
dependencies?: Array<{
|
|
339
|
+
sourceFile: string;
|
|
340
|
+
sourceType?: string;
|
|
341
|
+
targetFile: string;
|
|
342
|
+
targetType?: string;
|
|
343
|
+
dependencyType?: string;
|
|
344
|
+
importName?: string;
|
|
345
|
+
featureId?: string;
|
|
346
|
+
}>;
|
|
347
|
+
|
|
348
|
+
// Risk flags to create
|
|
349
|
+
riskFlags?: Array<{
|
|
350
|
+
riskLevel: 'low' | 'medium' | 'high' | 'critical';
|
|
351
|
+
riskCategory: string;
|
|
352
|
+
riskTitle: string;
|
|
353
|
+
riskDescription?: string;
|
|
354
|
+
triggerFile?: string;
|
|
355
|
+
triggerCode?: string;
|
|
356
|
+
triggerReason?: string;
|
|
357
|
+
aiRecommendation?: string;
|
|
358
|
+
phaseId?: string;
|
|
359
|
+
featureId?: string;
|
|
360
|
+
}>;
|
|
361
|
+
|
|
362
|
+
// Resource usage to track
|
|
363
|
+
resources?: Array<{
|
|
364
|
+
resourceType: string;
|
|
365
|
+
apiEndpoint?: string;
|
|
366
|
+
apiMethod?: string;
|
|
367
|
+
inputTokens?: number;
|
|
368
|
+
outputTokens?: number;
|
|
369
|
+
totalTokens?: number;
|
|
370
|
+
durationMs?: number;
|
|
371
|
+
estimatedCostMillicents?: number;
|
|
372
|
+
phaseId?: string;
|
|
373
|
+
featureId?: string;
|
|
374
|
+
}>;
|
|
375
|
+
|
|
376
|
+
// Create snapshot
|
|
377
|
+
createSnapshot?: {
|
|
378
|
+
snapshotName: string;
|
|
379
|
+
snapshotDescription?: string;
|
|
380
|
+
isAutomatic?: boolean;
|
|
381
|
+
gitCommitHash?: string;
|
|
382
|
+
gitBranch?: string;
|
|
383
|
+
projectState?: Record<string, unknown>;
|
|
384
|
+
fileTree?: Array<Record<string, unknown>>;
|
|
385
|
+
phaseId?: string;
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export interface ProjectSyncResult {
|
|
390
|
+
projectId: string;
|
|
391
|
+
synced: {
|
|
392
|
+
project: boolean;
|
|
393
|
+
phases: number;
|
|
394
|
+
events: number;
|
|
395
|
+
testRuns: number;
|
|
396
|
+
files: number;
|
|
397
|
+
dependencies: number;
|
|
398
|
+
riskFlags: number;
|
|
399
|
+
resources: number;
|
|
400
|
+
snapshot: boolean;
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Get or create a project on the server
|
|
406
|
+
*/
|
|
407
|
+
export async function getOrCreateProject(
|
|
408
|
+
projectHash: string,
|
|
409
|
+
projectName: string,
|
|
410
|
+
projectDescription?: string,
|
|
411
|
+
detectedStack?: Record<string, string>,
|
|
412
|
+
authHeaders?: Record<string, string>
|
|
413
|
+
): Promise<{ projectId: string; isNew: boolean }> {
|
|
414
|
+
const apiUrl = getApiUrl();
|
|
415
|
+
|
|
416
|
+
const response = await fetch(`${apiUrl}/api/projects`, {
|
|
417
|
+
method: 'POST',
|
|
418
|
+
headers: {
|
|
419
|
+
'Content-Type': 'application/json',
|
|
420
|
+
...authHeaders,
|
|
421
|
+
},
|
|
422
|
+
body: JSON.stringify({
|
|
423
|
+
projectHash,
|
|
424
|
+
projectName,
|
|
425
|
+
projectDescription,
|
|
426
|
+
detectedStack,
|
|
427
|
+
}),
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
if (!response.ok) {
|
|
431
|
+
const error = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
432
|
+
throw createApiError(
|
|
433
|
+
error.error || 'Failed to create/get project',
|
|
434
|
+
'PROJECT_ERROR',
|
|
435
|
+
['Check your internet connection', 'Verify your API key is valid']
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const result = await response.json();
|
|
440
|
+
return {
|
|
441
|
+
projectId: result.data?.id || result.id,
|
|
442
|
+
isNew: result.data?.isNew || result.isNew || false,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Sync project data to the server
|
|
448
|
+
* This is the main endpoint for keeping the server updated with local state
|
|
449
|
+
*/
|
|
450
|
+
export async function syncProjectData(
|
|
451
|
+
projectId: string,
|
|
452
|
+
data: ProjectSyncData,
|
|
453
|
+
authHeaders?: Record<string, string>
|
|
454
|
+
): Promise<ProjectSyncResult> {
|
|
455
|
+
const apiUrl = getApiUrl();
|
|
456
|
+
|
|
457
|
+
const response = await fetch(`${apiUrl}/api/projects/${projectId}/sync`, {
|
|
458
|
+
method: 'POST',
|
|
459
|
+
headers: {
|
|
460
|
+
'Content-Type': 'application/json',
|
|
461
|
+
...authHeaders,
|
|
462
|
+
},
|
|
463
|
+
body: JSON.stringify(data),
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
if (!response.ok) {
|
|
467
|
+
const error = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
468
|
+
throw createApiError(
|
|
469
|
+
error.error || 'Failed to sync project data',
|
|
470
|
+
'SYNC_ERROR',
|
|
471
|
+
['Check your internet connection', 'Try again in a few moments']
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const result = await response.json();
|
|
476
|
+
return result.data || result;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Get project dashboard data from the server
|
|
481
|
+
*/
|
|
482
|
+
export async function getProjectDashboard(
|
|
483
|
+
projectId: string,
|
|
484
|
+
authHeaders?: Record<string, string>
|
|
485
|
+
): Promise<Record<string, unknown>> {
|
|
486
|
+
const apiUrl = getApiUrl();
|
|
487
|
+
|
|
488
|
+
const response = await fetch(`${apiUrl}/api/projects/${projectId}`, {
|
|
489
|
+
method: 'GET',
|
|
490
|
+
headers: {
|
|
491
|
+
'Accept': 'application/json',
|
|
492
|
+
...authHeaders,
|
|
493
|
+
},
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
if (!response.ok) {
|
|
497
|
+
const error = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
498
|
+
throw createApiError(
|
|
499
|
+
error.error || 'Failed to get project dashboard',
|
|
500
|
+
'PROJECT_ERROR',
|
|
501
|
+
['Check your internet connection', 'Verify the project exists']
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const result = await response.json();
|
|
506
|
+
return result.data || result;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Create a project hash from the project directory
|
|
511
|
+
* Uses a combination of directory path and package.json name for uniqueness
|
|
512
|
+
*/
|
|
513
|
+
export function createProjectHash(projectDir: string, packageName?: string): string {
|
|
514
|
+
const crypto = require('crypto');
|
|
515
|
+
const hashInput = packageName ? `${projectDir}:${packageName}` : projectDir;
|
|
516
|
+
return crypto.createHash('sha256').update(hashInput).digest('hex').substring(0, 16);
|
|
517
|
+
}
|