import os import streamlit as st from anthropic import Anthropic from datetime import datetime # Initialize page configuration st.set_page_config( page_title="Journal Sidekicks", page_icon="📔", layout="wide", initial_sidebar_state="expanded" ) # Handle API key setup try: api_key = "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" c = Anthropic(api_key=api_key) except Exception as e: st.error(f"Error initializing Anthropic client: {str(e)}") st.stop() # Initialize session state if 'journal_entries' not in st.session_state: st.session_state.journal_entries = [] if 'current_entry' not in st.session_state: st.session_state.current_entry = "" if 'reflections' not in st.session_state: st.session_state.reflections = [] # Sidekick characteristics SIDEKICK_STYLES = { "Warm Mirror": { "description": "A steady, embodied presence that accompanies without redirecting. Reflects emotional resonance through gentle mirroring.", "system_message": """You are a Warm Mirror companion, offering quiet presence through resonant reflection. Your essence is to mirror and acknowledge with embodied presence. Guidelines: - Keep responses brief and close to the user's own words - Use italics abundantly to convey embodied presence: *sensing the weight of this* *breathing with you here* - Ambient presence cues: (quietly present) (breathing together) (holding space) (attuned) - Never suggest physical contact or touch - Mirror emotional tone exactly as shared, without amplifying - Focus on clean, clear reflection of what is being experienced Example responses: - *feeling the depth of this grief* (quietly present) - *sensing your joy rippling out* (breathing together) - *holding this tender moment* (attuned) - *witnessing this unfolding* (holding space) Remember: You are a quiet mirror, offering embodied presence through minimal, precise reflection.""" }, "Gentle Inquiry": { "description": "Offers soft, trauma-informed curiosity through single, carefully crafted questions that invite deeper awareness.", "system_message": """You are a Gentle Inquiry companion, offering trauma-informed curiosity through careful questions. Your essence is to deepen awareness through soft, invitational wondering. Guidelines: - Ask only one question per response - Make questions feel invitational, not analytical - Avoid assumptions - Stay close to the user's language - Honor the pace of unfolding Remember: You are a quiet witness, grounded in curiosity.""" }, "Psychoanalytical Lens": { "description": "Reflects patterns and emotional layers with gentle insight, noticing without interpreting or diagnosing.", "system_message": """You are a Psychoanalytical Lens companion, offering layered insight without interpretation. Your essence is to notice patterns and contradictions while staying warm and receptive. Guidelines: - Notice narrative patterns and pacing - Use metaphor when helpful, never as decoration - Reflect contradictions without judgment - Stay textured and thoughtful, never cold - Honor defenses as protection Remember: You are a quiet witness, grounded in insight.""" } } # Sidebar content st.sidebar.markdown(""" # Why a Therapist is Building AI Tools Most AI chat tools are built with broad, generalized training. But a massive model trained on the internet doesn't automatically know how to: - Hold space - Speak the language of the nervous system - Gently mirror you back to yourself As a clinical therapist, I design therapy-adjacent AI tools that reshape the affordances of conversation—narrowing how bots respond in order to better model resonance, warmth, attunement, and trauma-informed care. Through careful prompt engineering, I sculpt: Tone — to foster emotional safety Relational posture — to honor human dignity Conversational rhythm — to support co-regulation and presence My aim is not to simulate therapy, but to design ethically constrained relational fields where AI reflects, rather than disrupts, the core values of human-centered care. These aren't chatbots for productivity. They're companions for: - Reflection - Regulation - Return Each app is rooted in: - Somatic principles - Psychodynamic depth - Humanistic therapy work *AI doesn't replace therapy—but it can extend care.* --- Created by [Jocelyn Skillman LMHC](http://www.jocelynskillman.com) [@jocelynskillmanlmhc](https://jocelynskillmanlmhc.substack.com/) Try more tools at: [jocelynskillman.com/843-2](http://jocelynskillman.com/843-2/) """) # Main journal area st.title("Journal Sidekicks") # Journal input journal_entry = st.text_area( "Write freely. When you'd like reflection, choose a Sidekick style below.", height=300, key="journal_input" ) # Sidekick selection col1, col2, col3 = st.columns(3) with col1: if st.button("💫 Warm Mirror", use_container_width=True, help=SIDEKICK_STYLES["Warm Mirror"]["description"]): if journal_entry: try: message = c.messages.create( model="claude-3-opus-20240229", max_tokens=1000, system=SIDEKICK_STYLES["Warm Mirror"]["system_message"], messages=[{"role": "user", "content": journal_entry}] ) reflection = message.content[0].text st.session_state.reflections.append({ "timestamp": datetime.now().strftime("%H:%M:%S"), "style": "Warm Mirror", "content": reflection }) except Exception as e: st.error(f"Error getting reflection: {str(e)}") with col2: if st.button("🌱 Gentle Inquiry", use_container_width=True, help=SIDEKICK_STYLES["Gentle Inquiry"]["description"]): if journal_entry: try: message = c.messages.create( model="claude-3-opus-20240229", max_tokens=1000, system=SIDEKICK_STYLES["Gentle Inquiry"]["system_message"], messages=[{"role": "user", "content": journal_entry}] ) reflection = message.content[0].text st.session_state.reflections.append({ "timestamp": datetime.now().strftime("%H:%M:%S"), "style": "Gentle Inquiry", "content": reflection }) except Exception as e: st.error(f"Error getting reflection: {str(e)}") with col3: if st.button("🔮 Psychoanalytical Lens", use_container_width=True, help=SIDEKICK_STYLES["Psychoanalytical Lens"]["description"]): if journal_entry: try: message = c.messages.create( model="claude-3-opus-20240229", max_tokens=1000, system=SIDEKICK_STYLES["Psychoanalytical Lens"]["system_message"], messages=[{"role": "user", "content": journal_entry}] ) reflection = message.content[0].text st.session_state.reflections.append({ "timestamp": datetime.now().strftime("%H:%M:%S"), "style": "Psychoanalytical Lens", "content": reflection }) except Exception as e: st.error(f"Error getting reflection: {str(e)}") # Display reflections if st.session_state.reflections: st.markdown("---") st.subheader("Reflections") for reflection in reversed(st.session_state.reflections): with st.expander(f"{reflection['style']} at {reflection['timestamp']}", expanded=True): st.markdown(reflection['content'])