initial agent-mgr: app builder platform MVP
Go API server + Preact UI + Claude Code adapter. - App-centric model (ideas, not repos) - AgentProvider interface for multi-agent support - K8s pod lifecycle for sandboxed agent sessions - Gitea integration (create repos, push branches) - WebSocket streaming for live session output - Woodpecker CI/CD pipelines (kaniko build + kubectl deploy)
This commit is contained in:
136
internal/api/sessions.go
Normal file
136
internal/api/sessions.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/agentsphere/agent-mgr/internal/store"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type createSessionRequest struct {
|
||||
Prompt string `json:"prompt"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
Config json.RawMessage `json:"config,omitempty"`
|
||||
}
|
||||
|
||||
type sendMessageRequest struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (s *Server) createSession(w http.ResponseWriter, r *http.Request) {
|
||||
appID, err := uuid.Parse(chi.URLParam(r, "appID"))
|
||||
if err != nil {
|
||||
http.Error(w, `{"error":"invalid app id"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var req createSessionRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, `{"error":"invalid request body"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.Prompt == "" {
|
||||
http.Error(w, `{"error":"prompt required"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
app, err := s.store.GetApp(r.Context(), appID)
|
||||
if err != nil || app == nil {
|
||||
http.Error(w, `{"error":"app not found"}`, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
sess, err := s.app.StartSession(r.Context(), app, req.Prompt, req.Provider, req.Config)
|
||||
if err != nil {
|
||||
s.log.Error("create session failed", "err", err)
|
||||
http.Error(w, `{"error":"failed to create session"}`, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(map[string]any{"session": sess})
|
||||
}
|
||||
|
||||
func (s *Server) listSessions(w http.ResponseWriter, r *http.Request) {
|
||||
appID, err := uuid.Parse(chi.URLParam(r, "appID"))
|
||||
if err != nil {
|
||||
http.Error(w, `{"error":"invalid app id"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
sessions, err := s.store.ListSessionsByApp(r.Context(), appID)
|
||||
if err != nil {
|
||||
http.Error(w, `{"error":"failed to list sessions"}`, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if sessions == nil {
|
||||
sessions = []store.Session{}
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(map[string]any{"sessions": sessions})
|
||||
}
|
||||
|
||||
func (s *Server) getSession(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := uuid.Parse(chi.URLParam(r, "sessionID"))
|
||||
if err != nil {
|
||||
http.Error(w, `{"error":"invalid session id"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
sess, err := s.store.GetSession(r.Context(), id)
|
||||
if err != nil || sess == nil {
|
||||
http.Error(w, `{"error":"session not found"}`, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(map[string]any{"session": sess})
|
||||
}
|
||||
|
||||
func (s *Server) stopSession(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := uuid.Parse(chi.URLParam(r, "sessionID"))
|
||||
if err != nil {
|
||||
http.Error(w, `{"error":"invalid session id"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.app.StopSession(r.Context(), id); err != nil {
|
||||
s.log.Error("stop session failed", "err", err)
|
||||
http.Error(w, `{"error":"failed to stop session"}`, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(map[string]any{"status": "stopped"})
|
||||
}
|
||||
|
||||
func (s *Server) sendMessage(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := uuid.Parse(chi.URLParam(r, "sessionID"))
|
||||
if err != nil {
|
||||
http.Error(w, `{"error":"invalid session id"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var req sendMessageRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, `{"error":"invalid request body"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.Message == "" {
|
||||
http.Error(w, `{"error":"message required"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.app.SendMessage(r.Context(), id, req.Message); err != nil {
|
||||
s.log.Error("send message failed", "err", err)
|
||||
http.Error(w, `{"error":"failed to send message"}`, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(map[string]any{"status": "sent"})
|
||||
}
|
||||
|
||||
func (s *Server) listProviders(w http.ResponseWriter, r *http.Request) {
|
||||
infos := s.registry.List()
|
||||
json.NewEncoder(w).Encode(map[string]any{"providers": infos})
|
||||
}
|
||||
Reference in New Issue
Block a user