106 lines
2.4 KiB
Go
106 lines
2.4 KiB
Go
package services
|
||
|
||
import (
|
||
"encoding/json"
|
||
"os"
|
||
"path/filepath"
|
||
"strings"
|
||
|
||
"sproutclaw-web/internal/models"
|
||
)
|
||
|
||
// ListExtensions reads the extensions directory and returns metadata.
|
||
func ListExtensions(agentDir string) []models.ExtensionInfo {
|
||
extDir := filepath.Join(agentDir, "extensions")
|
||
entries, err := os.ReadDir(extDir)
|
||
if err != nil {
|
||
return nil
|
||
}
|
||
|
||
var exts []models.ExtensionInfo
|
||
for _, e := range entries {
|
||
if !e.IsDir() {
|
||
continue
|
||
}
|
||
ext := buildExtensionInfo(filepath.Join(extDir, e.Name()), e.Name())
|
||
exts = append(exts, ext)
|
||
}
|
||
return exts
|
||
}
|
||
|
||
func buildExtensionInfo(path, id string) models.ExtensionInfo {
|
||
info := models.ExtensionInfo{
|
||
ID: id,
|
||
Name: id,
|
||
Enabled: true, // assume enabled unless configured otherwise
|
||
Source: "local",
|
||
}
|
||
|
||
// try package.json for version/name
|
||
pkgPath := filepath.Join(path, "package.json")
|
||
if data, err := os.ReadFile(pkgPath); err == nil {
|
||
var pkg struct {
|
||
Name string `json:"name"`
|
||
Version string `json:"version"`
|
||
}
|
||
if json.Unmarshal(data, &pkg) == nil {
|
||
if pkg.Name != "" {
|
||
info.Name = pkg.Name
|
||
}
|
||
info.Version = pkg.Version
|
||
// detect npm packages
|
||
if strings.Contains(pkg.Name, "/") || strings.HasPrefix(pkg.Name, "@") {
|
||
info.Source = "npm"
|
||
}
|
||
}
|
||
}
|
||
return info
|
||
}
|
||
|
||
// ToggleExtension is a placeholder – full implementation requires settings.json management.
|
||
func ToggleExtension(agentDir, id string, enable bool) error {
|
||
return updateSettingsExtensions(filepath.Join(agentDir, "settings.json"), id, enable)
|
||
}
|
||
|
||
func updateSettingsExtensions(settingsPath, id string, enable bool) error {
|
||
data, err := os.ReadFile(settingsPath)
|
||
if err != nil && !os.IsNotExist(err) {
|
||
return err
|
||
}
|
||
|
||
var settings map[string]any
|
||
if len(data) > 0 {
|
||
if err := json.Unmarshal(data, &settings); err != nil {
|
||
settings = map[string]any{}
|
||
}
|
||
} else {
|
||
settings = map[string]any{}
|
||
}
|
||
|
||
// extensions is a list of enabled extension IDs
|
||
extList, _ := settings["extensions"].([]any)
|
||
set := map[string]bool{}
|
||
for _, e := range extList {
|
||
if s, ok := e.(string); ok {
|
||
set[s] = true
|
||
}
|
||
}
|
||
if enable {
|
||
set[id] = true
|
||
} else {
|
||
delete(set, id)
|
||
}
|
||
|
||
newList := make([]string, 0, len(set))
|
||
for k := range set {
|
||
newList = append(newList, k)
|
||
}
|
||
settings["extensions"] = newList
|
||
|
||
out, err := json.MarshalIndent(settings, "", " ")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
return os.WriteFile(settingsPath, append(out, '\n'), 0o644)
|
||
}
|