/ go / internal / cli / root.go
root.go
  1  package cli
  2  
  3  import (
  4  	"fmt"
  5  	"math/rand"
  6  	"os"
  7  	"sort"
  8  	"strings"
  9  	"time"
 10  
 11  	"github.com/spf13/cobra"
 12  	"github.com/TransformerOS/kamaji-go/internal/style"
 13  )
 14  
 15  var rootCmd = &cobra.Command{
 16  	Use:   "kamaji",
 17  	Short: "šŸ”„ Kamaji - AI CLI Assistant",
 18  	Long:  style.GetCompactBanner() + "\n" + style.Info("Kamaji AI CLI with multi-agent capabilities and tool integration"),
 19  	Run: func(cmd *cobra.Command, args []string) {
 20  		// If no subcommand specified, launch TUI by default
 21  		if err := runTUI(cmd, args); err != nil {
 22  			fmt.Fprintf(os.Stderr, "Error launching TUI: %v\n", err)
 23  			fmt.Fprintf(os.Stderr, "\nUse 'kamaji --help' to see all available commands.\n")
 24  			os.Exit(1)
 25  		}
 26  	},
 27  }
 28  
 29  func showStyledHelp(cmd *cobra.Command) {
 30  	fmt.Printf("%s\n", style.Header("šŸ”„ Available Commands:"))
 31  	
 32  	// Core commands
 33  	coreCommands := []struct {
 34  		name, desc string
 35  	}{
 36  		{"ask", "Ask a single question to Kamaji"},
 37  		{"chat", "Start interactive chat with memory"},
 38  		{"rag", "Query documents using RAG"},
 39  		{"interactive", "Agent mode with filesystem and shell tools"},
 40  		{"tui", "Launch beautiful terminal interface"},
 41  	}
 42  	
 43  	fmt.Printf("\n%s\n", style.Fire("šŸ”„ Core Commands:"))
 44  	for _, cmd := range coreCommands {
 45  		fmt.Printf("  %s  %s\n", style.Highlight(cmd.name), style.DimText(cmd.desc))
 46  	}
 47  	
 48  	// Management commands
 49  	mgmtCommands := []struct {
 50  		name, desc string
 51  	}{
 52  		{"work", "Work on tasks - prompts, paths, or task list"},
 53  		{"tasks", "Show current task list"},
 54  		{"queue", "Add tasks to task queue"},
 55  		{"do", "Select and execute a task"},
 56  		{"agents", "Manage AI agents and their capabilities"},
 57  		{"tools", "Explore and manage available tools"},
 58  		{"mcp", "Model Context Protocol server management"},
 59  		{"workflow", "Automated workflow management"},
 60  	}
 61  	
 62  	fmt.Printf("\n%s\n", style.Warning("šŸ¤– Management Commands:"))
 63  	for _, cmd := range mgmtCommands {
 64  		fmt.Printf("  %s  %s\n", style.Highlight(cmd.name), style.DimText(cmd.desc))
 65  	}
 66  	
 67  	// Advanced commands
 68  	advancedCommands := []struct {
 69  		name, desc string
 70  	}{
 71  		{"genetic", "Genetic algorithm optimization"},
 72  	}
 73  	
 74  	fmt.Printf("\n%s\n", style.Info("⚔ Advanced Commands:"))
 75  	for _, cmd := range advancedCommands {
 76  		fmt.Printf("  %s  %s\n", style.Highlight(cmd.name), style.DimText(cmd.desc))
 77  	}
 78  	
 79  	// Utility commands
 80  	utilCommands := []struct{
 81  		name, desc string
 82  	}{
 83  		{"update", "Update Kamaji to latest version"},
 84  		{"config", "Manage Kamaji configuration"},
 85  		{"version", "Show version information"},
 86  		{"help", "Help about any command"},
 87  	}
 88  	
 89  	fmt.Printf("\n%s\n", style.Info("šŸ› ļø  Utility Commands:"))
 90  	for _, cmd := range utilCommands {
 91  		fmt.Printf("  %s  %s\n", style.Highlight(cmd.name), style.DimText(cmd.desc))
 92  	}
 93  	
 94  	fmt.Printf("\n%s\n", style.DimText("Use 'kamaji [command] --help' for more information about a command."))
 95  	fmt.Printf("%s\n\n", style.Fire("šŸ”„ Ready to assist!"))
 96  }
 97  
 98  var geneticCmd = &cobra.Command{
 99  	Use:   "genetic",
100  	Short: "Genetic algorithm optimization",
101  	Long:  "Use genetic algorithms to evolve and optimize code",
102  }
103  
104  var evolveCmd = &cobra.Command{
105  	Use:   "evolve [file]",
106  	Short: "Evolve code using genetic algorithm",
107  	Args:  cobra.ExactArgs(1),
108  	RunE:  runEvolve,
109  }
110  
111  type Individual struct {
112  	Code    string
113  	Fitness float64
114  }
115  
116  type Population []Individual
117  
118  func Execute() error {
119  	return rootCmd.Execute()
120  }
121  
122  func init() {
123  	rand.Seed(time.Now().UnixNano())
124  	
125  	// Core commands
126  	rootCmd.AddCommand(askCmd)
127  	rootCmd.AddCommand(chatCmd)
128  	rootCmd.AddCommand(ragCmd)
129  	rootCmd.AddCommand(interactiveCmd)
130  	rootCmd.AddCommand(tuiCmd)
131  	rootCmd.AddCommand(updateCmd)
132  	rootCmd.AddCommand(configCmd)
133  	rootCmd.AddCommand(versionCmd)
134  	rootCmd.AddCommand(rebuildCmd)
135  	
136  	// Management commands
137  	rootCmd.AddCommand(workCmd)
138  	rootCmd.AddCommand(tasksCmd)
139  	rootCmd.AddCommand(queueCmd)
140  	rootCmd.AddCommand(doCmd)
141  	rootCmd.AddCommand(agentsCmd)
142  	rootCmd.AddCommand(toolsCmd)
143  	rootCmd.AddCommand(mcpCmd)
144  	rootCmd.AddCommand(workflowCmd)
145  	
146  	// Specialized commands
147  	rootCmd.AddCommand(geneticCmd)
148  	rootCmd.AddCommand(kamajiCmd)
149  	
150  	geneticCmd.AddCommand(evolveCmd)
151  	evolveCmd.Flags().IntP("population", "p", 20, "Population size")
152  	evolveCmd.Flags().IntP("generations", "g", 50, "Maximum generations")
153  	evolveCmd.Flags().Float64P("mutation", "m", 0.1, "Mutation rate")
154  	evolveCmd.Flags().Float64P("crossover", "c", 0.7, "Crossover rate")
155  	
156  	// Custom help command
157  	helpCmd := &cobra.Command{
158  		Use:   "help [command]",
159  		Short: "Help about any command",
160  		Run: func(cmd *cobra.Command, args []string) {
161  			if len(args) == 0 {
162  				fmt.Print(style.GetCompactBanner())
163  				showStyledHelp(rootCmd)
164  			} else {
165  				// Show help for specific command
166  				if targetCmd, _, err := rootCmd.Find(args); err == nil {
167  					targetCmd.Help()
168  				} else {
169  					fmt.Printf("%s\n", style.Error("Command not found: "+args[0]))
170  				}
171  			}
172  		},
173  	}
174  	rootCmd.AddCommand(helpCmd)
175  }
176  
177  func runEvolve(cmd *cobra.Command, args []string) error {
178  	filePath := args[0]
179  	
180  	code, err := os.ReadFile(filePath)
181  	if err != nil {
182  		return fmt.Errorf("failed to read file: %w", err)
183  	}
184  
185  	popSize, _ := cmd.Flags().GetInt("population")
186  	generations, _ := cmd.Flags().GetInt("generations")
187  	mutationRate, _ := cmd.Flags().GetFloat64("mutation")
188  	crossoverRate, _ := cmd.Flags().GetFloat64("crossover")
189  
190  	fmt.Printf("🧬 REAL Genetic Algorithm Evolution\n")
191  	fmt.Printf("Population: %d, Generations: %d\n", popSize, generations)
192  	fmt.Printf("Mutation: %.2f, Crossover: %.2f\n", mutationRate, crossoverRate)
193  	fmt.Printf("Original: %d chars\n\n", len(code))
194  
195  	// Initialize population
196  	population := initializePopulation(string(code), popSize)
197  	
198  	for gen := 0; gen < generations; gen++ {
199  		// Evaluate fitness
200  		for i := range population {
201  			population[i].Fitness = calculateFitness(population[i].Code)
202  		}
203  		
204  		// Sort by fitness (descending)
205  		sort.Slice(population, func(i, j int) bool {
206  			return population[i].Fitness > population[j].Fitness
207  		})
208  		
209  		if gen%10 == 0 {
210  			fmt.Printf("Gen %d: Best=%.4f, Worst=%.4f, Avg=%.4f\n", 
211  				gen, population[0].Fitness, population[len(population)-1].Fitness, avgFitness(population))
212  		}
213  		
214  		// Create new generation
215  		newPop := make(Population, popSize)
216  		
217  		// Elitism - keep best 20%
218  		eliteCount := popSize / 5
219  		copy(newPop[:eliteCount], population[:eliteCount])
220  		
221  		// Generate offspring
222  		for i := eliteCount; i < popSize; i++ {
223  			parent1 := tournamentSelect(population)
224  			parent2 := tournamentSelect(population)
225  			
226  			var child Individual
227  			if rand.Float64() < crossoverRate {
228  				child = crossover(parent1, parent2)
229  			} else {
230  				child = parent1
231  			}
232  			
233  			if rand.Float64() < mutationRate {
234  				child.Code = mutate(child.Code)
235  			}
236  			
237  			newPop[i] = child
238  		}
239  		
240  		population = newPop
241  	}
242  	
243  	// Final evaluation
244  	for i := range population {
245  		population[i].Fitness = calculateFitness(population[i].Code)
246  	}
247  	sort.Slice(population, func(i, j int) bool {
248  		return population[i].Fitness > population[j].Fitness
249  	})
250  	
251  	best := population[0]
252  	fmt.Printf("\nāœ… Evolution Complete!\n")
253  	fmt.Printf("Best fitness: %.6f\n", best.Fitness)
254  	fmt.Printf("Final length: %d chars\n", len(best.Code))
255  	fmt.Printf("\n--- EVOLVED CODE ---\n%s\n--- END ---\n", best.Code)
256  
257  	return nil
258  }
259  
260  func initializePopulation(seed string, size int) Population {
261  	pop := make(Population, size)
262  	pop[0] = Individual{Code: seed} // Keep original
263  	
264  	for i := 1; i < size; i++ {
265  		mutated := seed
266  		// Apply multiple random mutations
267  		for j := 0; j < rand.Intn(5)+1; j++ {
268  			mutated = mutate(mutated)
269  		}
270  		pop[i] = Individual{Code: mutated}
271  	}
272  	
273  	return pop
274  }
275  
276  func tournamentSelect(pop Population) Individual {
277  	tournamentSize := 3
278  	best := pop[rand.Intn(len(pop))]
279  	
280  	for i := 1; i < tournamentSize; i++ {
281  		candidate := pop[rand.Intn(len(pop))]
282  		if candidate.Fitness > best.Fitness {
283  			best = candidate
284  		}
285  	}
286  	
287  	return best
288  }
289  
290  func crossover(parent1, parent2 Individual) Individual {
291  	code1, code2 := parent1.Code, parent2.Code
292  	
293  	if len(code1) == 0 || len(code2) == 0 {
294  		return parent1
295  	}
296  	
297  	// Single-point crossover
298  	minLen := len(code1)
299  	if len(code2) < minLen {
300  		minLen = len(code2)
301  	}
302  	
303  	if minLen <= 1 {
304  		return parent1
305  	}
306  	
307  	point := rand.Intn(minLen-1) + 1
308  	child := code1[:point] + code2[point:]
309  	
310  	return Individual{Code: child}
311  }
312  
313  func mutate(code string) string {
314  	if len(code) == 0 {
315  		return code
316  	}
317  	
318  	mutations := []func(string) string{
319  		insertChar, deleteChar, replaceChar, swapChars, duplicateSegment,
320  	}
321  	
322  	mutation := mutations[rand.Intn(len(mutations))]
323  	return mutation(code)
324  }
325  
326  func insertChar(code string) string {
327  	pos := rand.Intn(len(code) + 1)
328  	char := byte(rand.Intn(95) + 32) // Printable ASCII
329  	return code[:pos] + string(char) + code[pos:]
330  }
331  
332  func deleteChar(code string) string {
333  	if len(code) <= 1 {
334  		return code
335  	}
336  	pos := rand.Intn(len(code))
337  	return code[:pos] + code[pos+1:]
338  }
339  
340  func replaceChar(code string) string {
341  	if len(code) == 0 {
342  		return code
343  	}
344  	pos := rand.Intn(len(code))
345  	char := byte(rand.Intn(95) + 32)
346  	return code[:pos] + string(char) + code[pos+1:]
347  }
348  
349  func swapChars(code string) string {
350  	if len(code) < 2 {
351  		return code
352  	}
353  	pos := rand.Intn(len(code) - 1)
354  	chars := []byte(code)
355  	chars[pos], chars[pos+1] = chars[pos+1], chars[pos]
356  	return string(chars)
357  }
358  
359  func duplicateSegment(code string) string {
360  	if len(code) < 2 {
361  		return code
362  	}
363  	start := rand.Intn(len(code))
364  	end := start + rand.Intn(len(code)-start) + 1
365  	segment := code[start:end]
366  	pos := rand.Intn(len(code) + 1)
367  	return code[:pos] + segment + code[pos:]
368  }
369  
370  func calculateFitness(code string) float64 {
371  	if len(code) == 0 {
372  		return 0
373  	}
374  	
375  	// Multi-objective fitness
376  	lengthScore := 1000.0 / float64(len(code))
377  	
378  	// Syntax bonus (very basic)
379  	syntaxScore := 0.0
380  	if strings.Contains(code, "func") {
381  		syntaxScore += 10
382  	}
383  	if strings.Contains(code, "{") && strings.Contains(code, "}") {
384  		syntaxScore += 5
385  	}
386  	
387  	// Penalize invalid characters
388  	penalty := 0.0
389  	for _, char := range code {
390  		if char < 32 || char > 126 {
391  			penalty += 1
392  		}
393  	}
394  	
395  	return lengthScore + syntaxScore - penalty
396  }
397  
398  func avgFitness(pop Population) float64 {
399  	sum := 0.0
400  	for _, ind := range pop {
401  		sum += ind.Fitness
402  	}
403  	return sum / float64(len(pop))
404  }