A React Native app for the ultimate thinking partner.
at bf2a37bf805fa5ccc8b5badeeb098f842186e615 192 lines 7.2 kB view raw
1import lettaApi from '../api/lettaApi'; 2import type { LettaAgent } from '../types/letta'; 3import { getDefaultMemoryBlocks } from '../constants/memoryBlocks'; 4import { CO_SYSTEM_PROMPT } from '../constants/systemPrompt'; 5import { Letta } from "@letta-ai/letta-client"; 6 7const CO_TAG = 'co-app'; 8 9/** 10 * Create Co - a comprehensive knowledge management assistant 11 */ 12export async function createCoAgent(userName: string): Promise<LettaAgent> { 13 try { 14 const agent = await lettaApi.createAgent({ 15 name: 'Co', 16 description: 'Co - A comprehensive knowledge management assistant designed to learn, adapt, and think alongside the user', 17 // agentType: Letta.AgentType.LettaV1Agent, // currently pending sleeptime fixes 18 // agentType: Letta.AgentType.MemgptV2Agent, 19 model: 'anthropic/claude-sonnet-4-5-20250929', 20 system: CO_SYSTEM_PROMPT, 21 tags: [CO_TAG], 22 memoryBlocks: getDefaultMemoryBlocks(), 23 // includeBaseTools: false, 24 tools: [ 25 'conversation_search', 26 'web_search', 27 'fetch_webpage', 28 ], 29 toolRules: [], // No tool rules 30 enableSleeptime: true, 31 }); 32 33 console.log('Agent created, finding sleeptime agent via shared memory blocks...'); 34 35 // Get the first memory block ID - both primary and sleeptime agents share the same blocks 36 const blockId = agent.memory?.blocks?.[0]?.id; 37 38 if (!blockId) { 39 console.warn('No memory blocks found on agent. Cannot find sleeptime agent.'); 40 return agent; 41 } 42 43 console.log('Using block ID to find agents:', blockId); 44 45 // Get all agents that share this memory block (should be primary + sleeptime) 46 const agentsForBlock = await lettaApi.listAgentsForBlock(blockId); 47 console.log('Agents sharing this block:', agentsForBlock.map(a => ({ id: a.id, name: a.name }))); 48 49 // Find the sleeptime agent (the one that's NOT the primary agent) 50 const sleeptimeAgent = agentsForBlock.find(a => a.id !== agent.id); 51 52 if (sleeptimeAgent) { 53 console.log('Found sleeptime agent:', sleeptimeAgent.id, sleeptimeAgent.name); 54 55 // Retrieve full primary agent details and store sleeptime agent ID 56 const fullAgent = await lettaApi.getAgent(agent.id); 57 fullAgent.sleeptime_agent_id = sleeptimeAgent.id; 58 59 // Attach archival memory tools to sleeptime agent 60 await ensureSleeptimeTools(fullAgent); 61 62 return fullAgent; 63 } else { 64 console.warn('No sleeptime agent found sharing memory blocks. Only found:', agentsForBlock.length, 'agent(s)'); 65 return agent; 66 } 67 } catch (error) { 68 console.error('Error creating Co agent:', error); 69 throw error; 70 } 71} 72 73/** 74 * Ensure sleeptime agent has required archival memory tools and co_memory block 75 */ 76export async function ensureSleeptimeTools(agent: LettaAgent): Promise<void> { 77 try { 78 // Try to get sleeptime agent ID from either the custom property or multi_agent_group 79 const sleeptimeAgentId = agent.sleeptime_agent_id || agent.multi_agent_group?.agent_ids?.[0]; 80 81 if (!sleeptimeAgentId) { 82 console.log('No sleeptime agent found for agent:', agent.id); 83 return; 84 } 85 86 console.log('Ensuring sleeptime agent has archival tools and co_memory block:', sleeptimeAgentId); 87 88 // Get the sleeptime agent to check its current tools and blocks 89 const sleeptimeAgent = await lettaApi.getAgent(sleeptimeAgentId); 90 const sleeptimeToolNames = sleeptimeAgent.tools?.map(t => t.name) || []; 91 const sleeptimeBlockLabels = sleeptimeAgent.memory?.blocks?.map(b => b.label) || []; 92 93 console.log('Current sleeptime tools:', sleeptimeToolNames); 94 console.log('Current sleeptime blocks:', sleeptimeBlockLabels); 95 96 // Attach missing tools 97 const requiredTools = ['archival_memory_search', 'archival_memory_insert']; 98 for (const toolName of requiredTools) { 99 if (!sleeptimeToolNames.includes(toolName)) { 100 console.log(`Attaching ${toolName} to sleeptime agent`); 101 try { 102 await lettaApi.attachToolToAgentByName(sleeptimeAgentId, toolName); 103 console.log(`✓ Successfully attached ${toolName}`); 104 } catch (error) { 105 console.error(`✗ Failed to attach ${toolName}:`, error); 106 throw error; 107 } 108 } else { 109 console.log(`${toolName} already attached`); 110 } 111 } 112 113 // Ensure co_memory block exists 114 if (!sleeptimeBlockLabels.includes('co_memory')) { 115 console.log('Creating co_memory block for sleeptime agent'); 116 try { 117 const { CO_MEMORY_BLOCK } = await import('../constants/memoryBlocks'); 118 119 // Two-step process: create block, then attach to agent 120 const createdBlock = await lettaApi.createBlock({ 121 label: CO_MEMORY_BLOCK.label, 122 value: CO_MEMORY_BLOCK.value, 123 description: CO_MEMORY_BLOCK.description, 124 limit: CO_MEMORY_BLOCK.limit, 125 }); 126 127 console.log('✓ Created co_memory block:', createdBlock.id); 128 129 await lettaApi.attachBlockToAgent(sleeptimeAgentId, createdBlock.id!); 130 console.log('✓ Successfully attached co_memory block to sleeptime agent'); 131 } catch (error) { 132 console.error('✗ Failed to create/attach co_memory block:', error); 133 throw error; 134 } 135 } else { 136 console.log('✓ co_memory block already exists'); 137 } 138 } catch (error) { 139 console.error('Error in ensureSleeptimeTools:', error); 140 throw error; 141 } 142} 143 144/** 145 * Find or create the Co agent for the logged-in user 146 */ 147export async function findOrCreateCo(userName: string): Promise<LettaAgent> { 148 try { 149 // Try to find existing Co agent 150 const existingAgent = await lettaApi.findAgentByTags([CO_TAG]); 151 152 if (existingAgent) { 153 console.log('Found existing Co agent:', existingAgent.id); 154 155 // Retrieve full agent details 156 const fullAgent = await lettaApi.getAgent(existingAgent.id); 157 158 // Find sleeptime agent using shared memory blocks (same approach as createCoAgent) 159 const blockId = fullAgent.memory?.blocks?.[0]?.id; 160 161 if (blockId) { 162 console.log('Using block ID to find sleeptime agent:', blockId); 163 const agentsForBlock = await lettaApi.listAgentsForBlock(blockId); 164 console.log('Agents sharing this block:', agentsForBlock.map(a => ({ id: a.id, name: a.name }))); 165 166 // Find the sleeptime agent (the one that's NOT the primary agent) 167 const sleeptimeAgent = agentsForBlock.find(a => a.id !== fullAgent.id); 168 169 if (sleeptimeAgent) { 170 fullAgent.sleeptime_agent_id = sleeptimeAgent.id; 171 console.log('Found sleeptime agent for existing Co:', sleeptimeAgent.id); 172 } else { 173 console.warn('No sleeptime agent found sharing memory blocks for existing agent'); 174 } 175 } else { 176 console.warn('No memory blocks found on existing agent. Cannot find sleeptime agent.'); 177 } 178 179 // Ensure sleeptime agent has required tools 180 await ensureSleeptimeTools(fullAgent); 181 182 return fullAgent; 183 } 184 185 // Create new Co agent 186 console.log('Creating new Co agent for user:', userName); 187 return await createCoAgent(userName); 188 } catch (error) { 189 console.error('Error in findOrCreateCo:', error); 190 throw error; 191 } 192}