Files
agent-mgr/internal/api/sessions.go
Steven Hooker e5b07cc1d8 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)
2026-02-18 15:56:32 +01:00

137 lines
3.8 KiB
Go

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})
}