Files
Elydora-Open-Source/sdks/go/cmd/elydora/main.go
T
雷电芽衣 b00932d047 sdks/go: mirror Elydora-Go-SDK v2.0.1 under the /v2 module path
Rebuilt from the standalone f5341ed tree (durable managed-file
transactions, Kiro IDE adapter, hook retry with a bounded chain lock,
CLI version 2.0.1) with the Open-Source API trims re-applied: no admin
events, members, webhooks, deep health, token rotation, or agent
integration updates, and the mirror's freeze/unfreeze and registration
validation contracts kept. The root quickstart now imports the /v2 path.

Claude-Session: https://claude.ai/code/session_01QoUjdc7HGKTsgj5GhG8HvF
2026-09-02 10:34:21 -04:00

294 lines
8.1 KiB
Go

package main
import (
"flag"
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"github.com/Elydora-Infrastructure/Elydora-Go-SDK/v2/cmd/elydora/plugins"
)
const version = "2.0.1"
func main() {
if len(os.Args) < 2 {
printUsage()
os.Exit(1)
}
switch os.Args[1] {
case "install":
cmdInstall(os.Args[2:])
case "uninstall":
cmdUninstall(os.Args[2:])
case "status":
cmdStatus(os.Args[2:])
case "agents":
cmdAgents()
case "version", "--version", "-v":
fmt.Printf("elydora %s\n", version)
case "help", "--help", "-h":
printUsage()
default:
fmt.Fprintf(os.Stderr, "Unknown command: %s\n\n", os.Args[1])
printUsage()
os.Exit(1)
}
}
func printUsage() {
fmt.Fprintf(os.Stderr, `Elydora CLI — agent hook installer for tamper-evident audit logging.
Usage:
elydora <command> [flags]
Commands:
install Install Elydora audit hook for an agent
uninstall Remove Elydora audit hook for an agent
status Show installation status for an agent (or all agents)
agents List all supported agents
version Print version
help Show this help
Run "elydora <command> -h" for details on each command.
`)
}
// ---------------------------------------------------------------------------
// install
// ---------------------------------------------------------------------------
func cmdInstall(args []string) {
if err := rejectLegacySecretArguments(args); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
fs := flag.NewFlagSet("install", flag.ExitOnError)
agent := fs.String("agent", "", "Agent name (required). Use 'elydora agents' to list.")
orgID := fs.String("org-id", "", "Organization ID (required)")
agentID := fs.String("agent-id", "", "Agent ID (required)")
privateKeyFile := fs.String("private-key-file", "", "Owner-only file containing the Ed25519 private key seed")
kid := fs.String("kid", "", "Key ID (defaults to <agent-id>-key-1)")
tokenFile := fs.String("token-file", "", "Owner-only file containing the optional API token")
baseURL := fs.String("base-url", "https://api.elydora.com", "Elydora API base URL")
fs.Parse(args)
if *agent == "" || *orgID == "" || *agentID == "" {
fmt.Fprintln(os.Stderr, "Error: --agent, --org-id, and --agent-id are required.")
fmt.Fprintln(os.Stderr)
fs.Usage()
os.Exit(1)
}
if *kid == "" {
*kid = *agentID + "-key-1"
}
plugin := plugins.NewPlugin(*agent)
if plugin == nil {
fmt.Fprintf(os.Stderr, "Error: unsupported agent %q. Run 'elydora agents' to see supported agents.\n", *agent)
os.Exit(1)
}
agentDirectory, err := plugins.ResolveAgentRuntimeDirectory(*agentID)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
secrets, err := resolveInstallSecrets(
installSecretSources{
privateKeyFile: *privateKeyFile,
tokenFile: *tokenFile,
},
newStandardSecretTerminal(),
)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
if err := validatePrivateKey(secrets.privateKey); err != nil {
fmt.Fprintf(os.Stderr, "Error: invalid private key: %v\n", err)
os.Exit(1)
}
guardScriptPath := filepath.Join(agentDirectory, "guard.js")
config := plugins.InstallConfig{
AgentName: *agent,
OrgID: *orgID,
AgentID: *agentID,
PrivateKey: secrets.privateKey,
KID: *kid,
Token: secrets.token,
BaseURL: *baseURL,
GuardScriptPath: guardScriptPath,
}
if preflighter, ok := plugin.(plugins.InstallPreflighter); ok {
if err := preflighter.PreflightInstall(config); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}
manager, managesGuard := plugin.(plugins.GuardRuntimeManager)
if !managesGuard || !manager.ManagesGuardRuntime() {
agentDirectory, err = plugins.PrepareAgentRuntimeDirectory(*agentID)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
guardScript := plugins.GenerateGuardScript(*agent, *agentID)
if err := plugins.WriteRuntimeFileAtomic(
guardScriptPath,
"Elydora guard runtime",
[]byte(guardScript),
0700,
); err != nil {
fmt.Fprintf(os.Stderr, "Error writing guard script: %v\n", err)
os.Exit(1)
}
}
if err := plugin.Install(config); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
fmt.Printf(" Guard script: %s\n", guardScriptPath)
}
// ---------------------------------------------------------------------------
// uninstall
// ---------------------------------------------------------------------------
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)
if *agent == "" {
fmt.Fprintln(os.Stderr, "Error: --agent is required.")
fmt.Fprintln(os.Stderr)
fs.Usage()
os.Exit(1)
}
plugin := plugins.NewPlugin(*agent)
if plugin == nil {
fmt.Fprintf(os.Stderr, "Error: unsupported agent %q. Run 'elydora agents' to see supported agents.\n", *agent)
os.Exit(1)
}
resolvedAgentID, agentDirectory, agentDirectoryExists, err := resolveAgentRuntimeForUninstall(*agent, *agentID)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
if resolvedAgentID == "" {
fmt.Fprintf(os.Stderr, "Error: could not find agent ID for %q in ~/.elydora/*/config.json; pass --agent-id explicitly\n", *agent)
os.Exit(1)
}
if err := plugin.Uninstall(resolvedAgentID); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
// Remove the per-agent directory
if agentDirectoryExists {
if err := os.RemoveAll(agentDirectory); err != nil {
fmt.Fprintf(os.Stderr, "Error removing agent directory %s: %v\n", agentDirectory, err)
os.Exit(1)
}
fmt.Printf(" Removed agent directory: %s\n", agentDirectory)
}
}
// ---------------------------------------------------------------------------
// status
// ---------------------------------------------------------------------------
func cmdStatus(args []string) {
fs := flag.NewFlagSet("status", flag.ExitOnError)
agent := fs.String("agent", "", "Agent name (optional — omit to show all)")
fs.Parse(args)
if *agent != "" {
showAgentStatus(*agent)
return
}
// Show status for all agents
names := sortedAgentNames()
for _, name := range names {
showAgentStatus(name)
}
}
func showAgentStatus(name string) {
plugin := plugins.NewPlugin(name)
if plugin == nil {
fmt.Fprintf(os.Stderr, "Unknown agent: %s\n", name)
return
}
status, err := plugin.Status()
if err != nil {
fmt.Fprintf(os.Stderr, " %s: error getting status: %v\n", name, err)
return
}
state := "not installed"
if status.Installed {
state = "installed"
} else if status.HookConfigured && !status.HookScriptExists {
state = "configured (hook script missing)"
} else if !status.HookConfigured && status.HookScriptExists {
state = "hook script exists (not configured)"
}
fmt.Printf(" %-14s %-20s %s\n", name, status.DisplayName, state)
}
// ---------------------------------------------------------------------------
// agents
// ---------------------------------------------------------------------------
func cmdAgents() {
fmt.Println("Supported agents:")
fmt.Println()
fmt.Printf(" %-14s %-20s %s\n", "ID", "Name", "Config")
fmt.Printf(" %-14s %-20s %s\n", strings.Repeat("-", 14), strings.Repeat("-", 20), strings.Repeat("-", 30))
names := sortedAgentNames()
for _, name := range names {
entry := plugins.SupportedAgents[name]
configPath := entry.ConfigDir + "/" + entry.ConfigFile // display only, not a filesystem path
fmt.Printf(" %-14s %-20s %s\n", name, entry.Name, configPath)
}
}
func sortedAgentNames() []string {
names := make([]string, 0, len(plugins.SupportedAgents))
for name := range plugins.SupportedAgents {
names = append(names, name)
}
sort.Strings(names)
return names
}
// guardScriptPathForAgent returns the path to ~/.elydora/<agentId>/guard.js.
func guardScriptPathForAgent(agentId string) (string, error) {
agentDirectory, err := plugins.ResolveAgentRuntimeDirectory(agentId)
if err != nil {
return "", err
}
return filepath.Join(agentDirectory, "guard.js"), nil
}