diff options
Diffstat (limited to 'internal/api/server.go')
| -rw-r--r-- | internal/api/server.go | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/internal/api/server.go b/internal/api/server.go index 608cdd4..bac98b6 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -24,9 +24,10 @@ type Server struct { hub *Hub logger *slog.Logger mux *http.ServeMux - claudeBinPath string // path to claude binary; defaults to "claude" - elaborateCmdPath string // overrides claudeBinPath; used in tests - workDir string // working directory injected into elaborate system prompt + claudeBinPath string // path to claude binary; defaults to "claude" + elaborateCmdPath string // overrides claudeBinPath; used in tests + startNextTaskScript string // path to start-next-task script; overridden in tests + workDir string // working directory injected into elaborate system prompt } func NewServer(store *storage.DB, pool *executor.Pool, logger *slog.Logger, claudeBinPath string) *Server { @@ -71,6 +72,8 @@ func (s *Server) routes() { s.mux.HandleFunc("GET /api/templates/{id}", s.handleGetTemplate) s.mux.HandleFunc("PUT /api/templates/{id}", s.handleUpdateTemplate) s.mux.HandleFunc("DELETE /api/templates/{id}", s.handleDeleteTemplate) + s.mux.HandleFunc("POST /api/tasks/{id}/answer", s.handleAnswerQuestion) + s.mux.HandleFunc("POST /api/scripts/start-next-task", s.handleStartNextTask) s.mux.HandleFunc("GET /api/ws", s.handleWebSocket) s.mux.HandleFunc("GET /api/health", s.handleHealth) s.mux.Handle("GET /", http.FileServerFS(webui.Files)) @@ -93,6 +96,49 @@ func (s *Server) forwardResults() { } } +// BroadcastQuestion sends a task_question event to all WebSocket clients. +func (s *Server) BroadcastQuestion(taskID, toolUseID string, questionData json.RawMessage) { + event := map[string]interface{}{ + "type": "task_question", + "task_id": taskID, + "question_id": toolUseID, + "data": json.RawMessage(questionData), + "timestamp": time.Now().UTC(), + } + data, _ := json.Marshal(event) + s.hub.Broadcast(data) +} + +func (s *Server) handleAnswerQuestion(w http.ResponseWriter, r *http.Request) { + taskID := r.PathValue("id") + + if _, err := s.store.GetTask(taskID); err != nil { + writeJSON(w, http.StatusNotFound, map[string]string{"error": "task not found"}) + return + } + + var input struct { + QuestionID string `json:"question_id"` + Answer string `json:"answer"` + } + if err := json.NewDecoder(r.Body).Decode(&input); err != nil { + writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON: " + err.Error()}) + return + } + if input.QuestionID == "" { + writeJSON(w, http.StatusBadRequest, map[string]string{"error": "question_id is required"}) + return + } + + ok := s.pool.Questions.Answer(input.QuestionID, input.Answer) + if !ok { + writeJSON(w, http.StatusNotFound, map[string]string{"error": "no pending question with that ID"}) + return + } + + writeJSON(w, http.StatusOK, map[string]string{"status": "delivered"}) +} + func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, map[string]string{"status": "ok"}) } |
