@@ -90,8 +90,13 @@ export async function recoverPendingApprovalsForAgent(
|
||||
};
|
||||
}
|
||||
|
||||
// Deduplicate by tool_call_id defensively (getPendingApprovals should
|
||||
// already dedup, but this guards against any upstream regression).
|
||||
const rejectedIds = new Set<string>();
|
||||
let rejectedCount = 0;
|
||||
for (const approval of pending) {
|
||||
if (rejectedIds.has(approval.toolCallId)) continue;
|
||||
rejectedIds.add(approval.toolCallId);
|
||||
const ok = await rejectApproval(agentId, {
|
||||
toolCallId: approval.toolCallId,
|
||||
reason,
|
||||
@@ -434,11 +439,19 @@ export async function getPendingApprovals(
|
||||
limit: 10,
|
||||
});
|
||||
|
||||
const pendingApprovals: PendingApproval[] = [];
|
||||
|
||||
// Collect qualifying run IDs (avoid re-fetching messages per run)
|
||||
const qualifyingRunIds: string[] = [];
|
||||
for await (const run of runsPage) {
|
||||
if (run.status === 'running' || run.stop_reason === 'requires_approval') {
|
||||
// Get recent messages to find approval_request_message
|
||||
qualifyingRunIds.push(run.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (qualifyingRunIds.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Fetch messages ONCE and scan for resolved + pending approvals
|
||||
const messagesPage = await client.agents.messages.list(agentId, {
|
||||
conversation_id: conversationId,
|
||||
limit: 100,
|
||||
@@ -449,6 +462,7 @@ export async function getPendingApprovals(
|
||||
messages.push(msg as { message_type?: string });
|
||||
}
|
||||
|
||||
// Build set of already-resolved tool_call_ids
|
||||
const resolvedToolCalls = new Set<string>();
|
||||
for (const msg of messages) {
|
||||
if ('message_type' in msg && msg.message_type === 'approval_response_message') {
|
||||
@@ -464,9 +478,10 @@ export async function getPendingApprovals(
|
||||
}
|
||||
}
|
||||
|
||||
// Collect unresolved approval requests, deduplicating across all runs
|
||||
const pendingApprovals: PendingApproval[] = [];
|
||||
const seenToolCalls = new Set<string>();
|
||||
for (const msg of messages) {
|
||||
// Check for approval_request_message type
|
||||
if ('message_type' in msg && msg.message_type === 'approval_request_message') {
|
||||
const approvalMsg = msg as {
|
||||
id: string;
|
||||
@@ -475,18 +490,13 @@ export async function getPendingApprovals(
|
||||
run_id?: string;
|
||||
};
|
||||
|
||||
// Extract tool call info
|
||||
const toolCalls = approvalMsg.tool_calls || (approvalMsg.tool_call ? [approvalMsg.tool_call] : []);
|
||||
for (const tc of toolCalls) {
|
||||
if (resolvedToolCalls.has(tc.tool_call_id)) {
|
||||
continue;
|
||||
}
|
||||
if (seenToolCalls.has(tc.tool_call_id)) {
|
||||
continue;
|
||||
}
|
||||
if (resolvedToolCalls.has(tc.tool_call_id)) continue;
|
||||
if (seenToolCalls.has(tc.tool_call_id)) continue;
|
||||
seenToolCalls.add(tc.tool_call_id);
|
||||
pendingApprovals.push({
|
||||
runId: approvalMsg.run_id || run.id,
|
||||
runId: approvalMsg.run_id || qualifyingRunIds[0],
|
||||
toolCallId: tc.tool_call_id,
|
||||
toolName: tc.name,
|
||||
messageId: approvalMsg.id,
|
||||
@@ -494,8 +504,6 @@ export async function getPendingApprovals(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pendingApprovals;
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user