Files
voicebox/backend/services/settings.py
T
James PineandClaude Opus 4.7 87c582ad54 feat(capture): dictation, personalities, 0.5.0
Ships the Capture release end to end. Global-hotkey dictation with
synthetic paste into the focused app on macOS and Windows, an on-screen
pill across recording / transcribing / refining, customizable push-to-
talk and toggle chords, and an accessibility-permission prompt scoped to
Settings → Captures with inline re-check feedback.

Voice profiles gain optional personalities that power compose / rewrite /
respond actions via a local Qwen3 LLM — shared with refinement, so there
is one local LLM in the app, not two.

Refinement hardened with deterministic Whisper-loop collapse before the
LLM sees the transcript, per-capture flag snapshots for re-runs, and a
ten-transcript evaluation harness across every bundled refinement size.

Version bump 0.4.5 → 0.5.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-04-22 18:49:16 -07:00

69 lines
2.1 KiB
Python

"""
Server-side user settings — singleton rows persisted in SQLite so every
client window, API consumer, and headless flow reads the same preferences.
Two domains live here: capture/refine defaults and long-form generation
defaults. Each has a ``get_*`` that lazily creates the row with defaults and
an ``update_*`` that accepts a partial payload.
"""
from typing import Any
from sqlalchemy.orm import Session
from ..database import CaptureSettings as DBCaptureSettings
from ..database import GenerationSettings as DBGenerationSettings
SINGLETON_ID = 1
def _get_or_create_capture_row(db: Session) -> DBCaptureSettings:
row = db.query(DBCaptureSettings).filter(DBCaptureSettings.id == SINGLETON_ID).first()
if row is None:
row = DBCaptureSettings(id=SINGLETON_ID)
db.add(row)
db.commit()
db.refresh(row)
return row
def _get_or_create_generation_row(db: Session) -> DBGenerationSettings:
row = db.query(DBGenerationSettings).filter(DBGenerationSettings.id == SINGLETON_ID).first()
if row is None:
row = DBGenerationSettings(id=SINGLETON_ID)
db.add(row)
db.commit()
db.refresh(row)
return row
def get_capture_settings(db: Session) -> DBCaptureSettings:
"""Return the capture settings row, creating it with defaults if missing."""
return _get_or_create_capture_row(db)
def update_capture_settings(db: Session, patch: dict[str, Any]) -> DBCaptureSettings:
row = _get_or_create_capture_row(db)
for key, value in patch.items():
if value is not None and hasattr(row, key):
setattr(row, key, value)
db.commit()
db.refresh(row)
return row
def get_generation_settings(db: Session) -> DBGenerationSettings:
"""Return the generation settings row, creating it with defaults if missing."""
return _get_or_create_generation_row(db)
def update_generation_settings(db: Session, patch: dict[str, Any]) -> DBGenerationSettings:
row = _get_or_create_generation_row(db)
for key, value in patch.items():
if value is not None and hasattr(row, key):
setattr(row, key, value)
db.commit()
db.refresh(row)
return row