diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-03-09 01:17:19 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-03-09 01:17:19 +0000 |
| commit | 601d1eaebcea11d6228dd10ee1a198bc2c6a1ad5 (patch) | |
| tree | 4f2d13c03574db93b946587596933ee31fee2586 /internal | |
| parent | 13846ea4ce4bacfadda6f86c5e48e5e76e13db07 (diff) | |
chore: remove deleted template files from git
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/api/templates.go | 150 | ||||
| -rw-r--r-- | internal/api/templates_test.go | 184 | ||||
| -rw-r--r-- | internal/storage/templates.go | 140 |
3 files changed, 0 insertions, 474 deletions
diff --git a/internal/api/templates.go b/internal/api/templates.go deleted file mode 100644 index 024a6df..0000000 --- a/internal/api/templates.go +++ /dev/null @@ -1,150 +0,0 @@ -package api - -import ( - "encoding/json" - "errors" - "net/http" - "time" - - "github.com/google/uuid" - "github.com/thepeterstone/claudomator/internal/storage" - "github.com/thepeterstone/claudomator/internal/task" -) - -func (s *Server) handleListTemplates(w http.ResponseWriter, r *http.Request) { - templates, err := s.store.ListTemplates() - if err != nil { - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) - return - } - if templates == nil { - templates = []*storage.Template{} - } - writeJSON(w, http.StatusOK, templates) -} - -func (s *Server) handleCreateTemplate(w http.ResponseWriter, r *http.Request) { - var input struct { - Name string `json:"name"` - Description string `json:"description"` - Agent task.AgentConfig `json:"agent"` - Timeout string `json:"timeout"` - Priority string `json:"priority"` - Tags []string `json:"tags"` - } - 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.Name == "" { - writeJSON(w, http.StatusBadRequest, map[string]string{"error": "name is required"}) - return - } - - now := time.Now().UTC() - tmpl := &storage.Template{ - ID: uuid.New().String(), - Name: input.Name, - Description: input.Description, - Agent: input.Agent, - Timeout: input.Timeout, - Priority: input.Priority, - Tags: input.Tags, - CreatedAt: now, - UpdatedAt: now, - } - if tmpl.Agent.Type == "" { - tmpl.Agent.Type = "claude" - } - if tmpl.Priority == "" { - tmpl.Priority = "normal" - } - if tmpl.Tags == nil { - tmpl.Tags = []string{} - } - - if err := s.store.CreateTemplate(tmpl); err != nil { - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) - return - } - writeJSON(w, http.StatusCreated, tmpl) -} - -func (s *Server) handleGetTemplate(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - tmpl, err := s.store.GetTemplate(id) - if err != nil { - if errors.Is(err, storage.ErrTemplateNotFound) { - writeJSON(w, http.StatusNotFound, map[string]string{"error": "template not found"}) - return - } - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) - return - } - writeJSON(w, http.StatusOK, tmpl) -} - -// handleUpdateTemplate fully replaces all fields of the template identified by {id}. -// All fields from the request body overwrite existing values; name is required. -func (s *Server) handleUpdateTemplate(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - existing, err := s.store.GetTemplate(id) - if err != nil { - if errors.Is(err, storage.ErrTemplateNotFound) { - writeJSON(w, http.StatusNotFound, map[string]string{"error": "template not found"}) - return - } - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) - return - } - - var input struct { - Name string `json:"name"` - Description string `json:"description"` - Agent task.AgentConfig `json:"agent"` - Timeout string `json:"timeout"` - Priority string `json:"priority"` - Tags []string `json:"tags"` - } - 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.Name == "" { - writeJSON(w, http.StatusBadRequest, map[string]string{"error": "name is required"}) - return - } - - existing.Name = input.Name - existing.Description = input.Description - existing.Agent = input.Agent - if existing.Agent.Type == "" { - existing.Agent.Type = "claude" - } - existing.Timeout = input.Timeout - existing.Priority = input.Priority - if input.Tags != nil { - existing.Tags = input.Tags - } - existing.UpdatedAt = time.Now().UTC() - - if err := s.store.UpdateTemplate(existing); err != nil { - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) - return - } - writeJSON(w, http.StatusOK, existing) -} - -func (s *Server) handleDeleteTemplate(w http.ResponseWriter, r *http.Request) { - id := r.PathValue("id") - err := s.store.DeleteTemplate(id) - if err != nil { - if errors.Is(err, storage.ErrTemplateNotFound) { - writeJSON(w, http.StatusNotFound, map[string]string{"error": "template not found"}) - return - } - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) - return - } - w.WriteHeader(http.StatusNoContent) -} diff --git a/internal/api/templates_test.go b/internal/api/templates_test.go deleted file mode 100644 index 474c5d4..0000000 --- a/internal/api/templates_test.go +++ /dev/null @@ -1,184 +0,0 @@ -package api - -import ( - "bytes" - "encoding/json" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/thepeterstone/claudomator/internal/storage" -) - -func TestListTemplates_Empty(t *testing.T) { - srv, _ := testServer(t) - - req := httptest.NewRequest("GET", "/api/templates", nil) - w := httptest.NewRecorder() - srv.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusOK { - t.Fatalf("status: want 200, got %d; body: %s", w.Code, w.Body.String()) - } - var templates []storage.Template - json.NewDecoder(w.Body).Decode(&templates) - if len(templates) != 0 { - t.Errorf("want 0 templates, got %d", len(templates)) - } -} - -func TestCreateTemplate_Success(t *testing.T) { - srv, _ := testServer(t) - - payload := `{ - "name": "Go: Run Tests", - "description": "Run the full test suite with race detector", - "agent": { - "type": "claude", - "model": "sonnet", - "instructions": "Run go test -race ./...", - "max_budget_usd": 0.50, - "allowed_tools": ["Bash"] - }, - "timeout": "10m", - "priority": "normal", - "tags": ["go", "testing"] - }` - req := httptest.NewRequest("POST", "/api/templates", bytes.NewBufferString(payload)) - req.Header.Set("Content-Type", "application/json") - w := httptest.NewRecorder() - srv.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusCreated { - t.Fatalf("status: want 201, got %d; body: %s", w.Code, w.Body.String()) - } - var created storage.Template - json.NewDecoder(w.Body).Decode(&created) - if created.Name != "Go: Run Tests" { - t.Errorf("name: want 'Go: Run Tests', got %q", created.Name) - } - if created.ID == "" { - t.Error("expected auto-generated ID") - } -} - -func TestGetTemplate_AfterCreate(t *testing.T) { - srv, _ := testServer(t) - - payload := `{"name": "Fetch Me", "agent": {"type": "claude", "instructions": "do thing", "model": "haiku"}}` - req := httptest.NewRequest("POST", "/api/templates", bytes.NewBufferString(payload)) - w := httptest.NewRecorder() - srv.Handler().ServeHTTP(w, req) - if w.Code != http.StatusCreated { - t.Fatalf("create: want 201, got %d", w.Code) - } - var created storage.Template - json.NewDecoder(w.Body).Decode(&created) - - req2 := httptest.NewRequest("GET", fmt.Sprintf("/api/templates/%s", created.ID), nil) - w2 := httptest.NewRecorder() - srv.Handler().ServeHTTP(w2, req2) - - if w2.Code != http.StatusOK { - t.Fatalf("get: want 200, got %d; body: %s", w2.Code, w2.Body.String()) - } - var fetched storage.Template - json.NewDecoder(w2.Body).Decode(&fetched) - if fetched.ID != created.ID { - t.Errorf("id: want %q, got %q", created.ID, fetched.ID) - } - if fetched.Name != "Fetch Me" { - t.Errorf("name: want 'Fetch Me', got %q", fetched.Name) - } -} - -func TestGetTemplate_NotFound(t *testing.T) { - srv, _ := testServer(t) - - req := httptest.NewRequest("GET", "/api/templates/nonexistent", nil) - w := httptest.NewRecorder() - srv.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusNotFound { - t.Errorf("status: want 404, got %d", w.Code) - } -} - -func TestUpdateTemplate(t *testing.T) { - srv, _ := testServer(t) - - payload := `{"name": "Original Name", "agent": {"type": "claude", "instructions": "original"}}` - req := httptest.NewRequest("POST", "/api/templates", bytes.NewBufferString(payload)) - w := httptest.NewRecorder() - srv.Handler().ServeHTTP(w, req) - var created storage.Template - json.NewDecoder(w.Body).Decode(&created) - - update := `{"name": "Updated Name", "agent": {"type": "claude", "instructions": "updated"}}` - req2 := httptest.NewRequest("PUT", fmt.Sprintf("/api/templates/%s", created.ID), bytes.NewBufferString(update)) - w2 := httptest.NewRecorder() - srv.Handler().ServeHTTP(w2, req2) - - if w2.Code != http.StatusOK { - t.Fatalf("update: want 200, got %d; body: %s", w2.Code, w2.Body.String()) - } - var updated storage.Template - json.NewDecoder(w2.Body).Decode(&updated) - if updated.Name != "Updated Name" { - t.Errorf("name: want 'Updated Name', got %q", updated.Name) - } -} - -func TestUpdateTemplate_NotFound(t *testing.T) { - srv, _ := testServer(t) - - update := `{"name": "Ghost", "agent": {"type": "claude", "instructions": "x"}}` - req := httptest.NewRequest("PUT", "/api/templates/nonexistent", bytes.NewBufferString(update)) - w := httptest.NewRecorder() - srv.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusNotFound { - t.Errorf("status: want 404, got %d", w.Code) - } -} - -func TestDeleteTemplate(t *testing.T) { - srv, _ := testServer(t) - - payload := `{"name": "To Delete", "agent": {"type": "claude", "instructions": "bye"}}` - req := httptest.NewRequest("POST", "/api/templates", bytes.NewBufferString(payload)) - w := httptest.NewRecorder() - srv.Handler().ServeHTTP(w, req) - var created storage.Template - json.NewDecoder(w.Body).Decode(&created) - - req2 := httptest.NewRequest("DELETE", fmt.Sprintf("/api/templates/%s", created.ID), nil) - w2 := httptest.NewRecorder() - srv.Handler().ServeHTTP(w2, req2) - - if w2.Code != http.StatusNoContent { - t.Fatalf("delete: want 204, got %d; body: %s", w2.Code, w2.Body.String()) - } - - // Subsequent GET returns 404. - req3 := httptest.NewRequest("GET", fmt.Sprintf("/api/templates/%s", created.ID), nil) - w3 := httptest.NewRecorder() - srv.Handler().ServeHTTP(w3, req3) - - if w3.Code != http.StatusNotFound { - t.Fatalf("get after delete: want 404, got %d", w3.Code) - } -} - -func TestDeleteTemplate_NotFound(t *testing.T) { - srv, _ := testServer(t) - - req := httptest.NewRequest("DELETE", "/api/templates/nonexistent", nil) - w := httptest.NewRecorder() - srv.Handler().ServeHTTP(w, req) - - if w.Code != http.StatusNotFound { - t.Errorf("status: want 404, got %d", w.Code) - } -} diff --git a/internal/storage/templates.go b/internal/storage/templates.go deleted file mode 100644 index 57abaa4..0000000 --- a/internal/storage/templates.go +++ /dev/null @@ -1,140 +0,0 @@ -package storage - -import ( - "database/sql" - "encoding/json" - "errors" - "fmt" - "time" - - "github.com/thepeterstone/claudomator/internal/task" -) - -// ErrTemplateNotFound is returned when a template ID does not exist. -var ErrTemplateNotFound = errors.New("template not found") - -// Template is a reusable task configuration saved for repeated use. -type Template struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Agent task.AgentConfig `json:"agent"` - Timeout string `json:"timeout"` - Priority string `json:"priority"` - Tags []string `json:"tags"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` -} - -// CreateTemplate inserts a new template. -func (s *DB) CreateTemplate(tmpl *Template) error { - configJSON, err := json.Marshal(tmpl.Agent) - if err != nil { - return fmt.Errorf("marshaling config: %w", err) - } - tagsJSON, err := json.Marshal(tmpl.Tags) - if err != nil { - return fmt.Errorf("marshaling tags: %w", err) - } - _, err = s.db.Exec(` - INSERT INTO templates (id, name, description, config_json, timeout, priority, tags_json, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, - tmpl.ID, tmpl.Name, tmpl.Description, string(configJSON), - tmpl.Timeout, tmpl.Priority, string(tagsJSON), - tmpl.CreatedAt.UTC(), tmpl.UpdatedAt.UTC(), - ) - return err -} - -// GetTemplate retrieves a template by ID, returning ErrTemplateNotFound if missing. -func (s *DB) GetTemplate(id string) (*Template, error) { - row := s.db.QueryRow(`SELECT id, name, description, config_json, timeout, priority, tags_json, created_at, updated_at FROM templates WHERE id = ?`, id) - return scanTemplate(row) -} - -// ListTemplates returns all templates ordered by name. -func (s *DB) ListTemplates() ([]*Template, error) { - rows, err := s.db.Query(`SELECT id, name, description, config_json, timeout, priority, tags_json, created_at, updated_at FROM templates ORDER BY name ASC`) - if err != nil { - return nil, err - } - defer rows.Close() - - var templates []*Template - for rows.Next() { - tmpl, err := scanTemplate(rows) - if err != nil { - return nil, err - } - templates = append(templates, tmpl) - } - return templates, rows.Err() -} - -// UpdateTemplate fully replaces a template's fields. Returns ErrTemplateNotFound if the ID is missing. -func (s *DB) UpdateTemplate(tmpl *Template) error { - configJSON, err := json.Marshal(tmpl.Agent) - if err != nil { - return fmt.Errorf("marshaling config: %w", err) - } - tagsJSON, err := json.Marshal(tmpl.Tags) - if err != nil { - return fmt.Errorf("marshaling tags: %w", err) - } - result, err := s.db.Exec(` - UPDATE templates SET name = ?, description = ?, config_json = ?, timeout = ?, priority = ?, tags_json = ?, updated_at = ? - WHERE id = ?`, - tmpl.Name, tmpl.Description, string(configJSON), tmpl.Timeout, tmpl.Priority, string(tagsJSON), - tmpl.UpdatedAt.UTC(), tmpl.ID, - ) - if err != nil { - return err - } - n, err := result.RowsAffected() - if err != nil { - return err - } - if n == 0 { - return ErrTemplateNotFound - } - return nil -} - -// DeleteTemplate removes a template by ID. Returns ErrTemplateNotFound if the ID is missing. -func (s *DB) DeleteTemplate(id string) error { - result, err := s.db.Exec(`DELETE FROM templates WHERE id = ?`, id) - if err != nil { - return err - } - n, err := result.RowsAffected() - if err != nil { - return err - } - if n == 0 { - return ErrTemplateNotFound - } - return nil -} - -func scanTemplate(row scanner) (*Template, error) { - var ( - tmpl Template - configJSON string - tagsJSON string - ) - err := row.Scan(&tmpl.ID, &tmpl.Name, &tmpl.Description, &configJSON, - &tmpl.Timeout, &tmpl.Priority, &tagsJSON, &tmpl.CreatedAt, &tmpl.UpdatedAt) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return nil, ErrTemplateNotFound - } - return nil, err - } - if err := json.Unmarshal([]byte(configJSON), &tmpl.Agent); err != nil { - return nil, fmt.Errorf("unmarshaling config: %w", err) - } - if err := json.Unmarshal([]byte(tagsJSON), &tmpl.Tags); err != nil { - return nil, fmt.Errorf("unmarshaling tags: %w", err) - } - return &tmpl, nil -} |
