A React Native app for the ultimate thinking partner.

Update README and add GitHub link to login screen

- Completely rewrote README: removed emoji, focused on core concept of co as thinking partner
- Added open source link to login screen (links to github.com/letta-ai/co)
- Fixed Refresh Co error handling: catch 404 errors and continue with agent recreation

🐾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

+204 -168
+19 -8
App.new.tsx
··· 386 386 // Delete primary agent 387 387 await lettaApi.deleteAgent(coAgent.id); 388 388 console.log('Deleted primary agent:', coAgent.id); 389 - 390 - // Clear agent and messages from store 391 - clearAgent(); 392 - clearMessages(); 393 - // useAgent hook will automatically reinitialize when it detects no agent 394 389 } catch (error: any) { 395 - if (Platform.OS === 'web') { 396 - window.alert('Failed to refresh agent: ' + error.message); 390 + // If agent not found, it's already deleted - continue with refresh 391 + const isNotFound = error.message?.toLowerCase().includes('not found') || 392 + error.status === 404 || 393 + error.statusCode === 404; 394 + 395 + if (isNotFound) { 396 + console.log('Agent already deleted, continuing with refresh'); 397 397 } else { 398 - Alert.alert('Error', 'Failed to refresh agent: ' + error.message); 398 + // Real error - show to user and abort 399 + if (Platform.OS === 'web') { 400 + window.alert('Failed to refresh agent: ' + error.message); 401 + } else { 402 + Alert.alert('Error', 'Failed to refresh agent: ' + error.message); 403 + } 404 + return; 399 405 } 400 406 } 407 + 408 + // Clear agent and messages from store (runs even if agent was already deleted) 409 + clearAgent(); 410 + clearMessages(); 411 + // useAgent hook will automatically reinitialize when it detects no agent 401 412 }; 402 413 403 414 // Load data when view changes
+28
CoLoginScreen.tsx
··· 8 8 ActivityIndicator, 9 9 SafeAreaView, 10 10 useColorScheme, 11 + Linking, 11 12 } from 'react-native'; 12 13 import { StatusBar } from 'expo-status-bar'; 13 14 import { useFonts, Lexend_400Regular, Lexend_600SemiBold, Lexend_700Bold } from '@expo-google-fonts/lexend'; ··· 81 82 <Text style={styles.helpText}> 82 83 Don't have an API key? Visit letta.com to create one. 83 84 </Text> 85 + 86 + <View style={styles.githubLink}> 87 + <Text style={styles.githubText}> 88 + co is{' '} 89 + <Text 90 + style={styles.githubLinkText} 91 + onPress={() => Linking.openURL('https://github.com/letta-ai/co')} 92 + > 93 + open source 94 + </Text> 95 + {' '}and welcomes contributions 96 + </Text> 97 + </View> 84 98 </View> 85 99 </View> 86 100 <StatusBar style="auto" /> ··· 165 179 color: darkTheme.colors.text.tertiary, 166 180 textAlign: 'center', 167 181 lineHeight: 20, 182 + }, 183 + githubLink: { 184 + marginTop: 24, 185 + alignItems: 'center', 186 + }, 187 + githubText: { 188 + fontSize: 13, 189 + fontFamily: 'Lexend_400Regular', 190 + color: darkTheme.colors.text.tertiary, 191 + textAlign: 'center', 192 + }, 193 + githubLinkText: { 194 + color: darkTheme.colors.interactive.primary, 195 + textDecorationLine: 'underline', 168 196 }, 169 197 });
+157 -160
README.md
··· 1 1 # co 2 2 3 - A minimalist chat interface for Letta AI agents. Each user gets their own persistent co agent that learns and remembers across conversations. 3 + A thinking partner that learns how you think. 4 + 5 + co is a single AI agent that builds itself around you through conversation. Unlike traditional chatbots, co maintains a persistent, evolving understanding of who you are, what you're working on, and how you approach problems. 6 + 7 + ## Core Concept 8 + 9 + Every user gets one co agent. That's it. No switching between assistants, no configuring multiple bots. Just one agent that: 10 + 11 + - **Learns your patterns**: Notices how you think, what excites you, what frustrates you 12 + - **Remembers everything**: Maintains both short-term context and long-term memory 13 + - **Evolves with you**: Updates its understanding as you grow and change 14 + - **Thinks alongside you**: Not just responding, but actively making connections and surfacing insights 15 + 16 + The entire agent definition lives in `src/utils/coAgent.ts`. When you log in for the first time, co creates itself and begins learning. 17 + 18 + ## How It Works 19 + 20 + ### Single Agent Architecture 21 + 22 + When you log in, the app: 23 + 1. Looks for an agent tagged with `co-app` 24 + 2. If found, connects to your existing co 25 + 3. If not found, creates a new co agent 26 + 27 + This means your co persists across devices and sessions. The same agent, with all its accumulated knowledge about you, is available wherever you log in. 28 + 29 + ### Memory System 30 + 31 + co maintains structured memory across multiple blocks: 32 + 33 + **You** - Dynamic snapshot of what you're focused on right now. Updated frequently as your attention shifts. 34 + 35 + **Human** - Stable facts about you. Professional context, communication style, interests. Changes slowly over time. 36 + 37 + **Tasks** - What co is helping you accomplish. Added as new work emerges, removed when complete. 38 + 39 + **Knowledge Structure** - How you think. Mental models you use, patterns in how you approach problems, connections between concepts. 40 + 41 + **Interaction Log** - Significant moments in your relationship. Decisions made, insights gained, understanding that shifted. 42 + 43 + **Persona** - co's core identity and directives. How it thinks about its role as your thinking partner. 44 + 45 + **Memory Management** - Guidelines for when to create new memory blocks dynamically based on your usage patterns. 46 + 47 + ### Background Processing 48 + 49 + co includes a sleeptime agent that runs in the background: 50 + - Manages long-term archival memory 51 + - Surfaces relevant context from past conversations 52 + - Operates independently to maintain the primary agent's performance 53 + 54 + The sleeptime agent shares memory blocks with the primary agent, enabling seamless context passing. 4 55 5 56 ## Features 6 57 7 - - 🤖 **Single Agent**: One co agent per user, automatically created on first login 8 - - 🧠 **Persistent Memory**: Advanced memory blocks that evolve over time 9 - - 💬 **Smooth Streaming**: Token-buffered streaming (50 FPS) for consistent text appearance 10 - - 🎨 **Polished UI**: Clean, minimal interface with animated message transitions 11 - - 🌓 **Theme Toggle**: Switch between light and dark modes 12 - - 🔧 **Tool Support**: Web search, archival memory, conversation search 13 - - 📱 **Cross-platform**: iOS, Android, and Web support via React Native + Expo 14 - - 🔒 **Secure**: API token storage with AsyncStorage/SecureStore 58 + ### Persistent Memory 59 + Every conversation builds on what co already knows. The agent's understanding compounds over time. 15 60 16 - ## Architecture 61 + ### Real-time Streaming 62 + Messages stream token-by-token on web, creating natural conversation flow. 17 63 18 - co uses a simplified single-agent architecture: 64 + ### Adaptive Interface 65 + - Light and dark themes 66 + - Cross-platform support (iOS, Android, Web) 67 + - Responsive layout for mobile and desktop 19 68 20 - 1. **Login**: User enters Letta API key 21 - 2. **Agent Discovery**: App searches for agent with `co-app` tag 22 - 3. **Auto-creation**: If no co agent exists, creates one automatically 23 - 4. **Chat**: User chats directly with their co agent 69 + ### File Sharing 70 + Attach files to messages for context. Works across all platforms. 24 71 25 - ### co Agent Configuration 72 + ### Memory Inspection 73 + View co's memory blocks to see how its understanding has evolved. Available through the sidebar navigation. 26 74 27 - co is created with: 28 - - **Model**: `anthropic/claude-sonnet-4-5-20250929` 29 - - **Tools**: `send_message`, `archival_memory_insert`, `archival_memory_search`, `conversation_search`, `web_search`, `fetch_webpage` 30 - - **Memory Blocks**: 31 - - `persona`: co's adaptive personality 32 - - `human`: User profile that evolves 33 - - `approach`: Conversation and memory approach 34 - - `working_theories`: Active theories about the user 35 - - `notes_to_self`: Reminders for future reference 36 - - `active_questions`: Questions to explore 37 - - `conversation_summary`: Ongoing conversation overview 75 + ### Tool Access 76 + co can search the web, manage archival memory, and search conversation history to provide informed responses. 38 77 39 78 ## Getting Started 40 79 41 80 ### Prerequisites 42 81 43 - - Node.js 18+ 44 - - npm or yarn 45 - - Expo CLI 82 + - Node.js 18 or higher 46 83 - Letta API token from [letta.com](https://letta.com) 47 84 48 85 ### Installation 49 86 50 87 ```bash 51 - # Install dependencies 52 88 npm install 53 - 54 - # Start development server 55 89 npm start 56 - 57 - # For production performance (recommended) 58 - npm run web:prod 59 90 ``` 60 91 61 - ### Run Options 92 + Press `w` to open in browser, or scan the QR code with Expo Go on your mobile device. 62 93 63 - - **Web**: `npm run web` or press `w` 64 - - **iOS**: Press `i` (requires Xcode) 65 - - **Android**: Press `a` (requires Android Studio) 66 - - **Mobile Device**: Use Expo Go app and scan QR code 94 + ### First Conversation 67 95 68 - ### First Use 96 + 1. Enter your Letta API key 97 + 2. Wait for co to initialize (creates agent with memory blocks) 98 + 3. Start talking 69 99 70 - 1. Launch the app 71 - 2. Enter your Letta API key 72 - 3. Wait for co to initialize (creates agent if needed) 73 - 4. Start chatting! 100 + co begins building its understanding immediately. The more you interact, the better it gets at thinking alongside you. 101 + 102 + ## Configuration 103 + 104 + ### Agent Definition 74 105 75 - ## Project Structure 106 + The entire agent is defined in `src/utils/coAgent.ts`. Key configuration: 76 107 77 - ``` 78 - co/ 79 - ├── App.tsx # Main application 80 - ├── CoLoginScreen.tsx # Login/authentication 81 - ├── web-styles.css # Web-specific CSS for focus states and themes 82 - ├── src/ 83 - │ ├── api/ 84 - │ │ └── lettaApi.ts # Letta API client 85 - │ ├── components/ 86 - │ │ ├── MessageContent.tsx # Markdown message rendering 87 - │ │ ├── ExpandableMessageContent.tsx # Collapsible long messages 88 - │ │ ├── ToolCallItem.tsx # Tool execution display 89 - │ │ └── LogoLoader.tsx # Loading animations 90 - │ ├── types/ 91 - │ │ └── letta.ts # TypeScript definitions 92 - │ ├── utils/ 93 - │ │ ├── coAgent.ts # co agent creation logic 94 - │ │ └── storage.ts # AsyncStorage wrapper 95 - │ └── theme/ 96 - │ ├── index.ts # Theme system 97 - │ ├── colors.ts # Color palette 98 - │ └── typography.ts # Font definitions 108 + ```typescript 109 + model: 'anthropic/claude-haiku-4-5-20251001' 110 + tools: ['conversation_search', 'web_search', 'fetch_webpage', 'memory'] 111 + enableSleeptime: true 99 112 ``` 100 113 101 - ## Key Features 114 + ### Memory Blocks 102 115 103 - ### Smooth Token Streaming 116 + Default memory structure is defined in `src/constants/memoryBlocks.ts`. Each block includes: 117 + - Label (unique identifier) 118 + - Description (guides when/how co should update it) 119 + - Initial value (template structure) 120 + - Size limit 104 121 105 - Messages stream at 50 FPS with a token buffer that releases 1-3 characters at a time for consistent, natural text appearance. A hollow circle indicator (○) appears at the end of streaming text. 122 + co can dynamically create new blocks based on usage patterns (e.g., creating a "decision_log" if you frequently discuss choices, or "technical_notes" if you share code regularly). 106 123 107 - ### Animated Message Layout 124 + ### System Prompt 108 125 109 - When you send a message: 110 - 1. Message appears at the bottom 111 - 2. An animated spacer grows beneath it (400ms animation) 112 - 3. Your message smoothly rises to the top of the viewport 113 - 4. co's response fills the reserved space below 126 + co's core behavior is defined in `src/constants/systemPrompt.ts`. This establishes: 127 + - How co thinks about its role 128 + - When to update memory 129 + - How to decompose and synthesize information 130 + - Relationship dynamics with the user 114 131 115 - This creates a clean reading experience where your message stays visible with room for the response. 132 + ## Architecture 116 133 117 - ### Theme Support 134 + Built with React Native and Expo for true cross-platform support: 118 135 119 - Toggle between light and dark modes with inverted text input styling: 120 - - **Dark mode**: White background input with black text 121 - - **Light mode**: Black background input with white text 136 + - **State**: Zustand stores for agent, auth, and chat state 137 + - **API**: Letta SDK client with streaming support 138 + - **Storage**: AsyncStorage (mobile) and SecureStore (sensitive data) 139 + - **UI**: Native components with custom animations 122 140 123 - ### Memory Viewer 141 + Key files: 124 142 125 - Access co's memory blocks through the sidebar to see what co has learned about you and how it's evolving its understanding over time. 143 + ``` 144 + src/ 145 + utils/coAgent.ts - Agent creation and initialization 146 + constants/memoryBlocks.ts - Memory block templates 147 + constants/systemPrompt.ts - Agent behavior definition 148 + hooks/useAgent.ts - Agent lifecycle management 149 + hooks/useMessageStream.ts - Streaming message handler 150 + stores/agentStore.ts - Agent state management 151 + ``` 126 152 127 - ## Customizing co 153 + ## Development 128 154 129 - ### Modify Personality 155 + ### Running Locally 130 156 131 - Edit `src/utils/coAgent.ts` and update: 132 - - System prompt 133 - - Memory block initial values 134 - - Available tools 135 - - Model selection 157 + ```bash 158 + # Web with production optimizations 159 + npm run web:prod 136 160 137 - ### Add Memory Blocks 161 + # iOS 162 + npm run ios 138 163 139 - Add new blocks to the `memoryBlocks` array in `createCoAgent()`: 164 + # Android 165 + npm run android 140 166 141 - ```typescript 142 - { 143 - label: 'custom_block', 144 - value: 'Custom content here...', 145 - } 167 + # Clear cache if needed 168 + npx expo start -c 146 169 ``` 147 170 148 - ### Change Model 171 + ### Platform Notes 149 172 150 - Update the `model` field in `findOrCreateCo()`: 173 + **Web**: Full feature support including token streaming 151 174 152 - ```typescript 153 - model: 'openai/gpt-4.1', // or other supported models 154 - ``` 175 + **iOS/Android**: No streaming (SDK limitation), but all other features work 155 176 156 - ## Development 177 + **Image uploads**: Currently disabled due to SDK validation issues 157 178 158 - ### Tech Stack 179 + ## Deployment 159 180 160 - - **React Native** + **Expo**: Cross-platform framework 161 - - **TypeScript**: Type safety 162 - - **Letta SDK** (`@letta-ai/letta-client`): AI agent framework 163 - - **AsyncStorage/SecureStore**: Persistent storage 164 - - **React Native Markdown Display**: Markdown rendering 165 - - **Lexend Font**: Custom typography 181 + The app is deployed to Vercel: 166 182 167 - ### Available Scripts 183 + ```bash 184 + npx expo export --platform web 185 + npx vercel dist --prod --yes 186 + ``` 168 187 169 - - `npm start` - Start Expo dev server 170 - - `npm run web` - Run in browser (dev mode) 171 - - `npm run android` - Run on Android 172 - - `npm run ios` - Run on iOS 173 - - `npx expo start -c` - Clear cache and restart 188 + Production URL will be provided upon deployment. 174 189 175 - ### Production Build 190 + ## Customization 176 191 177 - For better performance: 192 + ### Changing the Model 178 193 179 - ```bash 180 - # Development with production optimizations 181 - npx expo start --web --no-dev --minify 194 + Edit `src/utils/coAgent.ts`: 182 195 183 - # Static production build 184 - npx expo export:web 185 - npx serve web-build 196 + ```typescript 197 + model: 'anthropic/claude-sonnet-4-5-20250929' // or any supported model 186 198 ``` 187 199 188 - ## API Integration 200 + ### Adding Memory Blocks 189 201 190 - co connects to Letta's API: 202 + Create new block definitions in `src/constants/memoryBlocks.ts` and add to `getDefaultMemoryBlocks()`. 191 203 192 - - `GET /agents?tags=co-app` - Find co agent 193 - - `POST /agents` - Create co agent 194 - - `GET /agents/{id}/messages` - Load message history 195 - - `POST /agents/{id}/messages/streaming` - Stream messages 196 - - `GET /agents/{id}/blocks` - View memory blocks 204 + ### Modifying Behavior 197 205 198 - ## Troubleshooting 206 + Edit `src/constants/systemPrompt.ts` to change how co thinks about its role and responsibilities. 199 207 200 - ### Agent Not Found 208 + ## Known Limitations 201 209 202 - If co fails to initialize: 203 - 1. Check API token validity at letta.com 204 - 2. Verify network connection 205 - 3. Check console logs for errors 206 - 4. Try logging out and back in 210 + - Image uploads disabled (SDK bug with streaming endpoint) 211 + - Token streaming only works on web (React Native SDK limitation) 212 + - Agent initialization with sleeptime can take 30-60 seconds 213 + - "Refresh Co" button may timeout during recreation 207 214 208 - ### Memory Blocks Not Loading 215 + ## Philosophy 209 216 210 - - Ensure agent is fully initialized 211 - - Check that `listAgentBlocks()` has proper permissions 212 - - Verify agent ID is correct 217 + Most AI assistants are stateless or have shallow memory. They respond to prompts but don't build deep models of who you are. 213 218 214 - ### Streaming Issues 219 + co is different. It's designed to become your thinking partner through sustained interaction. It notices patterns in how you work, remembers what matters to you, and proactively makes connections you might miss. 215 220 216 - - Check network stability 217 - - Verify streaming endpoint support 218 - - Review console logs for chunk errors 219 - - Try clearing Expo cache: `npx expo start -c` 221 + The goal isn't to replace your thinking. It's to augment it. To be the cognitive extension that helps you see your own ideas more clearly. 220 222 221 - ### Slow Performance 222 - 223 - Run the app with production optimizations: 224 - ```bash 225 - npx expo start --web --no-dev --minify 226 - ``` 227 - 228 - ## License 229 - 230 - MIT License 223 + One agent. One relationship. Built over time through conversation. 231 224 232 225 ## Resources 233 226 234 227 - [Letta Documentation](https://docs.letta.com) 235 - - [Letta LLMs.txt](https://docs.letta.com/llms.txt) 228 + - [Letta Discord](https://discord.gg/letta) 236 229 - [React Native Docs](https://reactnative.dev) 237 230 - [Expo Docs](https://docs.expo.dev) 231 + 232 + ## License 233 + 234 + MIT