Skip to content

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 writes config.json atomically. Raises SettingsValidationError on 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() merges platform.BROWSER_APPS with any extra keys that appear in browser_auth.json so 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).