Files
MuyueWorkspace/internal/lsp/registry.go
Augustin 2e50366cd8
All checks were successful
Beta Release / beta (push) Successful in 2m24s
feat: add Cobra CLI, LSP/MCP registries, workflow engine, and enriched dashboard
Major changes:
- Refactor CLI entry point to Cobra commands (root, setup, scan, doctor, install, update, lsp, mcp, skills, config, version)
- Add LSP registry with health checks, auto-install, and editor config generation
- Add MCP registry with editor detection, status tracking, and per-editor configuration
- Add workflow engine with planner and step execution for automated task chains
- Add conversation search, export (Markdown/JSON), and detailed token counting
- Add streaming shell chat handler with tool call/result events
- Add skill validation, dry-run testing, and export endpoints
- Enrich dashboard with Tools/Activity/Status tabs and tool cards grid
- Add PRD documentation
- Complete i18n for both EN and FR

💘 Generated with Crush

Assisted-by: GLM-5.1 via Crush <crush@charm.land>
2026-04-22 22:22:05 +02:00

334 lines
12 KiB
Go

package lsp
import (
"os"
"path/filepath"
"time"
"gopkg.in/yaml.v3"
)
type RegistryEntry struct {
Name string `yaml:"name" json:"name"`
Language string `yaml:"language" json:"language"`
Description string `yaml:"description" json:"description"`
Command string `yaml:"command" json:"command"`
InstallCmd string `yaml:"install_cmd" json:"install_cmd"`
InstallType string `yaml:"install_type" json:"install_type"`
Category string `yaml:"category" json:"category"`
FilePatterns []string `yaml:"file_patterns,omitempty" json:"file_patterns,omitempty"`
ConfigFiles []string `yaml:"config_files,omitempty" json:"config_files,omitempty"`
Tags []string `yaml:"tags,omitempty" json:"tags,omitempty"`
HomePage string `yaml:"homepage,omitempty" json:"homepage,omitempty"`
NeovimSetup string `yaml:"neovim_setup,omitempty" json:"neovim_setup,omitempty"`
HelixLanguage string `yaml:"helix_language,omitempty" json:"helix_language,omitempty"`
}
type LSPRegistry struct {
SchemaVersion string `yaml:"schema_version"`
UpdatedAt time.Time `yaml:"updated_at"`
Servers []RegistryEntry `yaml:"servers"`
}
func DefaultLSPRegistry() *LSPRegistry {
return &LSPRegistry{
SchemaVersion: "v1",
UpdatedAt: time.Now(),
Servers: []RegistryEntry{
{
Name: "gopls", Language: "go", Description: "Go language server",
Command: "gopls", InstallCmd: "go install golang.org/x/tools/gopls@latest",
InstallType: "go", Category: "lsp", FilePatterns: []string{"*.go"},
ConfigFiles: []string{"go.mod"}, Tags: []string{"go", "linting", "completion"},
HomePage: "https://github.com/golang/tools",
NeovimSetup: `lspconfig.gopls.setup{}`,
HelixLanguage: "go",
},
{
Name: "pyright", Language: "python", Description: "Python type checker and language server",
Command: "pyright", InstallCmd: "npm install -g pyright",
InstallType: "npm", Category: "lsp", FilePatterns: []string{"*.py", "*.pyi"},
ConfigFiles: []string{"requirements.txt", "pyproject.toml", "setup.py", "Pipfile"},
Tags: []string{"python", "type-checking"}, HomePage: "https://github.com/microsoft/pyright",
NeovimSetup: `lspconfig.pyright.setup{}`,
HelixLanguage: "python",
},
{
Name: "typescript-language-server", Language: "typescript", Description: "TypeScript and JavaScript language server",
Command: "typescript-language-server", InstallCmd: "npm install -g typescript-language-server typescript",
InstallType: "npm", Category: "lsp", FilePatterns: []string{"*.ts", "*.tsx", "*.js", "*.jsx"},
ConfigFiles: []string{"tsconfig.json", "package.json"},
Tags: []string{"typescript", "javascript"}, HomePage: "https://github.com/typescript-language-server/typescript-language-server",
NeovimSetup: `lspconfig.tsserver.setup{}`,
HelixLanguage: "typescript",
},
{
Name: "vscode-json-language-server", Language: "json", Description: "JSON language server",
Command: "vscode-json-language-server", InstallCmd: "npm install -g vscode-langservers-extracted",
InstallType: "npm", Category: "lsp", FilePatterns: []string{"*.json", "*.jsonc"},
Tags: []string{"json"}, NeovimSetup: `lspconfig.jsonls.setup{}`,
HelixLanguage: "json",
},
{
Name: "vscode-html-language-server", Language: "html", Description: "HTML language server",
Command: "vscode-html-language-server", InstallCmd: "npm install -g vscode-langservers-extracted",
InstallType: "npm", Category: "lsp", FilePatterns: []string{"*.html", "*.htm"},
Tags: []string{"html"}, NeovimSetup: `lspconfig.html.setup{}`,
HelixLanguage: "html",
},
{
Name: "vscode-css-language-server", Language: "css", Description: "CSS/SCSS/LESS language server",
Command: "vscode-css-language-server", InstallCmd: "npm install -g vscode-langservers-extracted",
InstallType: "npm", Category: "lsp", FilePatterns: []string{"*.css", "*.scss", "*.less"},
Tags: []string{"css"}, NeovimSetup: `lspconfig.cssls.setup{}`,
HelixLanguage: "css",
},
{
Name: "yaml-language-server", Language: "yaml", Description: "YAML language server",
Command: "yaml-language-server", InstallCmd: "npm install -g yaml-language-server",
InstallType: "npm", Category: "lsp", FilePatterns: []string{"*.yml", "*.yaml"},
Tags: []string{"yaml"}, NeovimSetup: `lspconfig.yamlls.setup{}`,
HelixLanguage: "yaml",
},
{
Name: "bash-language-server", Language: "bash", Description: "Bash language server",
Command: "bash-language-server", InstallCmd: "npm install -g bash-language-server",
InstallType: "npm", Category: "lsp", FilePatterns: []string{"*.sh", "*.bash"},
Tags: []string{"bash", "shell"}, NeovimSetup: `lspconfig.bashls.setup{}`,
HelixLanguage: "bash",
},
{
Name: "rust-analyzer", Language: "rust", Description: "Rust language server",
Command: "rust-analyzer", InstallCmd: "rustup component add rust-analyzer",
InstallType: "rustup", Category: "lsp", FilePatterns: []string{"*.rs"},
ConfigFiles: []string{"Cargo.toml"}, Tags: []string{"rust"},
HomePage: "https://github.com/rust-lang/rust-analyzer",
NeovimSetup: `lspconfig.rust_analyzer.setup{}`,
HelixLanguage: "rust",
},
{
Name: "clangd", Language: "c/c++", Description: "C/C++ language server",
Command: "clangd", InstallCmd: "", InstallType: "system",
Category: "lsp", FilePatterns: []string{"*.c", "*.cpp", "*.h", "*.hpp"},
ConfigFiles: []string{"CMakeLists.txt", "Makefile"}, Tags: []string{"c", "cpp"},
NeovimSetup: `lspconfig.clangd.setup{}`,
HelixLanguage: "c",
},
{
Name: "lua-language-server", Language: "lua", Description: "Lua language server",
Command: "lua-language-server", InstallCmd: "npm install -g lua-language-server",
InstallType: "npm", Category: "lsp", FilePatterns: []string{"*.lua"},
Tags: []string{"lua"}, NeovimSetup: `lspconfig.lua_ls.setup{}`,
HelixLanguage: "lua",
},
{
Name: "dockerfile-language-server", Language: "dockerfile", Description: "Dockerfile language server",
Command: "docker-langserver", InstallCmd: "npm install -g dockerfile-language-server-nodejs",
InstallType: "npm", Category: "lsp", FilePatterns: []string{"Dockerfile", "Dockerfile.*"},
Tags: []string{"docker"}, NeovimSetup: `lspconfig.dockerls.setup{}`,
HelixLanguage: "dockerfile",
},
{
Name: "tailwindcss-language-server", Language: "tailwind", Description: "Tailwind CSS language server",
Command: "tailwindcss-language-server", InstallCmd: "npm install -g @tailwindcss/language-server",
InstallType: "npm", Category: "lsp", FilePatterns: []string{"*.html", "*.tsx", "*.jsx"},
ConfigFiles: []string{"tailwind.config.js", "tailwind.config.ts"},
Tags: []string{"tailwind", "css"}, NeovimSetup: `lspconfig.tailwindcss.setup{}`,
},
{
Name: "svelte-language-server", Language: "svelte", Description: "Svelte language server",
Command: "svelteserver", InstallCmd: "npm install -g svelte-language-server",
InstallType: "npm", Category: "lsp", FilePatterns: []string{"*.svelte"},
Tags: []string{"svelte"}, NeovimSetup: `lspconfig.svelte.setup{}`,
HelixLanguage: "svelte",
},
{
Name: "vue-language-server", Language: "vue", Description: "Vue language server",
Command: "vue-language-server", InstallCmd: "npm install -g @vue/language-server",
InstallType: "npm", Category: "lsp", FilePatterns: []string{"*.vue"},
Tags: []string{"vue"}, NeovimSetup: `lspconfig.vuels.setup{}`,
},
{
Name: "golangci-lint-langserver", Language: "go-lint", Description: "Go linter language server",
Command: "golangci-lint-langserver", InstallCmd: "go install github.com/nametake/golangci-lint-langserver@latest",
InstallType: "go", Category: "lsp", FilePatterns: []string{"*.go"},
Tags: []string{"go", "linting"},
},
},
}
}
var lspRegistryPath string
func init() {
home, _ := os.UserHomeDir()
if home != "" {
lspRegistryPath = filepath.Join(home, ".muyue", "lsp-registry.yaml")
}
}
func SetLSPRegistryPath(p string) {
lspRegistryPath = p
}
func LoadLSPRegistry() (*LSPRegistry, error) {
if lspRegistryPath == "" {
return DefaultLSPRegistry(), nil
}
data, err := os.ReadFile(lspRegistryPath)
if err != nil {
return DefaultLSPRegistry(), nil
}
var reg LSPRegistry
if err := yaml.Unmarshal(data, &reg); err != nil {
return nil, err
}
return &reg, nil
}
func SaveLSPRegistry(reg *LSPRegistry) error {
if lspRegistryPath == "" {
return nil
}
reg.UpdatedAt = time.Now()
data, err := yaml.Marshal(reg)
if err != nil {
return err
}
os.MkdirAll(filepath.Dir(lspRegistryPath), 0755)
return os.WriteFile(lspRegistryPath, data, 0644)
}
func InitLSPRegistry() error {
if lspRegistryPath == "" {
return nil
}
if _, err := os.Stat(lspRegistryPath); err == nil {
return nil
}
return SaveLSPRegistry(DefaultLSPRegistry())
}
func DetectProjectLanguages(projectDir string) []string {
if projectDir == "" {
return nil
}
langDetectors := map[string][]string{
"go": {"go.mod", "go.sum"},
"python": {"requirements.txt", "pyproject.toml", "setup.py", "Pipfile", "uv.lock"},
"typescript": {"tsconfig.json", "package.json"},
"javascript": {"package.json"},
"rust": {"Cargo.toml"},
"ruby": {"Gemfile"},
"java": {"pom.xml", "build.gradle"},
"c": {"CMakeLists.txt", "Makefile"},
"cpp": {"CMakeLists.txt"},
"php": {"composer.json"},
"lua": {".luarc.json"},
"docker": {"Dockerfile"},
}
extDetectors := map[string]string{
".go": "go",
".py": "python",
".rs": "rust",
".ts": "typescript",
".tsx": "typescript",
".js": "javascript",
".jsx": "javascript",
".rb": "ruby",
".java": "java",
".c": "c",
".cpp": "cpp",
".h": "c",
".lua": "lua",
".vue": "vue",
".svelte": "svelte",
}
detected := map[string]bool{}
for lang, files := range langDetectors {
for _, f := range files {
if _, err := os.Stat(filepath.Join(projectDir, f)); err == nil {
detected[lang] = true
break
}
}
}
entries, err := os.ReadDir(projectDir)
if err == nil {
for _, e := range entries {
if e.IsDir() {
continue
}
ext := filepath.Ext(e.Name())
if lang, ok := extDetectors[ext]; ok {
detected[lang] = true
}
}
}
var languages []string
for lang := range detected {
languages = append(languages, lang)
}
return languages
}
func GenerateNeovimConfig(servers []RegistryEntry) string {
config := `-- Generated by Muyue LSP Manager
-- Add to your init.lua or require from lspconfig setup
local lspconfig = require('lspconfig')
`
for _, s := range servers {
if s.NeovimSetup != "" {
config += s.NeovimSetup + "\n"
}
}
return config
}
func GenerateHelixConfig(servers []RegistryEntry) string {
config := `# Generated by Muyue LSP Manager
# Add to ~/.config/helix/languages.toml
`
for _, s := range servers {
if s.HelixLanguage != "" {
config += "[[language]]\n"
config += "name = \"" + s.HelixLanguage + "\"\n"
config += "language-servers = [\"" + s.Name + "\"]\n\n"
}
}
return config
}
func GenerateVSCodeRecommendations(servers []RegistryEntry) []string {
extensionMap := map[string][]string{
"gopls": {"golang.go"},
"pyright": {"ms-python.python", "ms-python.vscode-pylance"},
"typescript-language-server": {"ms-vscode.vscode-typescript-next"},
"rust-analyzer": {"rust-lang.rust-analyzer"},
"lua-language-server": {"sumneko.lua"},
"tailwindcss-language-server": {"bradlc.vscode-tailwindcss"},
"svelte-language-server": {"svelte.svelte-vscode"},
"vue-language-server": {"vue.volar"},
"yaml-language-server": {"redhat.vscode-yaml"},
"bash-language-server": {"mads-hartmann.bash-ide-vscode"},
}
var extensions []string
for _, s := range servers {
if exts, ok := extensionMap[s.Name]; ok {
extensions = append(extensions, exts...)
}
}
return extensions
}