Merge remote-tracking branch 'origin/master' into paperclip/pr-6222

This commit is contained in:
Frank Song committed 2026-07-19 01:42:49 +08:00
commit 1929cbd54d
3 files changed
+38 -1

No files matched your search

+2
View File
@@ -9,6 +9,8 @@
### Fixed
- **OIDC allowlist values containing spaces (e.g. a group named `Hermes Users`) are no longer split into separate entries.** The allowlist parser split comma-separated values on all whitespace, so a multi-word group/user name became two spurious entries. Allowlist parsing now splits only on commas/newlines (multi-word values stay intact and match their exact signed claim — strictly tightening, no security loosening), while OAuth **scope** parsing keeps its space-delimited behavior per RFC 6749 §3.3. A blank allowlist entry no longer bricks an OIDC-only deployment. Thanks @webtecnica. (#6244)
- **`/sessions` and `/resume` typed in the composer now open the session browser instead of being sent as chat text.** Both commands appeared in the slash-command autocomplete (they're exposed by `/api/commands`) but the WebUI send-time dispatch didn't handle them, so they were posted to the agent as plain text. They now open the native WebUI session browser and clear the composer — on desktop and (via the mobile-aware opener) on phone-width layouts. Thanks @webtecnica. (#6245, #6224)
- **Z.AI GLM models now advertise the correct reasoning controls per version.** The WebUI offered the full `reasoning_effort` ladder (max/xhigh/high/medium/low/minimal) for every GLM model, but per Z.AI's API only GLM-5.2+ supports the effort ladder — GLM-4.5 through 5.1 support the binary `thinking` on/off toggle, and GLM-4.7 forces thinking on (not configurable). Reasoning controls are now gated correctly: GLM-5.2+ keeps the full ladder + None, GLM-4.5/4.6/5.0/5.1 get a two-way On/None thinking toggle (no effort levels), and GLM-4.7 shows forced thinking with no toggle. All three surfaces (config status, effort resolution, composer chip) agree across model tiers, provider aliases, and namespaces. Thanks @rh-id. (#6219)
+16 -1
View File
@@ -207,7 +207,22 @@ def _normalize_scopes(raw: Any) -> list[str]:
def _normalize_allow_values(raw: Any) -> list[str]:
return _normalize_text_list(raw)
"""Normalize allowlist values, splitting only on commas/newlines.
Unlike ``_normalize_text_list`` (which also splits on whitespace), this
preserves multi-word values such as OIDC group names containing spaces
(e.g. ``"Hermes Users"`` stays as one entry).
RFC 6749 §3.3 requires space-delimited scope strings, so
``_normalize_scopes`` must keep using ``_normalize_text_list`` -- this
function is for allow-values only.
"""
if raw is None:
return []
if isinstance(raw, (list, tuple, set)):
return [value for value in (str(item).strip() for item in raw) if value]
text = str(raw).replace("\n", ",")
return [part.strip() for part in text.split(",") if part.strip()]
def _normalize_text_list(raw: Any) -> list[str]:
+20
View File
@@ -547,3 +547,23 @@ def test_coerce_numeric_claim_rejects_non_finite_values(value):
with pytest.raises(OIDCAuthError, match="claim exp was not numeric"):
auth_oidc._coerce_numeric_claim({"exp": value}, "exp")
def test_normalize_allow_values_and_scopes_use_separate_delimiters():
"""#6244: allowlist values are comma/newline-delimited (multi-word group names
like "Hermes Users" stay intact), while OAuth scopes stay space-delimited
(RFC 6749 §3.3). The two parsers must NOT share whitespace-splitting."""
from api import auth_oidc
# Allowlist: multi-word group name stays ONE entry; commas/newlines split.
assert auth_oidc._normalize_allow_values("Hermes Users") == ["Hermes Users"]
assert auth_oidc._normalize_allow_values("Hermes Users, Admins") == ["Hermes Users", "Admins"]
assert auth_oidc._normalize_allow_values("a\nb") == ["a", "b"]
# Blank collection elements are filtered (a bare [""] must not brick OIDC login).
assert auth_oidc._normalize_allow_values([""]) == []
assert auth_oidc._normalize_allow_values(["Hermes Users", "", " "]) == ["Hermes Users"]
# Scopes: space-delimited per RFC 6749 §3.3 — whitespace splitting is retained.
assert auth_oidc._normalize_text_list("openid profile email") == ["openid", "profile", "email"]
scopes = auth_oidc._normalize_scopes("openid profile email")
assert scopes[:3] == ["openid", "profile", "email"]