Files
ai-workflow/inbox/internal/httpapi/config.go
T

136 lines
5.8 KiB
Go

package httpapi
import (
"database/sql"
"errors"
"net/http"
"os"
"strings"
"inbox/internal/base/httpx"
"inbox/internal/base/timeutil"
"inbox/internal/inboxapp"
sqlitestore "inbox/internal/store/sqlite"
)
type HandlerOptions = inboxapp.Options
type Services = inboxapp.Services
type Handler struct {
Services
}
func NewHandler(store *sqlitestore.Store, clock timeutil.Clock) http.Handler {
return NewHandlerWithOptions(store, clock, HandlerOptions{})
}
func NewHandlerWithOptions(store *sqlitestore.Store, clock timeutil.Clock, opts HandlerOptions) http.Handler {
return NewHandlerWithServices(inboxapp.BuildServices(store, clock, opts))
}
func NewHandlerWithServices(services Services) http.Handler {
handler := &Handler{Services: services}
mux := http.NewServeMux()
handler.register(mux)
return httpx.CORSMiddleware(mux)
}
func writeSystemFSError(w http.ResponseWriter, err error) {
var pathErr *os.PathError
if isValidationError(err) || errors.As(err, &pathErr) {
httpx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
httpx.WriteError(w, http.StatusInternalServerError, err.Error())
}
func (h *Handler) register(mux *http.ServeMux) {
mux.HandleFunc("GET /api/v2/config/roles", h.listRoles)
mux.HandleFunc("GET /api/v2/config/roles/{roleName}", h.getRoleDetail)
mux.HandleFunc("PUT /api/v2/config/roles/{roleName}", h.putRole)
mux.HandleFunc("PUT /api/v2/config/roles/{roleName}/prompts/{promptKind}", h.putRolePrompt)
mux.HandleFunc("PUT /api/v2/config/roles/{roleName}/config", h.putRoleConfig)
mux.HandleFunc("GET /api/v2/config/skills", h.listSkills)
mux.HandleFunc("PUT /api/v2/config/skills/{skillKey}", h.putSkill)
mux.HandleFunc("DELETE /api/v2/config/skills/{skillKey}", h.deleteSkill)
mux.HandleFunc("PUT /api/v2/config/roles/{roleName}/skills/{skillKey}", h.putRoleSkillBinding)
mux.HandleFunc("GET /api/v2/runtime/roles/{roleName}", h.getResolvedRole)
mux.HandleFunc("GET /api/v2/projects", h.listProjects)
mux.HandleFunc("POST /api/v2/projects", h.createProject)
mux.HandleFunc("GET /api/v2/workspaces", h.listWorkspaces)
mux.HandleFunc("POST /api/v2/workspaces", h.createWorkspace)
mux.HandleFunc("POST /api/v2/workspaces/provision", h.provisionWorkspace)
mux.HandleFunc("GET /api/v2/topics", h.listTopics)
mux.HandleFunc("POST /api/v2/topics", h.createTopic)
mux.HandleFunc("GET /api/v2/topics/{topicID}", h.getTopic)
mux.HandleFunc("POST /api/v2/topics/{topicID}/confirm", h.confirmTopicPlan)
mux.HandleFunc("POST /api/v2/topics/{topicID}/stop", h.stopTopic)
mux.HandleFunc("DELETE /api/v2/topics/{topicID}", h.deleteTopic)
mux.HandleFunc("GET /api/v2/topics/{topicID}/messages", h.listTopicMessages)
mux.HandleFunc("POST /api/v2/topics/{topicID}/messages", h.createTopicMessage)
mux.HandleFunc("GET /api/v2/topics/{topicID}/lanes", h.listLanes)
mux.HandleFunc("POST /api/v2/topics/{topicID}/lanes", h.createLane)
mux.HandleFunc("GET /api/v2/lanes/{laneID}", h.getLane)
mux.HandleFunc("PATCH /api/v2/lanes/{laneID}", h.patchLane)
mux.HandleFunc("POST /api/v2/lanes/{laneID}/start", h.startLane)
mux.HandleFunc("POST /api/v2/lanes/{laneID}/stop", h.stopLane)
mux.HandleFunc("GET /api/v2/topics/{topicID}/tasks", h.listTasks)
mux.HandleFunc("POST /api/v2/topics/{topicID}/tasks", h.createTask)
mux.HandleFunc("GET /api/v2/lanes/{laneID}/tasks", h.listLaneTasks)
mux.HandleFunc("GET /api/v2/tasks/{taskID}", h.getTask)
mux.HandleFunc("PATCH /api/v2/tasks/{taskID}", h.patchTask)
mux.HandleFunc("GET /api/v2/tasks/{taskID}/dependencies", h.listTaskDependencies)
mux.HandleFunc("GET /api/v2/tasks/{taskID}/events", h.listTaskEvents)
mux.HandleFunc("POST /api/v2/tasks/{taskID}/events", h.appendTaskEvent)
mux.HandleFunc("GET /api/v2/topics/{topicID}/human-tasks", h.listTopicHumanTasks)
mux.HandleFunc("POST /api/v2/human-tasks/{taskID}/answer", h.answerHumanTask)
mux.HandleFunc("GET /api/v2/topics/{topicID}/workflow-runs", h.listWorkflowRuns)
mux.HandleFunc("POST /api/v2/topics/{topicID}/workflow-runs", h.createWorkflowRun)
mux.HandleFunc("GET /api/v2/workflow-runs/{runID}", h.getWorkflowRun)
mux.HandleFunc("PATCH /api/v2/workflow-runs/{runID}", h.patchWorkflowRun)
mux.HandleFunc("GET /api/v2/workflow-runs/{runID}/logs", h.listWorkflowRunLogs)
mux.HandleFunc("POST /api/v2/workflow-runs/{runID}/logs", h.appendWorkflowRunLog)
mux.HandleFunc("GET /api/v2/system/fs/dirs", h.listDirectories)
mux.HandleFunc("POST /api/v2/system/fs/dirs", h.createDirectory)
mux.HandleFunc("GET /api/v2/dashboard/messages", h.dashboardMessages)
mux.HandleFunc("GET /api/v2/dashboard/topics", h.dashboardTopics)
mux.HandleFunc("GET /api/v2/dashboard/topics/records", h.dashboardTopicRecords)
mux.HandleFunc("GET /api/v2/dashboard/roles", h.dashboardRoles)
mux.HandleFunc("GET /api/v2/dashboard/dispatch", h.dashboardDispatch)
mux.HandleFunc("GET /api/v2/dashboard/dispatch/live", h.dashboardDispatchLive)
mux.HandleFunc("GET /api/v2/dashboard/workflow/board", h.dashboardWorkflowBoard)
mux.HandleFunc("GET /api/v2/dashboard/spaces/{space}/topics", h.dashboardSpaceTopics)
mux.HandleFunc("GET /api/v2/dashboard/spaces/{space}/messages", h.dashboardSpaceMessages)
mux.HandleFunc("POST /api/v2/runtime/lanes/{laneID}/tasks/next", h.runtimeNextTaskExecution)
mux.HandleFunc("POST /api/v2/runtime/task-executions/{runID}/complete", h.runtimeTaskExecutionComplete)
}
func writeStoreError(w http.ResponseWriter, err error) {
switch {
case errors.Is(err, sql.ErrNoRows):
httpx.WriteError(w, http.StatusNotFound, err.Error())
case isValidationError(err):
httpx.WriteError(w, http.StatusBadRequest, err.Error())
default:
httpx.WriteError(w, http.StatusInternalServerError, err.Error())
}
}
func isValidationError(err error) bool {
if err == nil {
return false
}
msg := strings.ToLower(err.Error())
return strings.Contains(msg, "required") || strings.Contains(msg, "invalid")
}