mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-23 10:28:06 +00:00
feat: waiter connection manager - save/switch/delete connections, auto-apply default
This commit is contained in:
@ -17,6 +17,10 @@ func handleBuiltin(cmd string, cfg *Config, state *State, reconnect func()) bool
|
||||
/connect <path> switch to a different unix socket
|
||||
/remote <url> switch to remote HTTP mode
|
||||
/local switch back to local socket mode
|
||||
/conn list list saved connections
|
||||
/conn save <name> save current connection as <name>
|
||||
/conn use <name> switch to saved connection
|
||||
/conn del <name> delete saved connection
|
||||
|
||||
Server commands (sent to agent):
|
||||
/status system status
|
||||
@ -66,6 +70,48 @@ Any other text is sent to the agent directly.`)
|
||||
reconnect()
|
||||
return true
|
||||
|
||||
case cmd == "/conn list":
|
||||
if len(cfg.Connections) == 0 {
|
||||
fmt.Println("no saved connections")
|
||||
}
|
||||
for _, c := range cfg.Connections {
|
||||
mark := " "
|
||||
if c.Name == cfg.Default {
|
||||
mark = "*"
|
||||
}
|
||||
addr := c.Remote
|
||||
if addr == "" {
|
||||
addr = c.Socket
|
||||
}
|
||||
fmt.Printf(" %s %-15s %s\n", mark, c.Name, addr)
|
||||
}
|
||||
return true
|
||||
|
||||
case strings.HasPrefix(cmd, "/conn save "):
|
||||
name := strings.TrimSpace(cmd[11:])
|
||||
cfg.SaveConnection(name)
|
||||
fmt.Printf("connection saved as '%s' (default)\n", name)
|
||||
return true
|
||||
|
||||
case strings.HasPrefix(cmd, "/conn use "):
|
||||
name := strings.TrimSpace(cmd[10:])
|
||||
if cfg.SwitchConnection(name) {
|
||||
fmt.Printf("switched to '%s'\n", name)
|
||||
reconnect()
|
||||
} else {
|
||||
fmt.Printf("connection '%s' not found\n", name)
|
||||
}
|
||||
return true
|
||||
|
||||
case strings.HasPrefix(cmd, "/conn del "):
|
||||
name := strings.TrimSpace(cmd[10:])
|
||||
if cfg.DeleteConnection(name) {
|
||||
fmt.Printf("connection '%s' deleted\n", name)
|
||||
} else {
|
||||
fmt.Printf("connection '%s' not found\n", name)
|
||||
}
|
||||
return true
|
||||
|
||||
case cmd == "/status":
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
d, _ := rc.DoAPI("GET", "/api/v1/status", "")
|
||||
|
||||
@ -8,10 +8,40 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Connection struct {
|
||||
Name string `yaml:"name"`
|
||||
Socket string `yaml:"socket,omitempty"`
|
||||
Remote string `yaml:"remote,omitempty"`
|
||||
APIKey string `yaml:"api_key,omitempty"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Socket string `yaml:"socket"`
|
||||
Remote string `yaml:"remote"`
|
||||
APIKey string `yaml:"api_key"`
|
||||
Socket string `yaml:"socket"`
|
||||
Remote string `yaml:"remote"`
|
||||
APIKey string `yaml:"api_key"`
|
||||
Default string `yaml:"default"`
|
||||
Connections []Connection `yaml:"connections,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Config) Active() *Connection {
|
||||
for i := range c.Connections {
|
||||
if c.Connections[i].Name == c.Default {
|
||||
return &c.Connections[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) ApplyDefault() {
|
||||
conn := c.Active()
|
||||
if conn == nil {
|
||||
return
|
||||
}
|
||||
if c.Socket == "" && c.Remote == "" {
|
||||
c.Socket = conn.Socket
|
||||
c.Remote = conn.Remote
|
||||
c.APIKey = conn.APIKey
|
||||
}
|
||||
}
|
||||
|
||||
func discoverConfig(configPath string) *Config {
|
||||
@ -48,6 +78,14 @@ func configCandidates() []string {
|
||||
return cands
|
||||
}
|
||||
|
||||
func configPath() string {
|
||||
home, _ := os.UserHomeDir()
|
||||
if home == "" {
|
||||
return ""
|
||||
}
|
||||
return filepath.Join(home, ".config", "homeagent", "waiter.yaml")
|
||||
}
|
||||
|
||||
func readFile(path string) *Config {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
@ -61,6 +99,19 @@ func readFile(path string) *Config {
|
||||
return &cfg
|
||||
}
|
||||
|
||||
func (c *Config) Save() {
|
||||
p := configPath()
|
||||
if p == "" {
|
||||
return
|
||||
}
|
||||
os.MkdirAll(filepath.Dir(p), 0755)
|
||||
data, err := yaml.Marshal(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
os.WriteFile(p, data, 0644)
|
||||
}
|
||||
|
||||
func (c *Config) MergeCLI(socket, remote, apiKey string) {
|
||||
if socket != "" {
|
||||
c.Socket = socket
|
||||
@ -72,3 +123,51 @@ func (c *Config) MergeCLI(socket, remote, apiKey string) {
|
||||
c.APIKey = apiKey
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) SaveConnection(name string) {
|
||||
conn := Connection{
|
||||
Name: name,
|
||||
Socket: c.Socket,
|
||||
Remote: c.Remote,
|
||||
APIKey: c.APIKey,
|
||||
}
|
||||
for i, existing := range c.Connections {
|
||||
if existing.Name == name {
|
||||
c.Connections[i] = conn
|
||||
c.Default = name
|
||||
c.Save()
|
||||
return
|
||||
}
|
||||
}
|
||||
c.Connections = append(c.Connections, conn)
|
||||
c.Default = name
|
||||
c.Save()
|
||||
}
|
||||
|
||||
func (c *Config) SwitchConnection(name string) bool {
|
||||
for _, conn := range c.Connections {
|
||||
if conn.Name == name {
|
||||
c.Socket = conn.Socket
|
||||
c.Remote = conn.Remote
|
||||
c.APIKey = conn.APIKey
|
||||
c.Default = name
|
||||
c.Save()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Config) DeleteConnection(name string) bool {
|
||||
for i, conn := range c.Connections {
|
||||
if conn.Name == name {
|
||||
c.Connections = append(c.Connections[:i], c.Connections[i+1:]...)
|
||||
if c.Default == name {
|
||||
c.Default = ""
|
||||
}
|
||||
c.Save()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@ -86,6 +86,7 @@ func main() {
|
||||
|
||||
cfg := discoverConfig(*configPath)
|
||||
cfg.MergeCLI(*socket, *remote, *apiKey)
|
||||
cfg.ApplyDefault()
|
||||
|
||||
if cfg.Socket == "" && cfg.Remote == "" {
|
||||
cfg.Socket = discoverSocket("")
|
||||
|
||||
Reference in New Issue
Block a user