Private/Invoke-AnthropicReview.ps1

function Invoke-AnthropicReview {
    <#
    .SYNOPSIS
    Invoke code review using Anthropic Claude API
     
    .DESCRIPTION
    Calls Claude API with retry logic and returns parsed violations.
     
    .PARAMETER ReviewContext
    Array of file diffs
     
    .PARAMETER Rules
    Review rules markdown
     
    .PARAMETER ApiKey
    Anthropic API key
     
    .PARAMETER Config
    Provider configuration
     
    .PARAMETER MaxTokens
    Maximum output tokens
     
    .OUTPUTS
    System.Array - Array of violations
     
    .NOTES
    Author: waldo
    Version: 1.0.0
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [array]$ReviewContext,
        
        [Parameter(Mandatory = $true)]
        [string]$Rules,
        
        [Parameter(Mandatory = $true)]
        [string]$ApiKey,
        
        [Parameter(Mandatory = $true)]
        [object]$Config,
        
        [Parameter(Mandatory = $false)]
        [int]$MaxTokens = 4000
    )
    
    begin {
        Write-Verbose "Starting $($MyInvocation.MyCommand.Name)"
    }
    
    process {
        try {
            $prompts = Build-ReviewPrompt -Rules $Rules -ReviewContext $ReviewContext
            
            # Estimate tokens
            $estimatedInputTokens = [int](($prompts.SystemPrompt.Length + $prompts.UserPrompt.Length) / 4)
            Write-Host "Estimated input tokens: $estimatedInputTokens"
            
            $headers = @{
                "x-api-key" = $ApiKey
                "anthropic-version" = "2023-06-01"
                "content-type" = "application/json"
            }
            
            $body = @{
                model = $Config.model
                max_tokens = $MaxTokens
                system = $prompts.SystemPrompt
                messages = @(
                    @{
                        role = "user"
                        content = $prompts.UserPrompt
                    }
                )
            } | ConvertTo-Json -Depth 10
            
            # Call API with retry logic
            $maxRetries = 3
            $attempt = 0
            $violations = $null
            
            while ($attempt -lt $maxRetries -and $null -eq $violations) {
                try {
                    $attempt++
                    Write-Verbose "Calling Claude API (attempt $attempt/$maxRetries)..."
                    
                    $response = Invoke-RestMethod -Uri "https://api.anthropic.com/v1/messages" `
                        -Method Post `
                        -Headers $headers `
                        -Body $body `
                        -TimeoutSec 120
                    
                    $responseText = $response.content[0].text
                    Write-Verbose "Received response: $($responseText.Length) characters"
                    
                    $violations = Parse-AIResponse -ResponseText $responseText
                    
                    if ($null -ne $violations) {
                        Write-Host "✅ Successfully received $($violations.Count) violation(s)"
                        
                        # Log actual usage
                        if ($response.usage) {
                            Write-Host "Actual tokens: $($response.usage.input_tokens) input, $($response.usage.output_tokens) output"
                            $cost = ($response.usage.input_tokens / 1000000) * 3.0 + ($response.usage.output_tokens / 1000000) * 15.0
                            Write-Host "Estimated cost: `$$([math]::Round($cost, 4))"
                        }
                    }
                }
                catch {
                    Write-Warning "API call failed (attempt $attempt): $($_.Exception.Message)"
                    
                    if ($attempt -ge $maxRetries) {
                        throw "Failed after $maxRetries attempts: $($_.Exception.Message)"
                    }
                    
                    $sleepSeconds = [Math]::Pow(2, $attempt)
                    Write-Host "Retrying in $sleepSeconds seconds..."
                    Start-Sleep -Seconds $sleepSeconds
                }
            }
            
            return $violations
        }
        catch {
            Write-Error "Error in $($MyInvocation.MyCommand.Name): $_"
            throw
        }
    }
    
    end {
        Write-Verbose "Completed $($MyInvocation.MyCommand.Name)"
    }
}