feat: last-used persona cookie, emoji dropdown, theme support, auth status move

- cx_last_persona cookie set on serve_ui; root/login/help/settings
  redirects use preferred persona from cookie instead of alphabetically first
- /api/personas returns [{name, emoji}] objects; persona switcher dropdown
  renders emoji + name with flex layout and .pd-emoji span
- Help, Settings, Model Registry pages apply localStorage theme on load
  (no flash); CSS variables for dark/light replacing all hardcoded hex values
- Claude CLI auth status moved from prominent chat banner to Anthropic
  provider block in Model Registry — live dot indicator (ok/warn/err)
- Auth banner removed from main chat UI (index.html, app.js, style.css)
- Add Model collapsed into Models section as <details> to shorten page
- Light-mode overrides for provider icons, model badges, ctx-badge, tags
  (Anthropic/Google/local colors now readable in both themes)
- Help page gains table, pre/code, hr styles for HELP.md rendered content

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-04-28 22:52:34 -04:00
parent 1222f806ce
commit 66cb197de0
9 changed files with 305 additions and 245 deletions

View File

@@ -21,6 +21,9 @@ router = APIRouter()
_STATIC = Path(__file__).parent.parent / "static"
_LAST_PERSONA_COOKIE = "cx_last_persona"
def _get_session_user(request: Request) -> str | None:
token = request.cookies.get(COOKIE_NAME)
if not token:
@@ -31,6 +34,16 @@ def _get_session_user(request: Request) -> str | None:
return None
def _preferred_persona(request: Request, username: str) -> str:
names = list_user_personas(username)
if not names:
return ""
cookie_val = request.cookies.get(_LAST_PERSONA_COOKIE, "")
if cookie_val in names:
return cookie_val
return names[0]
@router.get("/help", include_in_schema=False)
async def help_page(request: Request, persona: str = ""):
username = _get_session_user(request)
@@ -38,11 +51,11 @@ async def help_page(request: Request, persona: str = ""):
return RedirectResponse("/login", status_code=302)
personas = list_user_personas(username)
# Use persona from query param if valid, else fall back to first
# Use persona from query param if valid, else prefer last-visited from cookie
if persona and persona in personas:
back_persona = persona
else:
back_persona = personas[0] if personas else ""
back_persona = _preferred_persona(request, username)
back_href = f"/{username}/{back_persona}" if back_persona else "/"
html = (_STATIC / "help.html").read_text()