@@ -12,20 +12,26 @@ import (
1212 "gptcode/internal/agents"
1313 "gptcode/internal/config"
1414 "gptcode/internal/feedback"
15+ "gptcode/internal/live"
1516 "gptcode/internal/llm"
1617 "gptcode/internal/observability"
1718)
1819
20+ // ProgressCallback is called during execution to report progress
21+ type ProgressCallback func (phase string , details string )
22+
1923// Conductor is the central coordinator (Maestro) that orchestrates all agents
2024type Conductor struct {
21- selector * config.ModelSelector
22- setup * config.Setup
23- cwd string
24- language string
25- Recovery * RecoveryStrategy
26- Tracer observability.Tracer
27- Observer * observability.AgentObserver // For tracking and summary
28- loopDetector * llm.LoopDetector // Centralized Claude Code-style loop detection
25+ selector * config.ModelSelector
26+ setup * config.Setup
27+ cwd string
28+ language string
29+ Recovery * RecoveryStrategy
30+ Tracer observability.Tracer
31+ Observer * observability.AgentObserver // For tracking and summary
32+ loopDetector * llm.LoopDetector // Centralized Claude Code-style loop detection
33+ liveReportConfig * live.ReportConfig // For Live Dashboard HTTP reporting
34+ progressCallback ProgressCallback // For real-time progress updates
2935}
3036
3137// NewConductor creates a new Maestro conductor
@@ -55,6 +61,26 @@ func NewConductor(
5561 }
5662}
5763
64+ // SetLiveReportConfig sets the Live Dashboard HTTP reporting configuration
65+ func (c * Conductor ) SetLiveReportConfig (reportConfig * live.ReportConfig ) {
66+ c .liveReportConfig = reportConfig
67+ }
68+
69+ // SetProgressCallback sets the callback for real-time progress updates
70+ func (c * Conductor ) SetProgressCallback (callback ProgressCallback ) {
71+ c .progressCallback = callback
72+ }
73+
74+ // reportProgress sends progress to Live Dashboard and calls progress callback
75+ func (c * Conductor ) reportProgress (phase string , details string ) {
76+ if c .liveReportConfig != nil {
77+ c .liveReportConfig .Step (phase + ": " + details , "step" )
78+ }
79+ if c .progressCallback != nil {
80+ c .progressCallback (phase , details )
81+ }
82+ }
83+
5884// ExecuteTask orchestrates the execution of a task
5985func (c * Conductor ) ExecuteTask (ctx context.Context , task string , complexity string ) error {
6086 if os .Getenv ("GPTCODE_DEBUG" ) == "1" {
@@ -95,9 +121,11 @@ func (c *Conductor) ExecuteTask(ctx context.Context, task string, complexity str
95121 planner := agents .NewPlanner (planProvider , planModel )
96122
97123 fmt .Println ("Creating plan..." )
124+ c .reportProgress ("planning" , "Creating plan" )
98125 start := time .Now ()
99126 plan , err := planner .CreatePlan (ctx , task , "" , nil )
100127 elapsed := time .Since (start )
128+ c .reportProgress ("planning" , "Plan created" )
101129 c .selector .RecordUsage (planBackend , planModel , err == nil , errorMsg (err ))
102130 if err != nil {
103131 return fmt .Errorf ("planning failed: %w" , err )
@@ -142,6 +170,9 @@ func (c *Conductor) ExecuteTask(ctx context.Context, task string, complexity str
142170 attempt := c .loopDetector .Iteration
143171 if attempt > 1 {
144172 fmt .Printf ("Retrying (attempt %d)...\n " , attempt )
173+ c .reportProgress ("retry" , fmt .Sprintf ("Attempt %d" , attempt ))
174+ } else {
175+ c .reportProgress ("editing" , "Starting code changes" )
145176 }
146177
147178 // Select model for editing
@@ -166,9 +197,11 @@ func (c *Conductor) ExecuteTask(ctx context.Context, task string, complexity str
166197
167198 // Execute with editor
168199 fmt .Println ("Executing changes..." )
200+ c .reportProgress ("editing" , "Executing code changes" )
169201 start = time .Now ()
170202 result , modifiedFiles , err := editor .Execute (ctx , history , nil )
171203 elapsed = time .Since (start )
204+ c .reportProgress ("editing" , fmt .Sprintf ("Completed - %d files changed" , len (modifiedFiles )))
172205 c .selector .RecordUsage (editBackend , editModel , err == nil , errorMsg (err ))
173206 if err != nil {
174207 // LoopDetector will handle max iterations check on next iteration
@@ -256,9 +289,11 @@ func (c *Conductor) ExecuteTask(ctx context.Context, task string, complexity str
256289
257290 // Validate
258291 fmt .Println ("Validating..." )
292+ c .reportProgress ("validation" , "Running tests and checks" )
259293 start = time .Now ()
260294 review , err := reviewer .Review (ctx , plan , modifiedFiles , nil )
261295 elapsed = time .Since (start )
296+ c .reportProgress ("validation" , "Validation complete" )
262297 c .selector .RecordUsage (reviewBackend , reviewModel , err == nil , errorMsg (err ))
263298 if err != nil {
264299 // LoopDetector will handle max iterations check on next iteration
@@ -469,10 +504,11 @@ func (c *Conductor) formatValidationIssues(issues []string) string {
469504 hasPackageError := false
470505 hasSnapshotFailure := false
471506 for _ , issue := range issues {
507+ lowerIssue := strings .ToLower (issue )
472508 if strings .Contains (issue , "found packages" ) {
473509 hasPackageError = true
474510 }
475- if strings .Contains (strings . ToLower ( issue ) , "snapshot" ) {
511+ if strings .Contains (lowerIssue , "snapshot" ) {
476512 hasSnapshotFailure = true
477513 }
478514 }
0 commit comments