@@ -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;
|
let rejectedCount = 0;
|
||||||
for (const approval of pending) {
|
for (const approval of pending) {
|
||||||
|
if (rejectedIds.has(approval.toolCallId)) continue;
|
||||||
|
rejectedIds.add(approval.toolCallId);
|
||||||
const ok = await rejectApproval(agentId, {
|
const ok = await rejectApproval(agentId, {
|
||||||
toolCallId: approval.toolCallId,
|
toolCallId: approval.toolCallId,
|
||||||
reason,
|
reason,
|
||||||
@@ -433,70 +438,73 @@ export async function getPendingApprovals(
|
|||||||
stop_reason: 'requires_approval',
|
stop_reason: 'requires_approval',
|
||||||
limit: 10,
|
limit: 10,
|
||||||
});
|
});
|
||||||
|
|
||||||
const pendingApprovals: PendingApproval[] = [];
|
// Collect qualifying run IDs (avoid re-fetching messages per run)
|
||||||
|
const qualifyingRunIds: string[] = [];
|
||||||
for await (const run of runsPage) {
|
for await (const run of runsPage) {
|
||||||
if (run.status === 'running' || run.stop_reason === 'requires_approval') {
|
if (run.status === 'running' || run.stop_reason === 'requires_approval') {
|
||||||
// Get recent messages to find approval_request_message
|
qualifyingRunIds.push(run.id);
|
||||||
const messagesPage = await client.agents.messages.list(agentId, {
|
}
|
||||||
conversation_id: conversationId,
|
}
|
||||||
limit: 100,
|
|
||||||
});
|
if (qualifyingRunIds.length === 0) {
|
||||||
|
return [];
|
||||||
const messages: Array<{ message_type?: string }> = [];
|
}
|
||||||
for await (const msg of messagesPage) {
|
|
||||||
messages.push(msg as { message_type?: string });
|
// Fetch messages ONCE and scan for resolved + pending approvals
|
||||||
}
|
const messagesPage = await client.agents.messages.list(agentId, {
|
||||||
|
conversation_id: conversationId,
|
||||||
const resolvedToolCalls = new Set<string>();
|
limit: 100,
|
||||||
for (const msg of messages) {
|
});
|
||||||
if ('message_type' in msg && msg.message_type === 'approval_response_message') {
|
|
||||||
const approvalMsg = msg as {
|
const messages: Array<{ message_type?: string }> = [];
|
||||||
approvals?: Array<{ tool_call_id?: string | null }>;
|
for await (const msg of messagesPage) {
|
||||||
};
|
messages.push(msg as { message_type?: string });
|
||||||
const approvals = approvalMsg.approvals || [];
|
}
|
||||||
for (const approval of approvals) {
|
|
||||||
if (approval.tool_call_id) {
|
// Build set of already-resolved tool_call_ids
|
||||||
resolvedToolCalls.add(approval.tool_call_id);
|
const resolvedToolCalls = new Set<string>();
|
||||||
}
|
for (const msg of messages) {
|
||||||
}
|
if ('message_type' in msg && msg.message_type === 'approval_response_message') {
|
||||||
}
|
const approvalMsg = msg as {
|
||||||
}
|
approvals?: Array<{ tool_call_id?: string | null }>;
|
||||||
|
};
|
||||||
const seenToolCalls = new Set<string>();
|
const approvals = approvalMsg.approvals || [];
|
||||||
for (const msg of messages) {
|
for (const approval of approvals) {
|
||||||
// Check for approval_request_message type
|
if (approval.tool_call_id) {
|
||||||
if ('message_type' in msg && msg.message_type === 'approval_request_message') {
|
resolvedToolCalls.add(approval.tool_call_id);
|
||||||
const approvalMsg = msg as {
|
|
||||||
id: string;
|
|
||||||
tool_calls?: Array<{ tool_call_id: string; name: string }>;
|
|
||||||
tool_call?: { tool_call_id: string; name: string };
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
seenToolCalls.add(tc.tool_call_id);
|
|
||||||
pendingApprovals.push({
|
|
||||||
runId: approvalMsg.run_id || run.id,
|
|
||||||
toolCallId: tc.tool_call_id,
|
|
||||||
toolName: tc.name,
|
|
||||||
messageId: approvalMsg.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Collect unresolved approval requests, deduplicating across all runs
|
||||||
|
const pendingApprovals: PendingApproval[] = [];
|
||||||
|
const seenToolCalls = new Set<string>();
|
||||||
|
for (const msg of messages) {
|
||||||
|
if ('message_type' in msg && msg.message_type === 'approval_request_message') {
|
||||||
|
const approvalMsg = msg as {
|
||||||
|
id: string;
|
||||||
|
tool_calls?: Array<{ tool_call_id: string; name: string }>;
|
||||||
|
tool_call?: { tool_call_id: string; name: string };
|
||||||
|
run_id?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
seenToolCalls.add(tc.tool_call_id);
|
||||||
|
pendingApprovals.push({
|
||||||
|
runId: approvalMsg.run_id || qualifyingRunIds[0],
|
||||||
|
toolCallId: tc.tool_call_id,
|
||||||
|
toolName: tc.name,
|
||||||
|
messageId: approvalMsg.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return pendingApprovals;
|
return pendingApprovals;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error('Failed to get pending approvals:', e);
|
log.error('Failed to get pending approvals:', e);
|
||||||
|
|||||||
Reference in New Issue
Block a user