protoagent 0.1.13 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agentic-loop.js +44 -0
- package/package.json +1 -1
package/dist/agentic-loop.js
CHANGED
|
@@ -235,6 +235,41 @@ function sanitizeMessagesForRetry(messages, validToolNames) {
|
|
|
235
235
|
});
|
|
236
236
|
return { messages: sanitizedMessages, changed };
|
|
237
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* Remove orphaned tool result messages that don't have a matching tool_call_id
|
|
240
|
+
* in any assistant message. This happens when messages are truncated and the
|
|
241
|
+
* assistant's tool_calls are removed but the tool results remain.
|
|
242
|
+
*/
|
|
243
|
+
function removeOrphanedToolResults(messages) {
|
|
244
|
+
// Collect all valid tool_call_ids from assistant messages
|
|
245
|
+
const validToolCallIds = new Set();
|
|
246
|
+
for (const message of messages) {
|
|
247
|
+
const msgAny = message;
|
|
248
|
+
if (message.role === 'assistant' && Array.isArray(msgAny.tool_calls)) {
|
|
249
|
+
for (const tc of msgAny.tool_calls) {
|
|
250
|
+
if (tc.id) {
|
|
251
|
+
validToolCallIds.add(tc.id);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// Filter out tool messages with orphaned tool_call_ids
|
|
257
|
+
const filteredMessages = messages.filter((message) => {
|
|
258
|
+
const msgAny = message;
|
|
259
|
+
if (message.role === 'tool' && msgAny.tool_call_id) {
|
|
260
|
+
const isOrphaned = !validToolCallIds.has(msgAny.tool_call_id);
|
|
261
|
+
if (isOrphaned) {
|
|
262
|
+
logger.warn('Removing orphaned tool result', {
|
|
263
|
+
tool_call_id: msgAny.tool_call_id,
|
|
264
|
+
contentPreview: msgAny.content?.slice(0, 100),
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
return !isOrphaned;
|
|
268
|
+
}
|
|
269
|
+
return true;
|
|
270
|
+
});
|
|
271
|
+
return { messages: filteredMessages, changed: filteredMessages.length !== messages.length };
|
|
272
|
+
}
|
|
238
273
|
function getValidToolNames() {
|
|
239
274
|
return new Set([...getAllTools(), subAgentTool]
|
|
240
275
|
.map((tool) => tool.function?.name)
|
|
@@ -695,6 +730,15 @@ export async function runAgenticLoop(client, model, messages, userInput, onEvent
|
|
|
695
730
|
continue;
|
|
696
731
|
}
|
|
697
732
|
}
|
|
733
|
+
// Try removing orphaned tool results
|
|
734
|
+
const orphanedRemoved = removeOrphanedToolResults(updatedMessages);
|
|
735
|
+
if (orphanedRemoved.changed) {
|
|
736
|
+
updatedMessages.length = 0;
|
|
737
|
+
updatedMessages.push(...orphanedRemoved.messages);
|
|
738
|
+
logger.warn('400 response after orphaned tool results; retrying with cleaned messages');
|
|
739
|
+
// Silently retry without showing error to user
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
698
742
|
// If sanitization didn't help, try removing messages one at a time (up to 5)
|
|
699
743
|
if (truncateRetryCount < MAX_TRUNCATE_RETRIES) {
|
|
700
744
|
truncateRetryCount++;
|