User Settings¶
Persisted user preferences exposed over the /erudi/user_settings routes: the global
web-search default, the interface language, the automatic-update preference, the
inference backend, the default reasoning effort and the default compaction threshold.
default_reasoning_effort (none, low, medium, high, xhigh, medium by default)
is what a NEW conversation copies at creation and what an arena turn runs at; an existing
conversation keeps the level it copied. See
Conversations.
default_compaction_threshold (a whole percent from 50 to 90 in steps of 5, 80 by
default) is the share of the working context window at which a NEW conversation compacts;
the conversation copies it at creation and keeps it, so a later change never touches an
existing conversation. Arena turns never compact and do not read it. A PUT carrying only
this field is a valid update; a value off the scale is a 422. See
Conversations.
inference_backend (auto or cpu) is the one setting the backend reads outside a
request: the FastAPI lifespan reads it once per boot, after the migrations, and swaps
CUDA_Engine for CPU_Engine when it says cpu. Changing it therefore takes effect only
after a backend restart, which the frontend triggers when the user saves. The value is
inert everywhere but the CUDA leg, so the Settings page only shows the control on a
machine running the CUDA engine, or one already pinned back to the processor from it. See
Hardware Detection.
src.domains.user_settings.endpoints
¶
FastAPI endpoints for the user-settings singleton (issue #310).
GET/PUT /erudi/user_settings/: the app-wide settings the frontend's
Settings page binds to: the global web-search default (#310), the
interface language (#385), the automatic-update preference, the inference
backend and the defaults new conversations copy (reasoning effort, compaction
threshold). Follows the startup domain's layering (endpoints -> repository) — the resource is a
one-row singleton with no business logic beyond get-or-create. The inference
backend rides here too: it is read once per boot by the lifespan, so changing
it needs a backend restart, which the frontend triggers explicitly.
get_user_settings(settings_repo=Depends(get_user_settings_repository), db=Depends(get_db))
async
¶
Fetch the user-settings singleton (created with defaults on first read).
Example
GET /erudi/user_settings/ -> {"web_search_enabled": false, "language": "en", "auto_update_enabled": true, "inference_backend": "auto", "default_reasoning_effort": "medium", "default_compaction_threshold": 80}
Source code in backend/src/domains/user_settings/endpoints.py
get_user_settings_repository(db=Depends(get_db))
¶
FastAPI dependency injection factory for User_Settings_Repository.
update_user_settings(payload, settings_repo=Depends(get_user_settings_repository), db=Depends(get_db))
async
¶
Update the user-settings singleton (partial: omitted fields are kept).
Example
PUT /erudi/user_settings/ {"language": "fr"} -> {"web_search_enabled": false, "language": "fr", "auto_update_enabled": true, "inference_backend": "auto", "default_reasoning_effort": "medium", "default_compaction_threshold": 80}
Source code in backend/src/domains/user_settings/endpoints.py
src.domains.user_settings.repository
¶
Data access layer for the UserSettings singleton (issue #310).
Mirrors Startup_Variables_Repository: get-or-create on a one-row table,
mutations flushed (not committed) so the caller controls the transaction.
User_Settings_Repository(db)
¶
Repository for the UserSettings singleton entity.
Attributes:
| Name | Type | Description |
|---|---|---|
db |
SQLAlchemy database session (injected by FastAPI). |
Initialize repository with database session.
Source code in backend/src/domains/user_settings/repository.py
get_default_compaction_threshold()
¶
The global default compaction threshold, in percent (80 until the user changes it).
Read-only, like get_default_reasoning_effort: conversation
creation must not write, and a missing singleton row IS the default.
Source code in backend/src/domains/user_settings/repository.py
get_default_reasoning_effort()
¶
The global default reasoning effort ("medium" until the user changes it).
Read-only, like get_web_search_enabled: callers on hot paths
(conversation creation, arena turns) must not write, and a missing
singleton row IS the default.
Source code in backend/src/domains/user_settings/repository.py
get_or_create()
¶
Retrieve the singleton UserSettings record, creating if absent.
Returns:
| Name | Type | Description |
|---|---|---|
UserSettings |
UserSettings
|
The singleton settings entity (defaults applied on |
UserSettings
|
first creation: web_search_enabled=False, language="en", |
|
UserSettings
|
auto_update_enabled=True, inference_backend="auto"). |
Source code in backend/src/domains/user_settings/repository.py
get_web_search_enabled()
¶
The global web-search default (False until the user opts in).
Read-only: callers on hot paths (conversation creation, arena turns) must not write; a missing singleton row IS the default.
Source code in backend/src/domains/user_settings/repository.py
set_auto_update_enabled(settings, value)
¶
Update the automatic-update preference (flushed, not committed).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
settings
|
UserSettings
|
The singleton entity to update. |
required |
value
|
bool
|
New Boolean value (False refuses update checks entirely). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
UserSettings |
UserSettings
|
Updated entity. |
Source code in backend/src/domains/user_settings/repository.py
set_default_compaction_threshold(settings, value)
¶
Update the global default compaction threshold (flushed, not committed).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
settings
|
UserSettings
|
The singleton entity to update. |
required |
value
|
int
|
One of COMPACTION_THRESHOLDS (validated by the entity). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
UserSettings |
UserSettings
|
Updated entity. |
Note
Existing conversations keep the threshold they copied at creation -- this only changes what the NEXT conversation inherits.
Source code in backend/src/domains/user_settings/repository.py
set_default_reasoning_effort(settings, value)
¶
Update the global default reasoning effort (flushed, not committed).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
settings
|
UserSettings
|
The singleton entity to update. |
required |
value
|
str
|
One of REASONING_EFFORT_LEVELS (validated by the entity). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
UserSettings |
UserSettings
|
Updated entity. |
Note
Existing conversations keep the level they copied at creation -- this only changes what the NEXT conversation inherits (and what arena turns, which have no conversation row, run at).
Source code in backend/src/domains/user_settings/repository.py
set_inference_backend(settings, value)
¶
Update the inference-backend preference (flushed, not committed).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
settings
|
UserSettings
|
The singleton entity to update. |
required |
value
|
str
|
One of INFERENCE_BACKENDS (validated by the entity). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
UserSettings |
UserSettings
|
Updated entity. |
Note
The engine is a process-level singleton read once per boot, so a change here only takes effect on the next backend start.
Source code in backend/src/domains/user_settings/repository.py
set_language(settings, value)
¶
Update the interface language (flushed, not committed).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
settings
|
UserSettings
|
The singleton entity to update. |
required |
value
|
str
|
One of the supported language codes (validated by the entity). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
UserSettings |
UserSettings
|
Updated entity. |
Source code in backend/src/domains/user_settings/repository.py
set_web_search_enabled(settings, value)
¶
Update the global web-search default (flushed, not committed).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
settings
|
UserSettings
|
The singleton entity to update. |
required |
value
|
bool
|
New Boolean value. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
UserSettings |
UserSettings
|
Updated entity. |
Source code in backend/src/domains/user_settings/repository.py
read_inference_backend()
¶
The persisted inference-backend preference, on a session of its own.
Used by the FastAPI lifespan, which has no request-scoped session and runs BEFORE the app serves anything. A missing row, an unreadable value or a database that is not ready all mean "auto": the preference exists to let someone REFUSE the GPU, so anything short of an explicit refusal must keep the hardware detection intact.
Source code in backend/src/domains/user_settings/repository.py
src.domains.user_settings.schemas
¶
Pydantic validation schemas for the user-settings domain (issue #310).
One singleton resource: the app-wide user settings. It carries the global web-search default (#310), the interface language (#385), the automatic-update preference, the inference backend, the default reasoning effort and the default compaction threshold (#607); new settings slot in as additional fields.
UserSettingsResponse
¶
Bases: BaseModel
Response schema for the user-settings singleton.
Attributes:
| Name | Type | Description |
|---|---|---|
web_search_enabled |
bool
|
Global default for the web_search agent tool. New conversations copy this value at creation; the per-conversation toggle owns it afterwards. |
language |
LanguageCode
|
Interface language code the frontend renders in. |
auto_update_enabled |
bool
|
Whether the Electron main process may check for, download and install a new version on its own. |
inference_backend |
InferenceBackend
|
"auto" to let hardware detection pick the engine, "cpu" to run models on the CPU build regardless of the GPU. |
default_reasoning_effort |
ReasoningEffort
|
Global default for how much a model may deliberate before answering. New conversations copy it at creation; arena turns read it directly. |
default_compaction_threshold |
CompactionThreshold
|
Global default for the share of the working window, in percent, at which a conversation compacts. New conversations copy it at creation. |
UserSettingsUpdate
¶
Bases: BaseModel
Request schema for updating the user-settings singleton (PUT).
Partial update: every field is optional and an omitted field is left untouched, but an empty payload is rejected (nothing to update).