mirror of
https://github.com/hanzoai/agent.git
synced 2026-09-11 21:08:51 +00:00
The bulk rename from agentfield to hanzo-agents introduced hyphens into Go variable names (e.g. hanzo-agentsHome), which are not valid Go identifiers. Fixed 361 occurrences across 36 files to use camelCase (e.g. hanzoAgentsHome). String literals like ".hanzo-agents" are preserved as-is.
180 lines
4.3 KiB
Go
180 lines
4.3 KiB
Go
package cli
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"path/filepath"
|
||
"sync"
|
||
"time"
|
||
|
||
"github.com/fatih/color"
|
||
)
|
||
|
||
// getHanzoAgentsHomeDir returns the HanzoAgents home directory (~/.hanzo-agents) and ensures it exists
|
||
func getHanzoAgentsHomeDir() string {
|
||
if customHome := os.Getenv("HANZO_AGENTS_HOME"); customHome != "" {
|
||
if err := os.MkdirAll(customHome, 0755); err != nil {
|
||
PrintError(fmt.Sprintf("Failed to create HANZO_AGENTS_HOME directory: %v", err))
|
||
os.Exit(1)
|
||
}
|
||
ensureSubdirs(customHome)
|
||
return customHome
|
||
}
|
||
|
||
homeDir, err := os.UserHomeDir()
|
||
if err != nil {
|
||
PrintError(fmt.Sprintf("Failed to get user home directory: %v", err))
|
||
os.Exit(1)
|
||
}
|
||
|
||
hanzoAgentsHome := filepath.Join(homeDir, ".hanzo-agents")
|
||
|
||
// Ensure .hanzo-agents directory exists
|
||
if err := os.MkdirAll(hanzoAgentsHome, 0755); err != nil {
|
||
PrintError(fmt.Sprintf("Failed to create .hanzo-agents directory: %v", err))
|
||
os.Exit(1)
|
||
}
|
||
|
||
ensureSubdirs(hanzoAgentsHome)
|
||
|
||
return hanzoAgentsHome
|
||
}
|
||
|
||
func ensureSubdirs(hanzoAgentsHome string) {
|
||
subdirs := []string{"packages", "logs", "config"}
|
||
for _, subdir := range subdirs {
|
||
if err := os.MkdirAll(filepath.Join(hanzoAgentsHome, subdir), 0755); err != nil {
|
||
PrintError(fmt.Sprintf("Failed to create %s directory: %v", subdir, err))
|
||
os.Exit(1)
|
||
}
|
||
}
|
||
}
|
||
|
||
// Professional CLI status symbols
|
||
const (
|
||
StatusSuccess = "✔" // Standardized
|
||
StatusError = "❗" // Standardized
|
||
StatusWarning = "⚠" // Added
|
||
StatusInfo = "ℹ" // Added
|
||
StatusArrow = "→"
|
||
StatusBullet = "•"
|
||
)
|
||
|
||
// Spinner characters for progress indication
|
||
var spinnerChars = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
|
||
|
||
// Color functions for professional output
|
||
var (
|
||
Green = color.New(color.FgGreen).SprintFunc()
|
||
Red = color.New(color.FgRed).SprintFunc()
|
||
Yellow = color.New(color.FgYellow).SprintFunc()
|
||
Blue = color.New(color.FgBlue).SprintFunc()
|
||
Cyan = color.New(color.FgCyan).SprintFunc() // Added
|
||
Gray = color.New(color.FgHiBlack).SprintFunc()
|
||
Bold = color.New(color.Bold).SprintFunc()
|
||
)
|
||
|
||
// Spinner represents a CLI spinner for progress indication
|
||
type Spinner struct {
|
||
message string
|
||
active bool
|
||
mu sync.Mutex
|
||
done chan bool
|
||
}
|
||
|
||
// NewSpinner creates a new spinner with the given message
|
||
func NewSpinner(message string) *Spinner {
|
||
return &Spinner{
|
||
message: message,
|
||
done: make(chan bool),
|
||
}
|
||
}
|
||
|
||
// Start begins the spinner animation
|
||
func (s *Spinner) Start() {
|
||
s.mu.Lock()
|
||
s.active = true
|
||
s.mu.Unlock()
|
||
|
||
go func() {
|
||
i := 0
|
||
for {
|
||
select {
|
||
case <-s.done:
|
||
return
|
||
default:
|
||
s.mu.Lock()
|
||
if s.active {
|
||
fmt.Printf("\r %s %s", spinnerChars[i%len(spinnerChars)], s.message)
|
||
i++
|
||
}
|
||
s.mu.Unlock()
|
||
time.Sleep(100 * time.Millisecond)
|
||
}
|
||
}
|
||
}()
|
||
}
|
||
|
||
// Stop stops the spinner and clears the line
|
||
func (s *Spinner) Stop() {
|
||
s.mu.Lock()
|
||
s.active = false
|
||
s.mu.Unlock()
|
||
s.done <- true
|
||
fmt.Print("\r\033[K") // Clear the line
|
||
}
|
||
|
||
// Success stops the spinner and shows a success message
|
||
func (s *Spinner) Success(message string) {
|
||
s.Stop()
|
||
fmt.Printf(" %s %s\n", Green(StatusSuccess), message)
|
||
}
|
||
|
||
// Error stops the spinner and shows an error message
|
||
func (s *Spinner) Error(message string) {
|
||
s.Stop()
|
||
fmt.Printf(" %s %s\n", Red(StatusError), message)
|
||
}
|
||
|
||
// UpdateMessage updates the spinner message while it's running
|
||
func (s *Spinner) UpdateMessage(message string) {
|
||
s.mu.Lock()
|
||
s.message = message
|
||
s.mu.Unlock()
|
||
}
|
||
|
||
// PrintSuccess prints a success message with checkmark
|
||
func PrintSuccess(message string) {
|
||
fmt.Printf("%s %s\n", Green(StatusSuccess), message)
|
||
}
|
||
|
||
// PrintError prints an error message with cross mark
|
||
func PrintError(message string) {
|
||
fmt.Printf("%s %s\n", Red(StatusError), message)
|
||
}
|
||
|
||
// PrintInfo prints an informational message with arrow
|
||
func PrintInfo(message string) {
|
||
fmt.Printf("%s %s\n", Blue(StatusArrow), message)
|
||
}
|
||
|
||
// PrintWarning prints a warning message
|
||
func PrintWarning(message string) {
|
||
fmt.Printf("%s %s\n", Yellow(StatusBullet), message)
|
||
}
|
||
|
||
// PrintHeader prints a header message in bold
|
||
func PrintHeader(message string) {
|
||
fmt.Printf("%s\n", Bold(message))
|
||
}
|
||
|
||
// PrintSubheader prints a subheader message
|
||
func PrintSubheader(message string) {
|
||
fmt.Printf("\n%s\n", message)
|
||
}
|
||
|
||
// PrintBullet prints a bullet point
|
||
func PrintBullet(message string) {
|
||
fmt.Printf(" %s %s\n", Gray(StatusBullet), message)
|
||
}
|