A React Native app for the ultimate thinking partner.

Format tool call content as Python-style string when converting from streaming

Streaming stores args as JSON, but the UI expects Python-style format like:
web_search(query="poetry", num_results=10)

Now converts JSON args to formatted string when creating permanent messages,
matching what the server sends for non-streaming messages.

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

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

Changed files
+30 -13
src
+30 -13
src/hooks/useMessageStream.ts
··· 196 196 console.log('📨 Converting', allStreamedMessages.length, 'streamed messages to permanent messages'); 197 197 198 198 // Convert to LettaMessage format and add to messages 199 - const permanentMessages: LettaMessage[] = allStreamedMessages.map((msg, idx) => ({ 200 - id: msg.id, 201 - role: 'assistant', 202 - message_type: msg.type === 'tool_call' ? 'tool_call_message' : 'assistant_message', 203 - content: msg.content, 204 - reasoning: msg.reasoning, 205 - ...(msg.type === 'tool_call' && msg.toolCallName ? { 206 - tool_call: { 207 - name: msg.toolCallName, 208 - arguments: msg.content, 199 + const permanentMessages: LettaMessage[] = allStreamedMessages.map((msg, idx) => { 200 + // Format tool call content as Python-style string (like server does) 201 + let content = msg.content; 202 + if (msg.type === 'tool_call' && msg.toolCallName) { 203 + try { 204 + const argsObj = JSON.parse(msg.content); 205 + const formattedArgs = Object.entries(argsObj) 206 + .map(([k, v]) => `${k}=${typeof v === 'string' ? `"${v}"` : JSON.stringify(v)}`) 207 + .join(', '); 208 + content = `${msg.toolCallName}(${formattedArgs})`; 209 + } catch (e) { 210 + // If parse fails, keep original content 211 + content = msg.content; 209 212 } 210 - } : {}), 211 - created_at: msg.timestamp, 212 - } as any)); 213 + } 214 + 215 + return { 216 + id: msg.id, 217 + role: 'assistant', 218 + message_type: msg.type === 'tool_call' ? 'tool_call_message' : 'assistant_message', 219 + content: content, 220 + reasoning: msg.reasoning, 221 + ...(msg.type === 'tool_call' && msg.toolCallName ? { 222 + tool_call: { 223 + name: msg.toolCallName, 224 + arguments: msg.content, // Keep as JSON for parseToolCall fallback 225 + } 226 + } : {}), 227 + created_at: msg.timestamp, 228 + } as any; 229 + }); 213 230 214 231 // Add to messages array 215 232 if (permanentMessages.length > 0) {