From 5b6342e6acd7399001e403b4dd88b9647094d035 Mon Sep 17 00:00:00 2001 From: RGBadmin Date: Sat, 14 Mar 2026 14:47:31 +0800 Subject: [PATCH] feat(api): expose priority and note fields in GET /auth-files list response The list endpoint previously omitted priority and note, which are stored inside each auth file's JSON content. This adds them to both the normal (auth-manager) and fallback (disk-read) code paths, and extends PATCH /auth-files/fields to support writing the note field. Co-Authored-By: Claude Opus 4.6 --- .../api/handlers/management/auth_files.go | 33 ++++++++++++++++++- internal/watcher/synthesizer/file.go | 8 +++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/internal/api/handlers/management/auth_files.go b/internal/api/handlers/management/auth_files.go index 2e471ae8..7b695f2c 100644 --- a/internal/api/handlers/management/auth_files.go +++ b/internal/api/handlers/management/auth_files.go @@ -332,6 +332,12 @@ func (h *Handler) listAuthFilesFromDisk(c *gin.Context) { emailValue := gjson.GetBytes(data, "email").String() fileData["type"] = typeValue fileData["email"] = emailValue + if pv := gjson.GetBytes(data, "priority"); pv.Exists() { + fileData["priority"] = int(pv.Int()) + } + if nv := gjson.GetBytes(data, "note"); nv.Exists() && strings.TrimSpace(nv.String()) != "" { + fileData["note"] = strings.TrimSpace(nv.String()) + } } files = append(files, fileData) @@ -415,6 +421,18 @@ func (h *Handler) buildAuthFileEntry(auth *coreauth.Auth) gin.H { if claims := extractCodexIDTokenClaims(auth); claims != nil { entry["id_token"] = claims } + // Expose priority from Attributes (set by synthesizer from JSON "priority" field). + if p := strings.TrimSpace(authAttribute(auth, "priority")); p != "" { + if parsed, err := strconv.Atoi(p); err == nil { + entry["priority"] = parsed + } + } + // Expose note from Metadata. + if note, ok := auth.Metadata["note"].(string); ok { + if trimmed := strings.TrimSpace(note); trimmed != "" { + entry["note"] = trimmed + } + } return entry } @@ -839,7 +857,7 @@ func (h *Handler) PatchAuthFileStatus(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"status": "ok", "disabled": *req.Disabled}) } -// PatchAuthFileFields updates editable fields (prefix, proxy_url, priority) of an auth file. +// PatchAuthFileFields updates editable fields (prefix, proxy_url, priority, note) of an auth file. func (h *Handler) PatchAuthFileFields(c *gin.Context) { if h.authManager == nil { c.JSON(http.StatusServiceUnavailable, gin.H{"error": "core auth manager unavailable"}) @@ -851,6 +869,7 @@ func (h *Handler) PatchAuthFileFields(c *gin.Context) { Prefix *string `json:"prefix"` ProxyURL *string `json:"proxy_url"` Priority *int `json:"priority"` + Note *string `json:"note"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"}) @@ -904,6 +923,18 @@ func (h *Handler) PatchAuthFileFields(c *gin.Context) { } changed = true } + if req.Note != nil { + if targetAuth.Metadata == nil { + targetAuth.Metadata = make(map[string]any) + } + trimmedNote := strings.TrimSpace(*req.Note) + if trimmedNote == "" { + delete(targetAuth.Metadata, "note") + } else { + targetAuth.Metadata["note"] = trimmedNote + } + changed = true + } if !changed { c.JSON(http.StatusBadRequest, gin.H{"error": "no fields to update"}) diff --git a/internal/watcher/synthesizer/file.go b/internal/watcher/synthesizer/file.go index ab54aeaa..b063b45f 100644 --- a/internal/watcher/synthesizer/file.go +++ b/internal/watcher/synthesizer/file.go @@ -149,6 +149,14 @@ func synthesizeFileAuths(ctx *SynthesisContext, fullPath string, data []byte) [] } } } + // Read note from auth file. + if rawNote, ok := metadata["note"]; ok { + if note, isStr := rawNote.(string); isStr { + if trimmed := strings.TrimSpace(note); trimmed != "" { + a.Attributes["note"] = trimmed + } + } + } ApplyAuthExcludedModelsMeta(a, cfg, perAccountExcluded, "oauth") // For codex auth files, extract plan_type from the JWT id_token. if provider == "codex" {