mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-22 01:48:11 +00:00
feat: expand local operator controls across CLI and WebUI
- Add structured CLI commands for status/kernel/settings/plugins/memory/knowledge/agents - Inject core dependencies directly into CLI plugin for non-HTTP operator workflows - Add plugin management panel and API proxy endpoints to WebUI - Let cmd_run inherit default workdir from core.agent.workdir - Use fixed loopback address for pluginmgr API - Remove stale MaxToolTurns config usage from homed wiring
This commit is contained in:
@ -4,6 +4,7 @@ import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
@ -103,6 +104,8 @@ func (h *Handler) RegisterRoutes(mux *http.ServeMux) {
|
||||
mux.HandleFunc("/api/v1/chat", h.handleChat)
|
||||
mux.HandleFunc("/api/v1/chat/events", h.handleChatEvents)
|
||||
mux.HandleFunc("/api/v1/kernel", h.handleKernel)
|
||||
mux.HandleFunc("/api/v1/plugins", h.handlePlugins)
|
||||
mux.HandleFunc("/api/v1/plugins/", h.handlePluginByID)
|
||||
mux.HandleFunc("/v1/chat/completions", h.handleOpenAICompletions)
|
||||
mux.HandleFunc("/", h.handleStatic)
|
||||
}
|
||||
@ -908,6 +911,90 @@ func (h *Handler) handleTracker(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// ======== Plugin Management (proxied to pluginmgr HTTP API) ========
|
||||
|
||||
func (h *Handler) pluginmgrAddr() string {
|
||||
addr := "127.0.0.1:9876"
|
||||
if h.cfgReg == nil {
|
||||
return addr
|
||||
}
|
||||
ps := h.cfgReg.PluginConfig("pluginmgr")
|
||||
if v, err := ps.Get("http_addr"); err == nil {
|
||||
if s, ok := v.(string); ok && s != "" {
|
||||
addr = s
|
||||
}
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
func (h *Handler) proxyToPluginmgr(w http.ResponseWriter, r *http.Request, path string) {
|
||||
addr := h.pluginmgrAddr()
|
||||
url := "http://" + addr + path
|
||||
req, err := http.NewRequestWithContext(r.Context(), r.Method, url, r.Body)
|
||||
if err != nil {
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
req.Header = r.Header.Clone()
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
writeJSON(w, http.StatusBadGateway, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
for k, v := range resp.Header {
|
||||
w.Header()[k] = v
|
||||
}
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
io.Copy(w, resp.Body)
|
||||
}
|
||||
|
||||
func (h *Handler) handlePlugins(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
h.proxyToPluginmgr(w, r, "/plugins")
|
||||
case http.MethodPost:
|
||||
h.proxyToPluginmgr(w, r, "/plugins")
|
||||
default:
|
||||
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handlePluginByID(w http.ResponseWriter, r *http.Request) {
|
||||
path := strings.TrimPrefix(r.URL.Path, "/api/v1/plugins/")
|
||||
path = strings.TrimSuffix(path, "/")
|
||||
|
||||
if path == "reload" && r.Method == http.MethodPost {
|
||||
if h.pluginReg == nil {
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "plugin registry not available"})
|
||||
return
|
||||
}
|
||||
dir := ""
|
||||
if h.cfgReg != nil {
|
||||
if v, _ := h.cfgReg.Get("core.plugin.dir"); v != nil {
|
||||
dir, _ = v.(string)
|
||||
}
|
||||
}
|
||||
if _, err := h.pluginReg.Reload(dir); err != nil {
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "reloaded"})
|
||||
return
|
||||
}
|
||||
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
h.proxyToPluginmgr(w, r, "/plugins/"+path)
|
||||
case http.MethodDelete:
|
||||
h.proxyToPluginmgr(w, r, "/plugins/"+path)
|
||||
default:
|
||||
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) handleStatic(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/" {
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
|
||||
Reference in New Issue
Block a user