mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 09:28:14 +00:00
feat: waiter CLI remote mode calls REST API directly for management commands
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
@ -28,6 +29,7 @@ Server commands (sent to agent):
|
||||
/plugin info <name> plugin details
|
||||
/memory query <text> query graph memory
|
||||
/knowledge list knowledge base
|
||||
/knowledge delete <name> delete knowledge item
|
||||
/agents list agents
|
||||
/chat <text> send to agent
|
||||
|
||||
@ -64,7 +66,136 @@ Any other text is sent to the agent directly.`)
|
||||
reconnect()
|
||||
return true
|
||||
|
||||
case cmd == "/status":
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
d, _ := rc.DoAPI("GET", "/api/v1/status", "")
|
||||
printJSON(d)
|
||||
} else {
|
||||
state.Send("/status")
|
||||
}
|
||||
return true
|
||||
|
||||
case cmd == "/kernel":
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
d, _ := rc.DoAPI("GET", "/api/v1/kernel", "")
|
||||
printJSON(d)
|
||||
} else {
|
||||
state.Send("/kernel")
|
||||
}
|
||||
return true
|
||||
|
||||
case strings.HasPrefix(cmd, "/settings set "):
|
||||
parts := strings.SplitN(cmd[14:], " ", 2)
|
||||
if len(parts) < 2 {
|
||||
fmt.Println("usage: /settings set <key> <value>")
|
||||
return true
|
||||
}
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
body := fmt.Sprintf(`{"%s":%q}`, parts[0], parts[1])
|
||||
rc.DoAPI("PUT", "/api/v1/settings", body)
|
||||
fmt.Println("ok")
|
||||
} else {
|
||||
state.Send(cmd[1:])
|
||||
}
|
||||
return true
|
||||
|
||||
case strings.HasPrefix(cmd, "/settings"):
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
d, _ := rc.DoAPI("GET", "/api/v1/settings", "")
|
||||
printJSON(d)
|
||||
} else {
|
||||
state.Send(cmd[1:])
|
||||
}
|
||||
return true
|
||||
|
||||
case cmd == "/plugin list":
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
d, _ := rc.DoAPI("GET", "/api/v1/plugins", "")
|
||||
printJSON(d)
|
||||
} else {
|
||||
state.Send("/plugin list")
|
||||
}
|
||||
return true
|
||||
|
||||
case strings.HasPrefix(cmd, "/plugin install "):
|
||||
url := strings.TrimSpace(cmd[16:])
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
body := fmt.Sprintf(`{"url":%q}`, url)
|
||||
d, _ := rc.DoAPI("POST", "/api/v1/plugins", body)
|
||||
printJSON(d)
|
||||
} else {
|
||||
state.Send(cmd[1:])
|
||||
}
|
||||
return true
|
||||
|
||||
case strings.HasPrefix(cmd, "/plugin remove "):
|
||||
name := strings.TrimSpace(cmd[15:])
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
d, _ := rc.DoAPI("DELETE", "/api/v1/plugins/"+name, "")
|
||||
printJSON(d)
|
||||
} else {
|
||||
state.Send(cmd[1:])
|
||||
}
|
||||
return true
|
||||
|
||||
case strings.HasPrefix(cmd, "/plugin info "):
|
||||
name := strings.TrimSpace(cmd[13:])
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
d, _ := rc.DoAPI("GET", "/api/v1/plugins/"+name, "")
|
||||
printJSON(d)
|
||||
} else {
|
||||
state.Send(cmd[1:])
|
||||
}
|
||||
return true
|
||||
|
||||
case strings.HasPrefix(cmd, "/memory query "):
|
||||
q := strings.TrimSpace(cmd[14:])
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
d, _ := rc.DoAPI("GET", "/api/v1/memory?query="+q, "")
|
||||
printJSON(d)
|
||||
} else {
|
||||
state.Send(cmd[1:])
|
||||
}
|
||||
return true
|
||||
|
||||
case strings.HasPrefix(cmd, "/knowledge delete "):
|
||||
name := strings.TrimSpace(cmd[18:])
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
d, _ := rc.DoAPI("DELETE", "/api/v1/knowledge/"+name, "")
|
||||
printJSON(d)
|
||||
} else {
|
||||
state.Send(cmd[1:])
|
||||
}
|
||||
return true
|
||||
|
||||
case cmd == "/knowledge":
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
d, _ := rc.DoAPI("GET", "/api/v1/knowledge", "")
|
||||
printJSON(d)
|
||||
} else {
|
||||
state.Send("/knowledge")
|
||||
}
|
||||
return true
|
||||
|
||||
case cmd == "/agents":
|
||||
if rc := state.RemoteConn(); rc != nil {
|
||||
d, _ := rc.DoAPI("GET", "/api/v1/agents", "")
|
||||
printJSON(d)
|
||||
} else {
|
||||
state.Send("/agents")
|
||||
}
|
||||
return true
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func printJSON(d map[string]interface{}) {
|
||||
if d == nil {
|
||||
fmt.Println("(no data)")
|
||||
return
|
||||
}
|
||||
b, _ := json.MarshalIndent(d, "", " ")
|
||||
fmt.Println(string(b))
|
||||
}
|
||||
|
||||
@ -76,19 +76,19 @@ func (c *localConn) Close() error {
|
||||
|
||||
func dialRemote(baseURL, apiKey string) (Conn, error) {
|
||||
baseURL = strings.TrimRight(baseURL, "/")
|
||||
return &remoteConn{url: baseURL + "/api/v1/chat", apiKey: apiKey}, nil
|
||||
return &remoteConn{baseURL: baseURL, apiKey: apiKey}, nil
|
||||
}
|
||||
|
||||
type remoteConn struct {
|
||||
url string
|
||||
apiKey string
|
||||
mu sync.Mutex
|
||||
buf []string
|
||||
closed bool
|
||||
baseURL string
|
||||
apiKey string
|
||||
mu sync.Mutex
|
||||
buf []string
|
||||
closed bool
|
||||
}
|
||||
|
||||
func (c *remoteConn) Send(line string) error {
|
||||
req, err := http.NewRequest("POST", c.url, strings.NewReader(
|
||||
req, err := http.NewRequest("POST", c.baseURL+"/api/v1/chat", strings.NewReader(
|
||||
fmt.Sprintf(`{"message":%q}`, line),
|
||||
))
|
||||
if err != nil {
|
||||
@ -117,6 +117,31 @@ func (c *remoteConn) Send(line string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *remoteConn) DoAPI(method, path string, body string) (map[string]interface{}, error) {
|
||||
var bodyReader io.Reader
|
||||
if body != "" {
|
||||
bodyReader = strings.NewReader(body)
|
||||
}
|
||||
req, err := http.NewRequest(method, c.baseURL+path, bodyReader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
if c.apiKey != "" {
|
||||
req.Header.Set("X-API-Key", c.apiKey)
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var result map[string]interface{}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *remoteConn) ReadLine() (string, error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
@ -41,6 +41,15 @@ func (s *State) Connected() bool {
|
||||
return s.conn != nil
|
||||
}
|
||||
|
||||
func (s *State) RemoteConn() *remoteConn {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if rc, ok := s.conn.(*remoteConn); ok {
|
||||
return rc
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *State) Send(line string) error {
|
||||
s.mu.Lock()
|
||||
c := s.conn
|
||||
|
||||
Reference in New Issue
Block a user