Skip to content

Commit e2a7bc6

Browse files
committed
fix: integrate actual project generation into wizard
- Wizard now calls generator.Orchestrate() when entering generating state - Generation runs asynchronously so UI doesn't freeze - Progress updates properly when generation completes - Shows success/error states based on actual generation results - Fixes issue where CLI was freezing at 0% progress
1 parent 5ca9876 commit e2a7bc6

6 files changed

Lines changed: 107 additions & 24 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# GoPlan-CLI
22

3-
Generated by [DoPlan](https://github.com/dorgham/doplan) - Zero-install AI Project Director
3+
Generated by [DoPlan](https://github.com/DoPlan-dev/CLI) - Zero-install AI Project Director
44

55
## Quick Start
66

@@ -94,7 +94,7 @@ All documentation is in .plan/
9494

9595
## Support
9696

97-
For issues or questions, visit: https://github.com/DoPlan-dev/CLI/
97+
For issues or questions, visit: https://github.com/DoPlan-dev/CLI
9898

9999
---
100100

bin/doplan.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ if (!fs.existsSync(binaryPath)) {
4141
process.exit(1);
4242
}
4343
} else {
44-
console.error('Error: DoPlan CLI binary not found.');
45-
console.error(`Expected: ${binaryPath}`);
46-
console.error('Please run: npm install');
47-
process.exit(1);
44+
console.error('Error: DoPlan CLI binary not found.');
45+
console.error(`Expected: ${binaryPath}`);
46+
console.error('Please run: npm install');
47+
process.exit(1);
4848
}
4949
}
5050

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
4545
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
4646
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
4747
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
48+
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
49+
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
4850
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
4951
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
5052
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

internal/cli/root.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"fmt"
55
"os"
66

7-
"github.com/doplan/cli/internal/generator"
87
"github.com/doplan/cli/internal/tui"
98
"github.com/doplan/cli/internal/version"
109
"github.com/spf13/cobra"
@@ -83,11 +82,8 @@ func runWizard() error {
8382
return nil
8483
}
8584

86-
// Generate the project
87-
if err := generator.Orchestrate(request); err != nil {
88-
return fmt.Errorf("failed to generate project: %w", err)
89-
}
90-
85+
// Generation is now handled inside the wizard, so if we get here,
86+
// the project was successfully created
9187
fmt.Printf("\n✨ Project '%s' created successfully!\n", request.ProjectName)
9288
fmt.Printf("Open with: %s ./%s\n", getIDECommand(request.IDE), request.ProjectName)
9389
fmt.Printf("Then type /tell to begin\n")

internal/generator/docs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func generateREADME(projectPath string, request *models.ProjectRequest) error {
4949

5050
content := `# ` + request.ProjectName + `
5151
52-
Generated by [DoPlan](https://github.com/dorgham/doplan) - Zero-install AI Project Director
52+
Generated by [DoPlan](https://github.com/DoPlan-dev/CLI) - Zero-install AI Project Director
5353
5454
## Quick Start
5555

internal/tui/wizard.go

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/charmbracelet/bubbles/textinput"
1010
tea "github.com/charmbracelet/bubbletea"
1111
"github.com/charmbracelet/lipgloss"
12+
"github.com/doplan/cli/internal/generator"
1213
"github.com/doplan/cli/pkg/models"
1314
)
1415

@@ -75,6 +76,18 @@ type Model struct {
7576
errorSuggestion string
7677
previousState wizardState // Store previous state for recovery
7778
stateHistory []wizardState // History for back navigation
79+
generationDone bool // Track if generation has completed
80+
generationErr error // Store generation error if any
81+
}
82+
83+
// generationCompleteMsg is sent when generation completes
84+
type generationCompleteMsg struct {
85+
err error
86+
}
87+
88+
// stepProgressMsg is sent when a step completes
89+
type stepProgressMsg struct {
90+
stepIndex int
7891
}
7992

8093
// IDEInfo contains information about an IDE option
@@ -327,7 +340,8 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
327340
if len(m.steps) > 0 {
328341
m.steps[0].Status = stepInProgress
329342
}
330-
return m, tickSpinner
343+
// Start actual generation in background
344+
return m, tea.Batch(tickSpinner, startGeneration(m))
331345
}
332346
}
333347
return m, nil
@@ -377,22 +391,64 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
377391
// Handle spinner tick
378392
if m.state == stateGenerating {
379393
m.spinnerFrame++
380-
// Simulate progress (for demo purposes)
381-
// In real implementation, this would be driven by actual generation progress
382-
// After a few ticks, transition to success (simulating completion)
383-
if m.spinnerFrame > 30 {
384-
// Mark all steps as completed
385-
for i := range m.steps {
386-
m.steps[i].Status = stepCompleted
394+
// Continue spinner animation while generating
395+
if m.generationDone {
396+
// Generation completed, stop spinner
397+
if m.generationErr != nil {
398+
// Transition to error state
399+
m.state = stateError
400+
m.errorMessage = m.generationErr.Error()
401+
m.errorSuggestion = "Please check the error message above and try again."
402+
return m, nil
403+
} else {
404+
// Mark all steps as completed and transition to success
405+
for i := range m.steps {
406+
m.steps[i].Status = stepCompleted
407+
}
408+
m.state = stateSuccess
409+
return m, nil
387410
}
388-
// Transition to success state
389-
m.state = stateSuccess
390-
return m, nil
391411
}
412+
// Update progress based on elapsed time (fallback if no step updates)
413+
// This provides visual feedback while generation is running
392414
return m, tickSpinner
393415
}
394416
return m, nil
395417

418+
case generationCompleteMsg:
419+
// Generation completed
420+
m.generationDone = true
421+
m.generationErr = msg.err
422+
if msg.err != nil {
423+
// Transition to error state
424+
m.state = stateError
425+
m.errorMessage = msg.err.Error()
426+
m.errorSuggestion = "Please check the error message above and try again."
427+
return m, nil
428+
} else {
429+
// Mark all steps as completed
430+
for i := range m.steps {
431+
m.steps[i].Status = stepCompleted
432+
}
433+
// Transition to success state
434+
m.state = stateSuccess
435+
return m, nil
436+
}
437+
438+
case stepProgressMsg:
439+
// Update step progress
440+
if msg.stepIndex < len(m.steps) {
441+
// Mark current step as completed
442+
if msg.stepIndex > 0 {
443+
m.steps[msg.stepIndex-1].Status = stepCompleted
444+
}
445+
// Mark next step as in progress
446+
if msg.stepIndex < len(m.steps) {
447+
m.steps[msg.stepIndex].Status = stepInProgress
448+
}
449+
}
450+
return m, nil
451+
396452
default:
397453
// Handle text input messages
398454
if m.state == stateProjectName {
@@ -1175,3 +1231,32 @@ func Run() (*models.ProjectRequest, error) {
11751231
// User quit or error occurred
11761232
return nil, nil
11771233
}
1234+
1235+
// startGeneration starts the project generation in a goroutine
1236+
func startGeneration(m Model) tea.Cmd {
1237+
return func() tea.Msg {
1238+
// Create project request
1239+
request := m.toProjectRequest()
1240+
if err := request.Validate(); err != nil {
1241+
return generationCompleteMsg{err: fmt.Errorf("invalid project request: %w", err)}
1242+
}
1243+
1244+
// Run generation in a goroutine to avoid blocking
1245+
// This allows the UI to continue updating while generation happens
1246+
errChan := make(chan error, 1)
1247+
go func() {
1248+
if err := generator.Orchestrate(request); err != nil {
1249+
errChan <- fmt.Errorf("generation failed: %w", err)
1250+
} else {
1251+
errChan <- nil
1252+
}
1253+
}()
1254+
1255+
// Wait for generation to complete
1256+
if err := <-errChan; err != nil {
1257+
return generationCompleteMsg{err: err}
1258+
}
1259+
1260+
return generationCompleteMsg{err: nil}
1261+
}
1262+
}

0 commit comments

Comments
 (0)