puck / frontend /src /lib /settings.ts
vu1n's picture
Puck β€” desktop fairy familiar (HF Build Small)
3c124f3
Raw
History Blame Contribute Delete
2.78 kB
import type { BubbleStyle, SpriteForm } from "../ui/Sprite";
import { DEFAULT_KOKORO_VOICE, type VoiceEngine, type VoiceMode } from "./voice";
export type Theme = "terrarium" | "candlelight" | "nocturne";
export type NotifyStyle = "adaptive" | "bubble" | "toast" | "interrupt";
// off: never. ondemand: only the "Look around" button. ambient: auto, on a slow
// timer, paused when idle/hidden so the cloud GPU scales to zero (cost-safe).
export type VisionMode = "off" | "ondemand" | "ambient";
/** Ambient capture interval. Doesn't change cloud cost much (GPU stays warm
* while active regardless) β€” idle-off is the real saving β€” but a slower cadence
* is gentler and plenty for a screen that changes on human timescales. */
export const AMBIENT_INTERVAL_MS = 45_000;
export interface Settings {
theme: Theme;
accent: string;
form: SpriteForm;
/** 0..100 β€” how often Puck wanders and how dense events are. */
presence: number;
mischief: number;
/** Comment typography: fairy serif, plain UI, or handwriting. */
voice: BubbleStyle;
voiceSound: VoiceMode;
/** Which TTS engine: local neural (Kokoro) or the OS voices. */
voiceEngine: VoiceEngine;
/** Chosen OS (speechSynthesis) voice name; "" = auto-pick a soft english voice. */
voiceName: string;
/** Chosen Kokoro voice id (e.g. "af_heart", "am_puck"). */
kokoroVoice: string;
/** Chosen macOS `say` voice name (e.g. "Samantha"); "" = system default. */
sayVoice: string;
/** Speak the short reaction shouts ("NANI?!", "shipped!") aloud too. */
speakShouts: boolean;
notify: NotifyStyle;
/** Mirror surfaced comments to OS notifications when the tab is hidden. */
osNotify: boolean;
/** How Puck uses his eyes (vision). Default on-demand: nothing runs unattended. */
visionMode: VisionMode;
}
export const ACCENTS = ["#e7b85c", "#8fcf86", "#e58fa6", "#b89be6", "#6fc6d6"] as const;
export const defaultSettings = (): Settings => ({
theme: "terrarium",
accent: "#e7b85c",
form: "mossling",
presence: 62,
mischief: 45,
voice: "voice",
voiceSound: "full", // audible by default (browser autoplay may need one click first)
voiceEngine: "say", // Mac-native voice β€” works in the overlay and the browser demo alike
voiceName: "",
kokoroVoice: DEFAULT_KOKORO_VOICE,
sayVoice: "Samantha",
speakShouts: true,
notify: "adaptive",
osNotify: false,
visionMode: "ondemand",
});
/** Readable ink color for text on top of the accent. */
export function inkFor(hex: string): string {
const h = hex.replace("#", "");
const n = parseInt(h.length === 3 ? h.replace(/./g, (c) => c + c) : h, 16);
const r = (n >> 16) & 255;
const g = (n >> 8) & 255;
const b = n & 255;
return r * 299 + g * 587 + b * 114 > 150000 ? "#22180a" : "#fff7e8";
}