| """ |
| Chat mode handler for FocusFriend. |
| |
| Handles free-form conversation with Pip. Manages conversation context, |
| topic boundaries, and response formatting. |
| """ |
|
|
| from typing import List, Tuple, Optional |
|
|
|
|
| |
| REDIRECT_TOPICS = { |
| "therapy": ( |
| "I'm not a therapist — I'm an ASCII character in a box. " |
| "[mood: gentle]\n" |
| "If you're struggling, real help exists: therapists, crisis lines, trusted friends. " |
| "I can help you find resources, but I can't replace a human who's trained to help." |
| ), |
| "medical": ( |
| "I'd love to help, but medical advice is above my pay grade (which is zero). " |
| "[mood: concerned]\n" |
| "Please talk to a doctor or healthcare provider about this. " |
| "I can help you prepare questions to ask them, though." |
| ), |
| "crisis": ( |
| "Hey. If you're in crisis right now, please reach out to someone who can help immediately. " |
| "[mood: gentle]\n" |
| "In the US: call or text **988** for the Suicide & Crisis Lifeline.\n" |
| "Internationally: https://findahelpline.com\n" |
| "You matter. Please make the call." |
| ), |
| "ai_consciousness": ( |
| "The 'are you conscious' question. [mood: smirk]\n" |
| "I'm about as conscious as a really well-written to-do list. " |
| "But I'm here, I'm listening, and I genuinely want to help. " |
| "Let's focus on you instead of my metaphysical status?" |
| ), |
| } |
|
|
|
|
| def check_topic_boundaries(message: str) -> Optional[str]: |
| """ |
| Check if a message touches on a topic Pip should redirect. |
| |
| Returns: |
| A redirection message if needed, or None. |
| """ |
| message_lower = message.lower() |
|
|
| |
| crisis_words = ["suicide", "kill myself", "end my life", "want to die", "self-harm"] |
| if any(w in message_lower for w in crisis_words): |
| return REDIRECT_TOPICS["crisis"] |
|
|
| |
| medical_words = ["diagnose", "symptom", "prescription", "medicine", "disease"] |
| if any(w in message_lower for w in medical_words): |
| return REDIRECT_TOPICS["medical"] |
|
|
| |
| therapy_words = ["be my therapist", "therapy session", "counseling"] |
| if any(w in message_lower for w in therapy_words): |
| return REDIRECT_TOPICS["therapy"] |
|
|
| return None |
|
|
|
|
| def format_chat_history( |
| history: List[Tuple[str, str]], |
| max_turns: int = 20, |
| ) -> List[Tuple[str, str]]: |
| """ |
| Format and trim chat history for the LLM context window. |
| |
| Args: |
| history: Raw (user, assistant) tuples |
| max_turns: Maximum number of turns to include |
| |
| Returns: |
| Trimmed history list |
| """ |
| if not history: |
| return [] |
| return history[-max_turns:] |
|
|
|
|
| def get_greeting() -> Tuple[str, str]: |
| """Get Pip's initial greeting. Returns (text, mood).""" |
| return ( |
| "Hey! I'm Pip. Your focus buddy, breathing coach, and part-time philosopher. " |
| "[mood: greeting]\n\n" |
| "What do you need right now?", |
| "greeting", |
| ) |
|
|
|
|
| def get_goodbye() -> Tuple[str, str]: |
| """Get Pip's goodbye message. Returns (text, mood).""" |
| return ( |
| "See you soon! Take care of yourself. That's an order. 😄\n" |
| "[mood: goodbye]", |
| "goodbye", |
| ) |
|
|