+2
-1
src/api/lettaApi.ts
+2
-1
src/api/lettaApi.ts
···
617
618
// CONSTRUCT content for tool call messages (if content is empty)
619
if ((type === 'tool_call_message' || type === 'tool_call') && !content && toolCall) {
620
const name = toolCall.name || 'tool';
621
const args = toolCall.arguments || '{}';
622
-
content = `${name}(${args})`;
623
}
624
625
// EXTRACT content for tool return messages (if content is empty)
···
617
618
// CONSTRUCT content for tool call messages (if content is empty)
619
if ((type === 'tool_call_message' || type === 'tool_call') && !content && toolCall) {
620
+
const { formatToolCall } = require('../utils/formatToolCall');
621
const name = toolCall.name || 'tool';
622
const args = toolCall.arguments || '{}';
623
+
content = formatToolCall(name, args);
624
}
625
626
// EXTRACT content for tool return messages (if content is empty)
+2
-10
src/hooks/useMessageStream.ts
+2
-10
src/hooks/useMessageStream.ts
···
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;
212
-
}
213
}
214
215
return {
···
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
+
const { formatToolCall } = require('../utils/formatToolCall');
204
+
content = formatToolCall(msg.toolCallName, msg.content);
205
}
206
207
return {
+32
src/utils/formatToolCall.ts
+32
src/utils/formatToolCall.ts
···
···
1
+
/**
2
+
* Format tool call arguments as Python-style string
3
+
*
4
+
* Input: { query: "poetry", num_results: 10 }
5
+
* Output: query="poetry", num_results=10
6
+
*/
7
+
export function formatToolArgs(args: any): string {
8
+
if (!args || typeof args !== 'object') {
9
+
return '';
10
+
}
11
+
12
+
return Object.entries(args)
13
+
.map(([k, v]) => `${k}=${typeof v === 'string' ? `"${v}"` : JSON.stringify(v)}`)
14
+
.join(', ');
15
+
}
16
+
17
+
/**
18
+
* Format tool call as Python-style function call
19
+
*
20
+
* Input: name="web_search", arguments='{"query":"poetry","num_results":10}'
21
+
* Output: web_search(query="poetry", num_results=10)
22
+
*/
23
+
export function formatToolCall(name: string, argumentsJson: string): string {
24
+
try {
25
+
const argsObj = JSON.parse(argumentsJson);
26
+
const formattedArgs = formatToolArgs(argsObj);
27
+
return `${name}(${formattedArgs})`;
28
+
} catch (e) {
29
+
// If JSON parse fails, wrap the raw string in parens
30
+
return `${name}(${argumentsJson})`;
31
+
}
32
+
}
+2
-23
src/utils/messageLabels.ts
+2
-23
src/utils/messageLabels.ts
···
14
15
/**
16
* Extract a specific argument from tool call arguments
17
-
* Handles multiple formats: Python string, JSON string, JSON-in-parens
18
*/
19
function extractToolArgument(group: MessageGroup, argName: string): string | null {
20
const argsStr = group.toolCall?.args || group.content || '';
21
22
-
// Try to parse as JSON first (pure JSON string)
23
-
if (argsStr.startsWith('{')) {
24
-
try {
25
-
const argsObj = JSON.parse(argsStr);
26
-
return argsObj[argName] || null;
27
-
} catch (e) {
28
-
// Not valid JSON, continue
29
-
}
30
-
}
31
-
32
-
// Try to extract JSON from inside parens: tool_name({"key": "value"})
33
-
const jsonMatch = argsStr.match(/\((\{.+\})\)/);
34
-
if (jsonMatch) {
35
-
try {
36
-
const argsObj = JSON.parse(jsonMatch[1]);
37
-
return argsObj[argName] || null;
38
-
} catch (e) {
39
-
// Not valid JSON, continue
40
-
}
41
-
}
42
-
43
-
// Try to extract from Python-style string: tool(arg="value", ...)
44
const regex = new RegExp(`${argName}=["']([^"']+)["']`);
45
const match = argsStr.match(regex);
46
if (match) {
···
14
15
/**
16
* Extract a specific argument from tool call arguments
17
+
* Expects Python-style format: tool(query="value", num=10)
18
*/
19
function extractToolArgument(group: MessageGroup, argName: string): string | null {
20
const argsStr = group.toolCall?.args || group.content || '';
21
22
+
// Extract from Python-style string: tool(arg="value", ...)
23
const regex = new RegExp(`${argName}=["']([^"']+)["']`);
24
const match = argsStr.match(regex);
25
if (match) {