cue.settings_model¶
Pure-logic layer for the Preferences window.
Separated from settings_window.py so the whole validate / draft / commit
cycle is testable with stdlib + pytest (no customtkinter, no subprocess).
Contract:
load_draft()→ fresh dict that mirrors what's currently persisted, merged with defaults so UI widgets always have a value to bind to.validate_*helpers return(ok: bool, error_msg: str).diff(draft, snapshot)reports whether anything changed vs the snapshot the UI took at window-open time.commit(draft)validates everything, then writesconfig.jsonatomically. RaisesSettingsValidationErroron any failure — the window disables Apply while errors exist, so commit() SHOULD succeed by the time it's called, but we still validate as defense-in-depth.supported_browsers()mergesplatform.BROWSER_APPSwith any extra keys that appear inbrowser_auth.jsonso user-added entries survive a reload.
The module never mutates module state and never calls platform APIs;
all I/O goes through cue.config + cue.fs.
SettingsValidationError ¶
Bases: ValueError
Raised from commit() when the draft fails validation.
validate_api_key ¶
validate_api_key(key: str) -> tuple[bool, str]
Mirrors cue.config._validate_key but returns a tuple instead of
raising. Empty string is treated as "keep previous" by the view; only
non-empty values are validated.
load_draft ¶
load_draft() -> dict
Read the current config.json merged with defaults. The UI seeds
each widget from this; its own mutations only touch the returned dict
copy, never the on-disk file, until commit().
Returned structure (stable contract for the view):
{
"api_key": str | "", # mask from widget; empty means leave as-is
"context_frames": bool,
"streaming": { "enabled": bool, ... },
"privacy": { full _PRIVACY_DEFAULTS merged with user overrides },
"browser_auth": { app_lower: state }, # snapshot at open time
}
diff ¶
diff(draft: dict, snapshot: dict) -> dict[str, Any]
Return a minimal change-set {dotted_path: new_value}. Used by
the Apply button's enabled state and by tests.
commit ¶
commit(draft: dict) -> dict
Validate the whole draft and write config.json + any browser_auth
mutations. Returns the new snapshot (same shape as load_draft()) so
the UI can re-baseline its compare.
supported_browsers ¶
supported_browsers() -> list[str]
All browsers we know how to probe, plus any extras the user might
have added to browser_auth.json manually. Lowercase app-name keys
(matching the BrowserAuth internal representation).