Skip to content

Commit b6f9fd9

Browse files
author
Test
committed
feat: add AutoEditor and Telemetry for enhanced autonomous execution
AutoEditor: - Integrates healer, retry, learning, and context management - Automatic error recovery and self-healing - Multi-editor for concurrent task execution Telemetry: - Session tracking and metrics collection - Cost and token usage monitoring - Performance tracking and reporting - MetricsCollector for detailed analytics - PerformanceTracker for task-level metrics
1 parent 7dc9714 commit b6f9fd9

2 files changed

Lines changed: 486 additions & 0 deletions

File tree

internal/autonomous/auto_editor.go

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
package autonomous
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"sync"
7+
"time"
8+
9+
"gptcode/internal/maestro"
10+
)
11+
12+
type AutoEditor struct {
13+
maestro *maestro.Conductor
14+
healer *SelfHealer
15+
retry *SmartRetry
16+
learning *LearningEngine
17+
context *ContextManager
18+
cwd string
19+
}
20+
21+
func NewAutoEditor(cwd string) *AutoEditor {
22+
return &AutoEditor{
23+
healer: NewSelfHealer(cwd),
24+
retry: NewSmartRetry(3),
25+
learning: NewLearningEngine(cwd),
26+
context: NewContextManager(8000),
27+
cwd: cwd,
28+
}
29+
}
30+
31+
func (ae *AutoEditor) SetMaestro(maestro *maestro.Conductor) {
32+
ae.maestro = maestro
33+
}
34+
35+
type EditResult struct {
36+
Success bool
37+
Files []string
38+
Retries int
39+
Error error
40+
Recovered bool
41+
Lessions []string
42+
}
43+
44+
func (ae *AutoEditor) Execute(ctx context.Context, task string) *EditResult {
45+
result := &EditResult{}
46+
47+
fmt.Printf("[AUTO-EDITOR] Starting autonomous edit...\n")
48+
49+
// Get learned suggestions
50+
if suggestions := ae.learning.GetSuggestions(task); len(suggestions) > 0 {
51+
fmt.Printf("[AUTO-EDITOR] Learned suggestions: %s\n", suggestions[0])
52+
}
53+
54+
// Execute with retry
55+
retryResult, err := ae.retry.Execute(ctx, task, func() error {
56+
return ae.executeOnce(ctx, task, result)
57+
})
58+
59+
if err != nil {
60+
result.Error = err
61+
result.Retries = retryResult.Attempts
62+
return result
63+
}
64+
65+
result.Success = true
66+
result.Retries = retryResult.Attempts
67+
result.Lessions = ae.learning.GetSuggestions(task)
68+
69+
// Record success for learning
70+
ae.learning.RecordAttempt(task, []string{"execute"}, true, "")
71+
72+
return result
73+
}
74+
75+
func (ae *AutoEditor) executeOnce(ctx context.Context, task string, result *EditResult) error {
76+
// Execute via maestro
77+
err := ae.maestro.ExecuteTask(ctx, task, "medium")
78+
if err == nil {
79+
result.Success = true
80+
return nil
81+
}
82+
83+
// Try self-healing
84+
healResult := ae.healer.AnalyzeAndHeal(err.Error())
85+
if healResult.Fixed {
86+
result.Recovered = true
87+
fmt.Printf("[AUTO-EDITOR] Self-healed: %s\n", healResult.Action)
88+
return nil
89+
}
90+
91+
// Get recovery tip
92+
classifier := NewErrorClassifier()
93+
category := classifier.Classify(err)
94+
fmt.Printf("[AUTO-EDITOR] Error: %s - %s\n", category.Category, category.Tip)
95+
96+
// Record failure for learning
97+
ae.learning.RecordAttempt(task, []string{"execute"}, false, category.Tip)
98+
99+
return err
100+
}
101+
102+
func (ae *AutoEditor) GetStats() string {
103+
return fmt.Sprintf("Learning: %s, Context: %s",
104+
ae.learning.GetStats(),
105+
ae.context.GetStats())
106+
}
107+
108+
type MultiEditor struct {
109+
editors []*AutoEditor
110+
concurrency int
111+
}
112+
113+
func NewMultiEditor(concurrency int) *MultiEditor {
114+
return &MultiEditor{
115+
concurrency: concurrency,
116+
editors: make([]*AutoEditor, concurrency),
117+
}
118+
}
119+
120+
func (me *MultiEditor) AddEditor(cwd string) *AutoEditor {
121+
editor := NewAutoEditor(cwd)
122+
me.editors = append(me.editors, editor)
123+
return editor
124+
}
125+
126+
func (me *MultiEditor) ExecuteAll(ctx context.Context, tasks []string) *MultiEditResult {
127+
result := &MultiEditResult{
128+
StartTime: time.Now(),
129+
}
130+
131+
sem := make(chan struct{}, me.concurrency)
132+
taskCh := make(chan string, len(tasks))
133+
134+
for _, task := range tasks {
135+
taskCh <- task
136+
}
137+
close(taskCh)
138+
139+
for i, task := range tasks {
140+
select {
141+
case sem <- struct{}{}:
142+
go func(idx int, t string) {
143+
editor := me.editors[idx%len(me.editors)]
144+
editResult := editor.Execute(ctx, t)
145+
result.mu.Lock()
146+
result.Results = append(result.Results, *editResult)
147+
if editResult.Success {
148+
result.Completed++
149+
} else {
150+
result.Failed++
151+
}
152+
result.mu.Unlock()
153+
<-sem
154+
}(i, task)
155+
}
156+
}
157+
158+
result.Duration = time.Since(result.StartTime)
159+
return result
160+
}
161+
162+
type MultiEditResult struct {
163+
Results []EditResult
164+
Completed int
165+
Failed int
166+
Duration time.Duration
167+
StartTime time.Time
168+
mu sync.Mutex
169+
}
170+
171+
func (r *MultiEditResult) Summary() string {
172+
return fmt.Sprintf("Completed: %d, Failed: %d, Duration: %v, Success Rate: %.0f%%",
173+
r.Completed, r.Failed, r.Duration, r.SuccessRate())
174+
}
175+
176+
func (r *MultiEditResult) SuccessRate() float64 {
177+
total := r.Completed + r.Failed
178+
if total == 0 {
179+
return 0
180+
}
181+
return float64(r.Completed) / float64(total) * 100
182+
}

0 commit comments

Comments
 (0)