/**
 * Builds a synthetic error result for a tool call that was never executed.
 *
 * @param call   - The dangling `ToolCall` from the provider response.
 * @param reason - Why reconciliation was triggered.
 * @returns A `SyntheticToolResult` safe to inject into the conversation.
 */
export function buildSyntheticResult(call, reason) {
    return {
        callId: call.id,
        success: false,
        error: `[RECONCILED] Tool call '${call.name}' (id: ${call.id}) was not executed — the turn ended before results could be produced. Reason: ${reason}.`,
        instruction: 'Do not retry the same call unless you are certain the underlying condition has changed.',
        synthetic: true,
        reason,
    };
}
/**
 * Determines whether a set of tool calls contains entries that were never
 * resolved (i.e., have no matching result in the provided results array).
 *
 * @param toolCalls - Tool calls from the provider response.
 * @param results   - Tool results collected during this turn.
 * @returns Array of unresolved `ToolCall` objects (may be empty).
 *
 * @note Uses Set semantics for resolved ID lookup: duplicate tool_use IDs in
 * `toolCalls` are each checked against the same resolved set, so both entries
 * are considered resolved if one result with that ID exists. The API spec
 * requires unique IDs, so duplicates are an error in provider output; treating
 * them as resolved prevents spurious synthetic results.
 */
export function detectUnresolvedToolCalls(toolCalls, results) {
    const resolvedIds = new Set(results.map((r) => r.callId));
    return toolCalls.filter((c) => !resolvedIds.has(c.id));
}
