@codebakers/cli 3.8.8 → 3.8.9
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/commands/go.d.ts +4 -0
- package/dist/commands/go.js +215 -0
- package/package.json +1 -1
- package/src/commands/go.ts +252 -0
package/dist/commands/go.d.ts
CHANGED
|
@@ -8,6 +8,10 @@ interface GoOptions {
|
|
|
8
8
|
/**
|
|
9
9
|
* Zero-friction entry point - start using CodeBakers instantly
|
|
10
10
|
* Single command for both trial and paid users
|
|
11
|
+
*
|
|
12
|
+
* SMART BEHAVIOR:
|
|
13
|
+
* - If CodeBakers already set up → Show context and resume from where you left off
|
|
14
|
+
* - If not set up → Run first-time setup (trial or login)
|
|
11
15
|
*/
|
|
12
16
|
export declare function go(options?: GoOptions): Promise<void>;
|
|
13
17
|
export {};
|
package/dist/commands/go.js
CHANGED
|
@@ -709,6 +709,190 @@ function updateGitignore(cwd) {
|
|
|
709
709
|
}
|
|
710
710
|
}
|
|
711
711
|
}
|
|
712
|
+
function analyzeProjectState(cwd) {
|
|
713
|
+
const state = {
|
|
714
|
+
isSetUp: false,
|
|
715
|
+
hasPrd: false,
|
|
716
|
+
inProgressTasks: [],
|
|
717
|
+
completedTasks: [],
|
|
718
|
+
blockers: [],
|
|
719
|
+
suggestion: '',
|
|
720
|
+
};
|
|
721
|
+
// Check if CodeBakers is set up
|
|
722
|
+
const codebakersJsonPath = (0, path_1.join)(cwd, '.codebakers.json');
|
|
723
|
+
if (!(0, fs_1.existsSync)(codebakersJsonPath)) {
|
|
724
|
+
state.suggestion = 'Project not set up. Running first-time setup...';
|
|
725
|
+
return state;
|
|
726
|
+
}
|
|
727
|
+
state.isSetUp = true;
|
|
728
|
+
// Read .codebakers.json
|
|
729
|
+
try {
|
|
730
|
+
const cbState = JSON.parse((0, fs_1.readFileSync)(codebakersJsonPath, 'utf-8'));
|
|
731
|
+
state.projectName = cbState.projectName;
|
|
732
|
+
state.projectType = cbState.projectType;
|
|
733
|
+
}
|
|
734
|
+
catch {
|
|
735
|
+
// Ignore parse errors
|
|
736
|
+
}
|
|
737
|
+
// Check for PRD.md
|
|
738
|
+
const prdPath = (0, path_1.join)(cwd, 'PRD.md');
|
|
739
|
+
if ((0, fs_1.existsSync)(prdPath)) {
|
|
740
|
+
state.hasPrd = true;
|
|
741
|
+
try {
|
|
742
|
+
const prdContent = (0, fs_1.readFileSync)(prdPath, 'utf-8');
|
|
743
|
+
// Extract one-liner if present
|
|
744
|
+
const oneLineMatch = prdContent.match(/\*\*One-liner:\*\*\s*(.+)/);
|
|
745
|
+
if (oneLineMatch) {
|
|
746
|
+
state.prdSummary = oneLineMatch[1].trim();
|
|
747
|
+
}
|
|
748
|
+
else {
|
|
749
|
+
// Get first non-comment, non-header line
|
|
750
|
+
const lines = prdContent.split('\n').filter(l => l.trim() && !l.startsWith('#') && !l.startsWith('<!--'));
|
|
751
|
+
if (lines[0]) {
|
|
752
|
+
state.prdSummary = lines[0].substring(0, 100);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
catch {
|
|
757
|
+
// Ignore read errors
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
// Read PROJECT-STATE.md for tasks
|
|
761
|
+
const projectStatePath = (0, path_1.join)(cwd, 'PROJECT-STATE.md');
|
|
762
|
+
if ((0, fs_1.existsSync)(projectStatePath)) {
|
|
763
|
+
try {
|
|
764
|
+
const content = (0, fs_1.readFileSync)(projectStatePath, 'utf-8');
|
|
765
|
+
// Extract In Progress section
|
|
766
|
+
const inProgressMatch = content.match(/## In Progress\n([\s\S]*?)(?=\n##|$)/);
|
|
767
|
+
if (inProgressMatch) {
|
|
768
|
+
const lines = inProgressMatch[1].split('\n')
|
|
769
|
+
.filter(l => l.trim().startsWith('-'))
|
|
770
|
+
.map(l => l.replace(/^-\s*/, '').trim())
|
|
771
|
+
.filter(l => l && !l.startsWith('<!--'));
|
|
772
|
+
state.inProgressTasks = lines;
|
|
773
|
+
}
|
|
774
|
+
// Extract Completed section (last 5)
|
|
775
|
+
const completedMatch = content.match(/## Completed\n([\s\S]*?)(?=\n##|$)/);
|
|
776
|
+
if (completedMatch) {
|
|
777
|
+
const lines = completedMatch[1].split('\n')
|
|
778
|
+
.filter(l => l.trim().startsWith('-'))
|
|
779
|
+
.map(l => l.replace(/^-\s*/, '').trim())
|
|
780
|
+
.filter(l => l && !l.startsWith('<!--'));
|
|
781
|
+
state.completedTasks = lines.slice(-5);
|
|
782
|
+
}
|
|
783
|
+
// Extract Blockers section
|
|
784
|
+
const blockersMatch = content.match(/## Blockers\n([\s\S]*?)(?=\n##|$)/);
|
|
785
|
+
if (blockersMatch) {
|
|
786
|
+
const lines = blockersMatch[1].split('\n')
|
|
787
|
+
.filter(l => l.trim().startsWith('-'))
|
|
788
|
+
.map(l => l.replace(/^-\s*/, '').trim())
|
|
789
|
+
.filter(l => l && !l.startsWith('<!--'));
|
|
790
|
+
state.blockers = lines;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
catch {
|
|
794
|
+
// Ignore read errors
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
// Read DEVLOG for last session
|
|
798
|
+
const devlogPath = (0, path_1.join)(cwd, '.codebakers', 'DEVLOG.md');
|
|
799
|
+
if ((0, fs_1.existsSync)(devlogPath)) {
|
|
800
|
+
try {
|
|
801
|
+
const content = (0, fs_1.readFileSync)(devlogPath, 'utf-8');
|
|
802
|
+
// Get first session entry
|
|
803
|
+
const sessionMatch = content.match(/## .+?\n\*\*Session:\*\*\s*(.+)/);
|
|
804
|
+
if (sessionMatch) {
|
|
805
|
+
state.lastSession = sessionMatch[1].trim();
|
|
806
|
+
}
|
|
807
|
+
// Get "What was done" from most recent entry
|
|
808
|
+
const whatDoneMatch = content.match(/### What was done:\n([\s\S]*?)(?=\n###|---|\n\n)/);
|
|
809
|
+
if (whatDoneMatch && !state.lastSession) {
|
|
810
|
+
const lines = whatDoneMatch[1].split('\n')
|
|
811
|
+
.filter(l => l.trim().startsWith('-'))
|
|
812
|
+
.map(l => l.replace(/^-\s*/, '').trim());
|
|
813
|
+
if (lines[0]) {
|
|
814
|
+
state.lastSession = lines[0];
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
catch {
|
|
819
|
+
// Ignore read errors
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
// Determine suggestion based on state
|
|
823
|
+
if (state.blockers.length > 0) {
|
|
824
|
+
state.suggestion = `BLOCKED: ${state.blockers[0]}. Address this blocker first.`;
|
|
825
|
+
}
|
|
826
|
+
else if (state.inProgressTasks.length > 0) {
|
|
827
|
+
state.suggestion = `CONTINUE: ${state.inProgressTasks[0]}`;
|
|
828
|
+
}
|
|
829
|
+
else if (state.hasPrd && state.completedTasks.length === 0) {
|
|
830
|
+
state.suggestion = `START BUILDING: PRD exists. Begin implementing features from PRD.md`;
|
|
831
|
+
}
|
|
832
|
+
else if (!state.hasPrd) {
|
|
833
|
+
state.suggestion = `DEFINE PROJECT: No PRD found. Describe what you want to build.`;
|
|
834
|
+
}
|
|
835
|
+
else {
|
|
836
|
+
state.suggestion = `READY: Project set up. Ask for the next feature to build.`;
|
|
837
|
+
}
|
|
838
|
+
return state;
|
|
839
|
+
}
|
|
840
|
+
function showResumeContext(state) {
|
|
841
|
+
console.log(chalk_1.default.blue(`
|
|
842
|
+
╔═══════════════════════════════════════════════════════════╗
|
|
843
|
+
║ ║
|
|
844
|
+
║ ${chalk_1.default.bold.white('CodeBakers - Resuming Session')} ║
|
|
845
|
+
║ ║
|
|
846
|
+
╚═══════════════════════════════════════════════════════════╝
|
|
847
|
+
`));
|
|
848
|
+
console.log(chalk_1.default.white(` 📁 Project: ${chalk_1.default.cyan(state.projectName || 'Unknown')}`));
|
|
849
|
+
if (state.prdSummary) {
|
|
850
|
+
console.log(chalk_1.default.gray(` 📝 ${state.prdSummary}`));
|
|
851
|
+
}
|
|
852
|
+
console.log('');
|
|
853
|
+
// Show blockers first (critical)
|
|
854
|
+
if (state.blockers.length > 0) {
|
|
855
|
+
console.log(chalk_1.default.red(' ⚠️ BLOCKERS:'));
|
|
856
|
+
for (const blocker of state.blockers) {
|
|
857
|
+
console.log(chalk_1.default.red(` • ${blocker}`));
|
|
858
|
+
}
|
|
859
|
+
console.log('');
|
|
860
|
+
}
|
|
861
|
+
// Show in-progress tasks
|
|
862
|
+
if (state.inProgressTasks.length > 0) {
|
|
863
|
+
console.log(chalk_1.default.yellow(' 🔄 IN PROGRESS:'));
|
|
864
|
+
for (const task of state.inProgressTasks) {
|
|
865
|
+
console.log(chalk_1.default.yellow(` • ${task}`));
|
|
866
|
+
}
|
|
867
|
+
console.log('');
|
|
868
|
+
}
|
|
869
|
+
// Show recent completed (context)
|
|
870
|
+
if (state.completedTasks.length > 0) {
|
|
871
|
+
console.log(chalk_1.default.green(' ✓ RECENTLY COMPLETED:'));
|
|
872
|
+
for (const task of state.completedTasks.slice(-3)) {
|
|
873
|
+
console.log(chalk_1.default.gray(` • ${task}`));
|
|
874
|
+
}
|
|
875
|
+
console.log('');
|
|
876
|
+
}
|
|
877
|
+
// Show last session timestamp if available
|
|
878
|
+
if (state.lastSession) {
|
|
879
|
+
console.log(chalk_1.default.gray(` 📅 Last session: ${state.lastSession}`));
|
|
880
|
+
console.log('');
|
|
881
|
+
}
|
|
882
|
+
// Show the suggestion prominently
|
|
883
|
+
console.log(chalk_1.default.cyan(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
884
|
+
console.log(chalk_1.default.white.bold(`\n → ${state.suggestion}\n`));
|
|
885
|
+
console.log(chalk_1.default.cyan(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
|
|
886
|
+
// Output machine-readable context for AI
|
|
887
|
+
console.log(chalk_1.default.gray(' [AI Context]'));
|
|
888
|
+
console.log(chalk_1.default.gray(` Project: ${state.projectName || 'Unknown'}`));
|
|
889
|
+
console.log(chalk_1.default.gray(` Status: ${state.inProgressTasks.length > 0 ? 'IN_PROGRESS' : state.blockers.length > 0 ? 'BLOCKED' : 'READY'}`));
|
|
890
|
+
console.log(chalk_1.default.gray(` Next Action: ${state.suggestion}`));
|
|
891
|
+
if (state.hasPrd) {
|
|
892
|
+
console.log(chalk_1.default.gray(` PRD: Available at PRD.md`));
|
|
893
|
+
}
|
|
894
|
+
console.log('');
|
|
895
|
+
}
|
|
712
896
|
/**
|
|
713
897
|
* Get CLI version from package.json
|
|
714
898
|
*/
|
|
@@ -754,11 +938,42 @@ function log(message, options) {
|
|
|
754
938
|
/**
|
|
755
939
|
* Zero-friction entry point - start using CodeBakers instantly
|
|
756
940
|
* Single command for both trial and paid users
|
|
941
|
+
*
|
|
942
|
+
* SMART BEHAVIOR:
|
|
943
|
+
* - If CodeBakers already set up → Show context and resume from where you left off
|
|
944
|
+
* - If not set up → Run first-time setup (trial or login)
|
|
757
945
|
*/
|
|
758
946
|
async function go(options = {}) {
|
|
759
947
|
log('Starting go command...', options);
|
|
760
948
|
log(`API URL: ${(0, config_js_1.getApiUrl)()}`, options);
|
|
761
949
|
log(`Working directory: ${process.cwd()}`, options);
|
|
950
|
+
const cwd = process.cwd();
|
|
951
|
+
// =========================================================================
|
|
952
|
+
// SMART CONTEXT CHECK - If already set up, show resume context
|
|
953
|
+
// =========================================================================
|
|
954
|
+
const projectState = analyzeProjectState(cwd);
|
|
955
|
+
if (projectState.isSetUp) {
|
|
956
|
+
// Project already has CodeBakers - show context and resume
|
|
957
|
+
showResumeContext(projectState);
|
|
958
|
+
// Verify auth is still valid
|
|
959
|
+
const existingApiKey = (0, config_js_1.getApiKey)();
|
|
960
|
+
const existingTrial = (0, config_js_1.getTrialState)();
|
|
961
|
+
if (existingApiKey) {
|
|
962
|
+
console.log(chalk_1.default.green(' ✓ Authenticated (API key)\n'));
|
|
963
|
+
}
|
|
964
|
+
else if (existingTrial && !(0, config_js_1.isTrialExpired)()) {
|
|
965
|
+
const daysRemaining = (0, config_js_1.getTrialDaysRemaining)();
|
|
966
|
+
console.log(chalk_1.default.green(` ✓ Trial active (${daysRemaining} days remaining)\n`));
|
|
967
|
+
}
|
|
968
|
+
else if (existingTrial && (0, config_js_1.isTrialExpired)()) {
|
|
969
|
+
console.log(chalk_1.default.yellow(' ⚠️ Trial expired. Run `codebakers extend` or login.\n'));
|
|
970
|
+
}
|
|
971
|
+
// Don't run setup again - just show context
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
// =========================================================================
|
|
975
|
+
// FIRST-TIME SETUP - Project not yet configured
|
|
976
|
+
// =========================================================================
|
|
762
977
|
console.log(chalk_1.default.blue(`
|
|
763
978
|
╔═══════════════════════════════════════════════════════════╗
|
|
764
979
|
║ ║
|
package/package.json
CHANGED
package/src/commands/go.ts
CHANGED
|
@@ -778,6 +778,222 @@ interface GoOptions {
|
|
|
778
778
|
skipReview?: boolean;
|
|
779
779
|
}
|
|
780
780
|
|
|
781
|
+
// ============================================================================
|
|
782
|
+
// SMART CONTEXT DETECTION - "Where am I? What's next?"
|
|
783
|
+
// ============================================================================
|
|
784
|
+
|
|
785
|
+
interface ProjectState {
|
|
786
|
+
isSetUp: boolean;
|
|
787
|
+
projectName?: string;
|
|
788
|
+
projectType?: string;
|
|
789
|
+
hasPrd: boolean;
|
|
790
|
+
prdSummary?: string;
|
|
791
|
+
inProgressTasks: string[];
|
|
792
|
+
completedTasks: string[];
|
|
793
|
+
blockers: string[];
|
|
794
|
+
lastSession?: string;
|
|
795
|
+
suggestion: string;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
function analyzeProjectState(cwd: string): ProjectState {
|
|
799
|
+
const state: ProjectState = {
|
|
800
|
+
isSetUp: false,
|
|
801
|
+
hasPrd: false,
|
|
802
|
+
inProgressTasks: [],
|
|
803
|
+
completedTasks: [],
|
|
804
|
+
blockers: [],
|
|
805
|
+
suggestion: '',
|
|
806
|
+
};
|
|
807
|
+
|
|
808
|
+
// Check if CodeBakers is set up
|
|
809
|
+
const codebakersJsonPath = join(cwd, '.codebakers.json');
|
|
810
|
+
if (!existsSync(codebakersJsonPath)) {
|
|
811
|
+
state.suggestion = 'Project not set up. Running first-time setup...';
|
|
812
|
+
return state;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
state.isSetUp = true;
|
|
816
|
+
|
|
817
|
+
// Read .codebakers.json
|
|
818
|
+
try {
|
|
819
|
+
const cbState = JSON.parse(readFileSync(codebakersJsonPath, 'utf-8'));
|
|
820
|
+
state.projectName = cbState.projectName;
|
|
821
|
+
state.projectType = cbState.projectType;
|
|
822
|
+
} catch {
|
|
823
|
+
// Ignore parse errors
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// Check for PRD.md
|
|
827
|
+
const prdPath = join(cwd, 'PRD.md');
|
|
828
|
+
if (existsSync(prdPath)) {
|
|
829
|
+
state.hasPrd = true;
|
|
830
|
+
try {
|
|
831
|
+
const prdContent = readFileSync(prdPath, 'utf-8');
|
|
832
|
+
// Extract one-liner if present
|
|
833
|
+
const oneLineMatch = prdContent.match(/\*\*One-liner:\*\*\s*(.+)/);
|
|
834
|
+
if (oneLineMatch) {
|
|
835
|
+
state.prdSummary = oneLineMatch[1].trim();
|
|
836
|
+
} else {
|
|
837
|
+
// Get first non-comment, non-header line
|
|
838
|
+
const lines = prdContent.split('\n').filter(l =>
|
|
839
|
+
l.trim() && !l.startsWith('#') && !l.startsWith('<!--')
|
|
840
|
+
);
|
|
841
|
+
if (lines[0]) {
|
|
842
|
+
state.prdSummary = lines[0].substring(0, 100);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
} catch {
|
|
846
|
+
// Ignore read errors
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// Read PROJECT-STATE.md for tasks
|
|
851
|
+
const projectStatePath = join(cwd, 'PROJECT-STATE.md');
|
|
852
|
+
if (existsSync(projectStatePath)) {
|
|
853
|
+
try {
|
|
854
|
+
const content = readFileSync(projectStatePath, 'utf-8');
|
|
855
|
+
|
|
856
|
+
// Extract In Progress section
|
|
857
|
+
const inProgressMatch = content.match(/## In Progress\n([\s\S]*?)(?=\n##|$)/);
|
|
858
|
+
if (inProgressMatch) {
|
|
859
|
+
const lines = inProgressMatch[1].split('\n')
|
|
860
|
+
.filter(l => l.trim().startsWith('-'))
|
|
861
|
+
.map(l => l.replace(/^-\s*/, '').trim())
|
|
862
|
+
.filter(l => l && !l.startsWith('<!--'));
|
|
863
|
+
state.inProgressTasks = lines;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// Extract Completed section (last 5)
|
|
867
|
+
const completedMatch = content.match(/## Completed\n([\s\S]*?)(?=\n##|$)/);
|
|
868
|
+
if (completedMatch) {
|
|
869
|
+
const lines = completedMatch[1].split('\n')
|
|
870
|
+
.filter(l => l.trim().startsWith('-'))
|
|
871
|
+
.map(l => l.replace(/^-\s*/, '').trim())
|
|
872
|
+
.filter(l => l && !l.startsWith('<!--'));
|
|
873
|
+
state.completedTasks = lines.slice(-5);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
// Extract Blockers section
|
|
877
|
+
const blockersMatch = content.match(/## Blockers\n([\s\S]*?)(?=\n##|$)/);
|
|
878
|
+
if (blockersMatch) {
|
|
879
|
+
const lines = blockersMatch[1].split('\n')
|
|
880
|
+
.filter(l => l.trim().startsWith('-'))
|
|
881
|
+
.map(l => l.replace(/^-\s*/, '').trim())
|
|
882
|
+
.filter(l => l && !l.startsWith('<!--'));
|
|
883
|
+
state.blockers = lines;
|
|
884
|
+
}
|
|
885
|
+
} catch {
|
|
886
|
+
// Ignore read errors
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// Read DEVLOG for last session
|
|
891
|
+
const devlogPath = join(cwd, '.codebakers', 'DEVLOG.md');
|
|
892
|
+
if (existsSync(devlogPath)) {
|
|
893
|
+
try {
|
|
894
|
+
const content = readFileSync(devlogPath, 'utf-8');
|
|
895
|
+
// Get first session entry
|
|
896
|
+
const sessionMatch = content.match(/## .+?\n\*\*Session:\*\*\s*(.+)/);
|
|
897
|
+
if (sessionMatch) {
|
|
898
|
+
state.lastSession = sessionMatch[1].trim();
|
|
899
|
+
}
|
|
900
|
+
// Get "What was done" from most recent entry
|
|
901
|
+
const whatDoneMatch = content.match(/### What was done:\n([\s\S]*?)(?=\n###|---|\n\n)/);
|
|
902
|
+
if (whatDoneMatch && !state.lastSession) {
|
|
903
|
+
const lines = whatDoneMatch[1].split('\n')
|
|
904
|
+
.filter(l => l.trim().startsWith('-'))
|
|
905
|
+
.map(l => l.replace(/^-\s*/, '').trim());
|
|
906
|
+
if (lines[0]) {
|
|
907
|
+
state.lastSession = lines[0];
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
} catch {
|
|
911
|
+
// Ignore read errors
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// Determine suggestion based on state
|
|
916
|
+
if (state.blockers.length > 0) {
|
|
917
|
+
state.suggestion = `BLOCKED: ${state.blockers[0]}. Address this blocker first.`;
|
|
918
|
+
} else if (state.inProgressTasks.length > 0) {
|
|
919
|
+
state.suggestion = `CONTINUE: ${state.inProgressTasks[0]}`;
|
|
920
|
+
} else if (state.hasPrd && state.completedTasks.length === 0) {
|
|
921
|
+
state.suggestion = `START BUILDING: PRD exists. Begin implementing features from PRD.md`;
|
|
922
|
+
} else if (!state.hasPrd) {
|
|
923
|
+
state.suggestion = `DEFINE PROJECT: No PRD found. Describe what you want to build.`;
|
|
924
|
+
} else {
|
|
925
|
+
state.suggestion = `READY: Project set up. Ask for the next feature to build.`;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
return state;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
function showResumeContext(state: ProjectState): void {
|
|
932
|
+
console.log(chalk.blue(`
|
|
933
|
+
╔═══════════════════════════════════════════════════════════╗
|
|
934
|
+
║ ║
|
|
935
|
+
║ ${chalk.bold.white('CodeBakers - Resuming Session')} ║
|
|
936
|
+
║ ║
|
|
937
|
+
╚═══════════════════════════════════════════════════════════╝
|
|
938
|
+
`));
|
|
939
|
+
|
|
940
|
+
console.log(chalk.white(` 📁 Project: ${chalk.cyan(state.projectName || 'Unknown')}`));
|
|
941
|
+
|
|
942
|
+
if (state.prdSummary) {
|
|
943
|
+
console.log(chalk.gray(` 📝 ${state.prdSummary}`));
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
console.log('');
|
|
947
|
+
|
|
948
|
+
// Show blockers first (critical)
|
|
949
|
+
if (state.blockers.length > 0) {
|
|
950
|
+
console.log(chalk.red(' ⚠️ BLOCKERS:'));
|
|
951
|
+
for (const blocker of state.blockers) {
|
|
952
|
+
console.log(chalk.red(` • ${blocker}`));
|
|
953
|
+
}
|
|
954
|
+
console.log('');
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
// Show in-progress tasks
|
|
958
|
+
if (state.inProgressTasks.length > 0) {
|
|
959
|
+
console.log(chalk.yellow(' 🔄 IN PROGRESS:'));
|
|
960
|
+
for (const task of state.inProgressTasks) {
|
|
961
|
+
console.log(chalk.yellow(` • ${task}`));
|
|
962
|
+
}
|
|
963
|
+
console.log('');
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// Show recent completed (context)
|
|
967
|
+
if (state.completedTasks.length > 0) {
|
|
968
|
+
console.log(chalk.green(' ✓ RECENTLY COMPLETED:'));
|
|
969
|
+
for (const task of state.completedTasks.slice(-3)) {
|
|
970
|
+
console.log(chalk.gray(` • ${task}`));
|
|
971
|
+
}
|
|
972
|
+
console.log('');
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
// Show last session timestamp if available
|
|
976
|
+
if (state.lastSession) {
|
|
977
|
+
console.log(chalk.gray(` 📅 Last session: ${state.lastSession}`));
|
|
978
|
+
console.log('');
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
// Show the suggestion prominently
|
|
982
|
+
console.log(chalk.cyan(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
983
|
+
console.log(chalk.white.bold(`\n → ${state.suggestion}\n`));
|
|
984
|
+
console.log(chalk.cyan(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
|
|
985
|
+
|
|
986
|
+
// Output machine-readable context for AI
|
|
987
|
+
console.log(chalk.gray(' [AI Context]'));
|
|
988
|
+
console.log(chalk.gray(` Project: ${state.projectName || 'Unknown'}`));
|
|
989
|
+
console.log(chalk.gray(` Status: ${state.inProgressTasks.length > 0 ? 'IN_PROGRESS' : state.blockers.length > 0 ? 'BLOCKED' : 'READY'}`));
|
|
990
|
+
console.log(chalk.gray(` Next Action: ${state.suggestion}`));
|
|
991
|
+
if (state.hasPrd) {
|
|
992
|
+
console.log(chalk.gray(` PRD: Available at PRD.md`));
|
|
993
|
+
}
|
|
994
|
+
console.log('');
|
|
995
|
+
}
|
|
996
|
+
|
|
781
997
|
interface ConfirmData {
|
|
782
998
|
version: string;
|
|
783
999
|
moduleCount: number;
|
|
@@ -838,12 +1054,48 @@ function log(message: string, options?: GoOptions): void {
|
|
|
838
1054
|
/**
|
|
839
1055
|
* Zero-friction entry point - start using CodeBakers instantly
|
|
840
1056
|
* Single command for both trial and paid users
|
|
1057
|
+
*
|
|
1058
|
+
* SMART BEHAVIOR:
|
|
1059
|
+
* - If CodeBakers already set up → Show context and resume from where you left off
|
|
1060
|
+
* - If not set up → Run first-time setup (trial or login)
|
|
841
1061
|
*/
|
|
842
1062
|
export async function go(options: GoOptions = {}): Promise<void> {
|
|
843
1063
|
log('Starting go command...', options);
|
|
844
1064
|
log(`API URL: ${getApiUrl()}`, options);
|
|
845
1065
|
log(`Working directory: ${process.cwd()}`, options);
|
|
846
1066
|
|
|
1067
|
+
const cwd = process.cwd();
|
|
1068
|
+
|
|
1069
|
+
// =========================================================================
|
|
1070
|
+
// SMART CONTEXT CHECK - If already set up, show resume context
|
|
1071
|
+
// =========================================================================
|
|
1072
|
+
const projectState = analyzeProjectState(cwd);
|
|
1073
|
+
|
|
1074
|
+
if (projectState.isSetUp) {
|
|
1075
|
+
// Project already has CodeBakers - show context and resume
|
|
1076
|
+
showResumeContext(projectState);
|
|
1077
|
+
|
|
1078
|
+
// Verify auth is still valid
|
|
1079
|
+
const existingApiKey = getApiKey();
|
|
1080
|
+
const existingTrial = getTrialState();
|
|
1081
|
+
|
|
1082
|
+
if (existingApiKey) {
|
|
1083
|
+
console.log(chalk.green(' ✓ Authenticated (API key)\n'));
|
|
1084
|
+
} else if (existingTrial && !isTrialExpired()) {
|
|
1085
|
+
const daysRemaining = getTrialDaysRemaining();
|
|
1086
|
+
console.log(chalk.green(` ✓ Trial active (${daysRemaining} days remaining)\n`));
|
|
1087
|
+
} else if (existingTrial && isTrialExpired()) {
|
|
1088
|
+
console.log(chalk.yellow(' ⚠️ Trial expired. Run `codebakers extend` or login.\n'));
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
// Don't run setup again - just show context
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
// =========================================================================
|
|
1096
|
+
// FIRST-TIME SETUP - Project not yet configured
|
|
1097
|
+
// =========================================================================
|
|
1098
|
+
|
|
847
1099
|
console.log(chalk.blue(`
|
|
848
1100
|
╔═══════════════════════════════════════════════════════════╗
|
|
849
1101
|
║ ║
|