feat: initial release of muyue - AI-powered dev environment assistant
Complete implementation of muyue v0.1.0, a single-binary Go tool that transforms the development environment with AI-powered orchestration. Core features: - TUI with 5 tabs (Dashboard/Chat/Workflow/Agents/Config) using Charm stack - AI chat via MiniMax M2.7 with async message handling - Structured Plan→Execute workflow engine (gather→plan→review→execute) - System scanner detecting 14 tools + 8 runtimes across Linux/macOS/Windows - Auto-installer for Crush, Claude Code, BMAD, Starship, runtimes - Background update daemon with hourly checks - LSP auto-config for 16 language servers - MCP auto-config for 12 servers (deployed to Crush + Claude Code) - Skills system with 5 built-ins + AI-powered generation - Crush/Claude Code proxy for unified control - HTML preview server for visual outputs - First-time setup wizard with interactive profiling - Cross-platform: Linux (primary), macOS, Windows, WSL CI/CD: - GitHub Actions CI: build + test + lint on Linux/macOS/Windows - Release workflow: cross-compile 6 binaries with checksums on tag push 💘 Generated with Crush Assisted-by: GLM-5.1 via Crush <crush@charm.land>
This commit is contained in:
125
internal/profiler/profiler.go
Normal file
125
internal/profiler/profiler.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package profiler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/huh"
|
||||
"github.com/muyue/muyue/internal/config"
|
||||
"github.com/muyue/muyue/internal/scanner"
|
||||
)
|
||||
|
||||
func RunFirstTimeSetup() (*config.MuyueConfig, error) {
|
||||
cfg := config.Default()
|
||||
result := scanner.ScanSystem()
|
||||
|
||||
fmt.Println("Welcome to muyue! Let's set up your environment.\n")
|
||||
|
||||
var name, pseudo, email string
|
||||
var languages []string
|
||||
var editor string
|
||||
var aiProvider string
|
||||
|
||||
nameField := huh.NewInput().
|
||||
Title("What's your name?").
|
||||
Placeholder("Augustin").
|
||||
Value(&name)
|
||||
|
||||
pseudoField := huh.NewInput().
|
||||
Title("Your pseudo?").
|
||||
Placeholder("muyue").
|
||||
Value(&pseudo)
|
||||
|
||||
emailField := huh.NewInput().
|
||||
Title("Your email (for git config)?").
|
||||
Placeholder("you@example.com").
|
||||
Value(&email)
|
||||
|
||||
langOptions := []huh.Option[string]{
|
||||
{Key: "Go", Value: "go"},
|
||||
{Key: "TypeScript/JavaScript", Value: "typescript"},
|
||||
{Key: "Python", Value: "python"},
|
||||
{Key: "Rust", Value: "rust"},
|
||||
{Key: "Java", Value: "java"},
|
||||
{Key: "C/C++", Value: "c"},
|
||||
{Key: "Ruby", Value: "ruby"},
|
||||
{Key: "PHP", Value: "php"},
|
||||
{Key: "Swift", Value: "swift"},
|
||||
{Key: "Kotlin", Value: "kotlin"},
|
||||
}
|
||||
|
||||
langSelect := huh.NewMultiSelect[string]().
|
||||
Title("Which languages do you work with?").
|
||||
Options(langOptions...).
|
||||
Value(&languages)
|
||||
|
||||
editorOptions := []huh.Option[string]{
|
||||
{Key: "VS Code", Value: "code"},
|
||||
{Key: "Neovim", Value: "nvim"},
|
||||
{Key: "Vim", Value: "vim"},
|
||||
{Key: "Emacs", Value: "emacs"},
|
||||
{Key: "JetBrains", Value: "jetbrains"},
|
||||
{Key: "Helix", Value: "hx"},
|
||||
{Key: "Sublime Text", Value: "subl"},
|
||||
}
|
||||
|
||||
editorSelect := huh.NewSelect[string]().
|
||||
Title("Preferred editor?").
|
||||
Options(editorOptions...).
|
||||
Value(&editor)
|
||||
|
||||
aiOptions := []huh.Option[string]{
|
||||
{Key: "MiniMax M2.7", Value: "minimax"},
|
||||
{Key: "Z.AI GLM", Value: "zai"},
|
||||
{Key: "Anthropic Claude", Value: "anthropic"},
|
||||
{Key: "OpenAI", Value: "openai"},
|
||||
}
|
||||
|
||||
aiSelect := huh.NewSelect[string]().
|
||||
Title("Which AI provider for orchestration?").
|
||||
Options(aiOptions...).
|
||||
Value(&aiProvider)
|
||||
|
||||
form := huh.NewForm(
|
||||
huh.NewGroup(nameField, pseudoField, emailField),
|
||||
huh.NewGroup(langSelect),
|
||||
huh.NewGroup(editorSelect),
|
||||
huh.NewGroup(aiSelect),
|
||||
)
|
||||
|
||||
if err := form.Run(); err != nil {
|
||||
return nil, fmt.Errorf("profile form: %w", err)
|
||||
}
|
||||
|
||||
cfg.Profile.Name = name
|
||||
cfg.Profile.Pseudo = pseudo
|
||||
cfg.Profile.Email = email
|
||||
cfg.Profile.Languages = languages
|
||||
cfg.Profile.Preferences.Editor = editor
|
||||
cfg.Profile.Preferences.DefaultAI = aiProvider
|
||||
|
||||
for i := range cfg.AI.Providers {
|
||||
cfg.AI.Providers[i].Active = cfg.AI.Providers[i].Name == aiProvider
|
||||
}
|
||||
|
||||
_ = result
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func AskAPIKey(providerName string) (string, error) {
|
||||
var apiKey string
|
||||
|
||||
field := huh.NewInput().
|
||||
Title(fmt.Sprintf("Enter your %s API key:", providerName)).
|
||||
Description("The key will be stored locally in ~/.muyue/config.yaml").
|
||||
EchoMode(huh.EchoModePassword).
|
||||
Value(&apiKey)
|
||||
|
||||
form := huh.NewForm(huh.NewGroup(field))
|
||||
if err := form.Run(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.TrimSpace(apiKey), nil
|
||||
}
|
||||
Reference in New Issue
Block a user