feat: add ai gateway local core flow
This commit is contained in:
@@ -54,8 +54,12 @@ func (s *Server) register(w http.ResponseWriter, r *http.Request) {
|
||||
writeError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
if errors.Is(err, store.ErrUserAlreadyExists) {
|
||||
writeError(w, http.StatusConflict, err.Error())
|
||||
return
|
||||
}
|
||||
s.logger.Error("register local user failed", "error", err)
|
||||
writeError(w, http.StatusConflict, "user already exists or tenant is unavailable")
|
||||
writeError(w, http.StatusInternalServerError, "register local user failed")
|
||||
return
|
||||
}
|
||||
s.writeAuthResponse(w, http.StatusCreated, user)
|
||||
@@ -230,6 +234,56 @@ func (s *Server) listUserGroups(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, map[string]any{"items": items})
|
||||
}
|
||||
|
||||
func (s *Server) listAPIKeys(w http.ResponseWriter, r *http.Request) {
|
||||
user, _ := auth.UserFromContext(r.Context())
|
||||
items, err := s.store.ListAPIKeys(r.Context(), user)
|
||||
if err != nil {
|
||||
s.logger.Error("list api keys failed", "error", err)
|
||||
writeError(w, http.StatusInternalServerError, "list api keys failed")
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{"items": items})
|
||||
}
|
||||
|
||||
func (s *Server) createAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
user, _ := auth.UserFromContext(r.Context())
|
||||
var input store.CreateAPIKeyInput
|
||||
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
|
||||
writeError(w, http.StatusBadRequest, "invalid json body")
|
||||
return
|
||||
}
|
||||
created, err := s.store.CreateAPIKey(r.Context(), input, user)
|
||||
if err != nil {
|
||||
if errors.Is(err, store.ErrLocalUserRequired) {
|
||||
writeError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
s.logger.Error("create api key failed", "error", err)
|
||||
writeError(w, http.StatusInternalServerError, "create api key failed")
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusCreated, created)
|
||||
}
|
||||
|
||||
func (s *Server) disableAPIKey(w http.ResponseWriter, r *http.Request) {
|
||||
user, _ := auth.UserFromContext(r.Context())
|
||||
item, err := s.store.DisableAPIKey(r.Context(), r.PathValue("apiKeyID"), user)
|
||||
if err == nil {
|
||||
writeJSON(w, http.StatusOK, item)
|
||||
return
|
||||
}
|
||||
if errors.Is(err, store.ErrLocalUserRequired) {
|
||||
writeError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
if store.IsNotFound(err) {
|
||||
writeError(w, http.StatusNotFound, "api key not found")
|
||||
return
|
||||
}
|
||||
s.logger.Error("disable api key failed", "error", err)
|
||||
writeError(w, http.StatusInternalServerError, "disable api key failed")
|
||||
}
|
||||
|
||||
func (s *Server) estimatePricing(w http.ResponseWriter, r *http.Request) {
|
||||
var body map[string]any
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
@@ -275,6 +329,7 @@ func (s *Server) createTask(kind string) http.Handler {
|
||||
task, err := s.store.CreateTask(r.Context(), store.CreateTaskInput{
|
||||
Kind: kind,
|
||||
Model: model,
|
||||
RunMode: runModeFromRequest(body),
|
||||
Request: body,
|
||||
}, user)
|
||||
if err != nil {
|
||||
@@ -322,24 +377,37 @@ func (s *Server) taskEvents(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Cache-Control", "no-cache")
|
||||
w.Header().Set("Connection", "keep-alive")
|
||||
|
||||
sendSSE(w, "task.accepted", map[string]any{
|
||||
"taskId": task.ID,
|
||||
"status": task.Status,
|
||||
})
|
||||
if flusher, ok := w.(http.Flusher); ok {
|
||||
flusher.Flush()
|
||||
}
|
||||
|
||||
timer := time.NewTimer(250 * time.Millisecond)
|
||||
defer timer.Stop()
|
||||
|
||||
select {
|
||||
case <-r.Context().Done():
|
||||
events, err := s.store.ListTaskEvents(r.Context(), task.ID)
|
||||
if err != nil {
|
||||
s.logger.Error("list task events failed", "error", err)
|
||||
return
|
||||
case <-timer.C:
|
||||
sendSSE(w, "task.placeholder", map[string]any{
|
||||
"taskId": task.ID,
|
||||
"message": "runtime worker is not wired yet",
|
||||
}
|
||||
for _, event := range events {
|
||||
sendSSE(w, event.EventType, event)
|
||||
if flusher, ok := w.(http.Flusher); ok {
|
||||
flusher.Flush()
|
||||
}
|
||||
}
|
||||
if len(events) == 0 {
|
||||
sendSSE(w, "task.accepted", map[string]any{
|
||||
"taskId": task.ID,
|
||||
"status": task.Status,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func runModeFromRequest(body map[string]any) string {
|
||||
if value, ok := body["runMode"].(string); ok {
|
||||
return value
|
||||
}
|
||||
if value, ok := body["mode"].(string); ok {
|
||||
return value
|
||||
}
|
||||
if value, ok := body["simulation"].(bool); ok && value {
|
||||
return "simulation"
|
||||
}
|
||||
if value, ok := body["testMode"].(bool); ok && value {
|
||||
return "simulation"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user