Migrate to per-agent subdirectories, uniform 8-agent support, cross-platform fixes
- All paths use ~/.elydora/{agentId}/ per-agent isolation
- Add copilot, letta plugins; split kiro into kirocli + kiroide
- Remove augment (SDK-only agent, not one-click)
- Fix filepath.Join usage (replace string concatenation)
- Fix stale comment referencing old ~/.elydora/agents/ path
- Uniform 8 agents: claudecode, cursor, gemini, kirocli, kiroide, opencode, copilot, letta
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
c21e9fcfc6
commit
d80819093a
14 files changed
+830
-199
No files matched your search
+61
-11
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -91,12 +92,12 @@ func cmdInstall(args []string) {
|
||||
}
|
||||
|
||||
// Generate guard script (PreToolUse — freeze enforcement)
|
||||
guardScriptPath, err := guardScriptPathForAgent(*agent)
|
||||
guardScriptPath, err := guardScriptPathForAgent(*agentID)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
guardScript := plugins.GenerateGuardScript(*agent)
|
||||
guardScript := plugins.GenerateGuardScript(*agent, *agentID)
|
||||
if err := os.MkdirAll(filepath.Dir(guardScriptPath), 0755); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error creating guard script directory: %v\n", err)
|
||||
os.Exit(1)
|
||||
@@ -131,6 +132,7 @@ func cmdInstall(args []string) {
|
||||
func cmdUninstall(args []string) {
|
||||
fs := flag.NewFlagSet("uninstall", flag.ExitOnError)
|
||||
agent := fs.String("agent", "", "Agent name (required)")
|
||||
agentID := fs.String("agent-id", "", "Agent ID (if omitted, scans ~/.elydora/*/config.json for matching agent_name)")
|
||||
|
||||
fs.Parse(args)
|
||||
|
||||
@@ -147,18 +149,66 @@ func cmdUninstall(args []string) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := plugin.Uninstall(); err != nil {
|
||||
// Resolve agentID: if not given, scan ~/.elydora/*/config.json for matching agent_name
|
||||
resolvedAgentID := *agentID
|
||||
if resolvedAgentID == "" {
|
||||
resolvedAgentID = findAgentIDByName(*agent)
|
||||
if resolvedAgentID == "" {
|
||||
fmt.Fprintf(os.Stderr, "Warning: could not find agent ID for %q in ~/.elydora/*/config.json\n", *agent)
|
||||
}
|
||||
}
|
||||
|
||||
if err := plugin.Uninstall(resolvedAgentID); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Also remove the guard script
|
||||
guardPath, _ := guardScriptPathForAgent(*agent)
|
||||
if guardPath != "" {
|
||||
os.Remove(guardPath)
|
||||
// Remove the per-agent directory
|
||||
if resolvedAgentID != "" {
|
||||
home, err := os.UserHomeDir()
|
||||
if err == nil {
|
||||
agentDir := filepath.Join(home, ".elydora", resolvedAgentID)
|
||||
if err := os.RemoveAll(agentDir); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: failed to remove agent directory %s: %v\n", agentDir, err)
|
||||
} else {
|
||||
fmt.Printf(" Removed agent directory: %s\n", agentDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// findAgentIDByName scans ~/.elydora/*/config.json for a config whose agent_name
|
||||
// matches the given name and returns the directory name (agent ID).
|
||||
func findAgentIDByName(agentName string) string {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
elydoraDir := filepath.Join(home, ".elydora")
|
||||
entries, err := os.ReadDir(elydoraDir)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
configPath := filepath.Join(elydoraDir, entry.Name(), "config.json")
|
||||
data, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var config map[string]interface{}
|
||||
if err := json.Unmarshal(data, &config); err != nil {
|
||||
continue
|
||||
}
|
||||
if name, _ := config["agent_name"].(string); name == agentName {
|
||||
return entry.Name()
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// status
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -219,7 +269,7 @@ func cmdAgents() {
|
||||
names := sortedAgentNames()
|
||||
for _, name := range names {
|
||||
entry := plugins.SupportedAgents[name]
|
||||
configPath := entry.ConfigDir + "/" + entry.ConfigFile
|
||||
configPath := entry.ConfigDir + "/" + entry.ConfigFile // display only, not a filesystem path
|
||||
fmt.Printf(" %-14s %-20s %s\n", name, entry.Name, configPath)
|
||||
}
|
||||
}
|
||||
@@ -233,11 +283,11 @@ func sortedAgentNames() []string {
|
||||
return names
|
||||
}
|
||||
|
||||
// guardScriptPathForAgent returns the path to ~/.elydora/hooks/<agent>-guard.js.
|
||||
func guardScriptPathForAgent(agentName string) (string, error) {
|
||||
// guardScriptPathForAgent returns the path to ~/.elydora/<agentId>/guard.js.
|
||||
func guardScriptPathForAgent(agentId string) (string, error) {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("resolve home directory: %w", err)
|
||||
}
|
||||
return filepath.Join(home, ".elydora", "hooks", agentName+"-guard.js"), nil
|
||||
return filepath.Join(home, ".elydora", agentId, "guard.js"), nil
|
||||
}
|
||||
Reference in new issue
Block a user