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