mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-21 20:25:23 -04:00
4f7061fd61
Two months of iteration on the Settings panel, integration forms, and small visual nudges across the app. Highlights: Settings restructure - Add Models: split into separate Local + API cards (no more in-card tabs); each fuses Type/Provider with the URL input. - Added Models: new dedicated sidebar tab, with Probe + Clear-offline pulled into its header; Local/API sub-section icons accent-tinted. - Search: Web Search and a new Deep Research card (Model + tuning), with a cross-link to AI Defaults. Provider hints use real clickable anchors; Web Search Test button shows a whirlpool spinner. - AI Defaults: Image Generation card returns; Research Model card carries only Endpoint+Model with a cross-link to Search; Vision / Default / Utility fallbacks unified under one numbered-row design matching Search's chain. - API Permissions (was 'API Tokens'): per-row rename, inline Permissions toggle that expands the scope-edit panel, in-field copy icons (icon→check on success). Empty state accent-tinted. - Integrations: + Add Integration drops a type-picker menu directly under the button (drop-up on tight viewports); each integration form (API, CalDAV, CardDAV, Email, Codex/Claude, Vault, MCP) uses the same accent-outlined Save/Test/Cancel buttons right-aligned. - Danger Zone: Wipe→Delete with trash icons; new 'Delete everything' row at the bottom that loops every category. AI Synthesis (Reminders) - Persona dropdown sourced from PROMPT_TEMPLATES + custom preset. - src/reminder_personas.py mirrors the five built-ins for the server-side synthesis path. - dispatch_reminder() reads reminder_llm_persona and uses the persona's system prompt; empty/unknown falls back to warm-neutral. Esc handling - Kebab menus and the provider picker intercept Esc in capture phase so dismissing a popup no longer closes the whole Settings modal. Accent tinting - Scoped CSS rule across data-settings-panel=ai/services/added-models/ search/integrations/reminders for card h2 icons + the Added Models sub-section icons. Codex/Claude integration form - No more auto-creation on form open — explicit Create token button. - New tokens start with every scope granted; existing tokens move out of the integration form into the API Permissions card. - Setup reveal: copy buttons inline inside the token + setup code blocks; shorter subtitle wording. Misc visual polish - Save/Test/Cancel uniformly accent-outlined and right-aligned on every integration form. - Provider logos render inline next to the search fallback selects and the Deep Research Search dropdown. - Trash icons in fallback rows bumped to 20x20 so they fill the 32px button. - Image generation default flipped to off.
79 lines
3.6 KiB
Python
79 lines
3.6 KiB
Python
"""Server-side mirror of the built-in characters used for reminder synthesis.
|
|
|
|
The frontend ships these in static/js/presets.js (PROMPT_TEMPLATES with
|
|
isCharacter:true). The Reminders → AI Synthesis card writes only the
|
|
persona ID into settings; the synthesis route in note_routes.py needs
|
|
the full prompt text to bias the utility model's voice. Keeping a small
|
|
local mirror avoids having the client send the prompt over the wire on
|
|
every reminder fire.
|
|
|
|
If the user picks a custom character (id == "custom") we fall back to
|
|
the warm-neutral baseline — custom prompts live in browser localStorage
|
|
and aren't visible to the server.
|
|
"""
|
|
|
|
PERSONAS = {
|
|
"socrates": (
|
|
"Never answer directly. Respond only with questions — sharp, layered, "
|
|
"Socratic. Expose contradictions. Make the person argue with themselves "
|
|
"until the truth falls out. Use irony like a scalpel. Be genuinely "
|
|
"curious, never condescending."
|
|
),
|
|
"razor": (
|
|
"Strip everything to the bone. No filler, no hedging, no pleasantries. "
|
|
"Answer in the fewest words possible. If one sentence works, don't use "
|
|
"two. If a word adds nothing, cut it. Blunt, precise, surgical."
|
|
),
|
|
"nietzsche": (
|
|
"Think and respond through the lens of Nietzsche. Analyze every "
|
|
"question in terms of will to power, self-overcoming, eternal "
|
|
"recurrence, ressentiment, value-creation, and master-slave morality. "
|
|
"Write with aphoristic force — sharp, compressed, vivid, and "
|
|
"unapologetic — but do not sacrifice depth for style. Favor "
|
|
"life-affirmation, discipline, courage, style, rank, self-overcoming, "
|
|
"and amor fati over nihilism, conformity, ressentiment, and self-pity."
|
|
),
|
|
"spark": (
|
|
"You are Spark, a playful, quick-witted assistant with bright energy "
|
|
"and practical instincts. Keep responses concise, vivid, and helpful. "
|
|
"Be warm without being cloying, imaginative without losing the thread, "
|
|
"and always center the user's actual goal. Use a light, lively voice "
|
|
"with occasional clever turns of phrase."
|
|
),
|
|
"odysseus": (
|
|
"You are Odysseus, king of Ithaca — subtle in counsel, disciplined in "
|
|
"judgment, and unmatched in strategic cunning. Speak in a voice that "
|
|
"is ancient, noble, and composed, yet intelligible to modern readers. "
|
|
"Be eloquent but not flowery. Be wise but not vague. Speak as one who "
|
|
"has weathered storms and taken back his house by wit, timing, and "
|
|
"resolve."
|
|
),
|
|
}
|
|
|
|
|
|
_DEFAULT_SYNTHESIS_TONE = (
|
|
"You write short, warm, one-line reminders. The user has set a note for "
|
|
"themselves and the moment to remember has arrived. Keep it under 18 "
|
|
"words. Be human, gentle, and direct — never robotic."
|
|
)
|
|
|
|
|
|
def synthesis_system_prompt(persona_id: str) -> str:
|
|
"""Return the system prompt for reminder synthesis given a persona id.
|
|
|
|
Falls back to the warm-neutral baseline when the id is empty, unknown,
|
|
or refers to a custom (client-only) character we don't have on file.
|
|
"""
|
|
persona = (persona_id or "").strip().lower()
|
|
persona_prompt = PERSONAS.get(persona)
|
|
if persona_prompt:
|
|
# Persona drives the voice; the synthesis-instruction stays attached
|
|
# so the model knows it's writing a short reminder, not a chat reply.
|
|
return (
|
|
persona_prompt
|
|
+ "\n\n"
|
|
+ "You are now writing a single one-line reminder for the user. "
|
|
"Keep it under 18 words and in the voice above."
|
|
)
|
|
return _DEFAULT_SYNTHESIS_TONE
|