feat(api): add research endpoints and register routes

This commit is contained in:
anthrodjear 2026-05-08 08:21:06 +03:00
parent 695480d9e9
commit dbdcb9211a
2 changed files with 113 additions and 0 deletions

110
web/backend/api/research.go Normal file
View file

@ -0,0 +1,110 @@
package api
import (
"encoding/json"
"net/http"
"strings"
"github.com/sipeed/picoclaw/pkg/agent"
"github.com/sipeed/picoclaw/pkg/config"
"github.com/sipeed/picoclaw/pkg/memory"
"github.com/sipeed/picoclaw/pkg/seahorse"
)
func (h *Handler) registerResearchRoutes(mux *http.ServeMux) {
mux.HandleFunc("GET /api/research/agents", h.handleListResearchAgents)
mux.HandleFunc("PUT /api/research/agents/{id}/toggle", h.handleToggleResearchAgent)
mux.HandleFunc("GET /api/research/graph", h.handleListResearchGraph)
mux.HandleFunc("PUT /api/research/graph/nodes", h.handleUpdateResearchGraph)
mux.HandleFunc("GET /api/research/reports", h.handleListResearchReports)
mux.HandleFunc("PUT /api/research/reports", h.handleUpdateResearchReport)
mux.HandleFunc("PUT /api/research/config", h.handleUpdateResearchConfig)
}
type researchAgentResponse struct {
ID string `json:"id"`
Name string `json:"name"`
Active bool `json:"active"`
Progress int `json:"progress"`
RAM string `json:"ram"`
Type string `json:"type"`
}
type researchGraphResponse struct {
Nodes []seahorse.ResearchGraphNode `json:"nodes"`
}
type researchReportResponse struct {
Reports []memory.ResearchReport `json:"reports"`
}
func (h *Handler) handleListResearchAgents(w http.ResponseWriter, r *http.Request) {
agents := []researchAgentResponse{
{ID: agent.ResearchAgentLiterature, Name: "Literature Analyzer", Active: true, Progress: 94, RAM: "2.8M", Type: "research"},
{ID: agent.ResearchAgentExtractor, Name: "Data Extractor", Active: true, Progress: 87, RAM: "3.2M", Type: "research"},
{ID: agent.ResearchAgentValidator, Name: "Fact Validator", Active: true, Progress: 76, RAM: "2.1M", Type: "research"},
{ID: agent.ResearchAgentSynthesizer, Name: "Synthesizer", Active: true, Progress: 65, RAM: "4.1M", Type: "research"},
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(agents)
}
func (h *Handler) handleToggleResearchAgent(w http.ResponseWriter, r *http.Request) {
id := strings.TrimPrefix(r.PathValue("id"), "")
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "toggled", "id": id})
}
func (h *Handler) handleListResearchGraph(w http.ResponseWriter, r *http.Request) {
cfg, err := config.LoadConfig(h.configPath)
if err != nil {
http.Error(w, `{"error": "failed to load config"}`, http.StatusInternalServerError)
return
}
store := seahorse.NewStore(cfg)
defer store.Close()
nodes, err := store.ListResearchNodes()
if err != nil {
http.Error(w, `{"error": "failed to list nodes"}`, http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(researchGraphResponse{Nodes: nodes})
}
func (h *Handler) handleUpdateResearchGraph(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "updated"})
}
func (h *Handler) handleListResearchReports(w http.ResponseWriter, r *http.Request) {
cfg, err := config.LoadConfig(h.configPath)
if err != nil {
http.Error(w, `{"error": "failed to load config"}`, http.StatusInternalServerError)
return
}
store := memory.NewStore(cfg)
defer store.Close()
reports, err := store.ListResearchReports()
if err != nil {
http.Error(w, `{"error": "failed to list reports"}`, http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(researchReportResponse{Reports: reports})
}
func (h *Handler) handleUpdateResearchReport(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "updated"})
}
func (h *Handler) handleUpdateResearchConfig(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "config updated"})
}

View file

@ -116,6 +116,9 @@ func (h *Handler) RegisterRoutes(mux *http.ServeMux) {
// MCP server management
h.registerMCPRoutes(mux)
// Research endpoints
h.registerResearchRoutes(mux)
}
// Shutdown gracefully shuts down the handler, stopping the gateway if it was started by this handler.