Antigravity : BigInt Patcher Suite and Cleanup [Windows] [Linux] [MacOS]

Heya, published on the Git a script for patching BigInt. I’m just on Windows, and would love some help from anyone on Mac and Linux to help me test? It patches the full BigInt at LOCALAPPDATA\Programs\Antigravity\resources\app\out\main.js

It handles patching, checking, and unpatching as well as a backup and restoration feature for safety, which should resolve numerous different issues for different users on different operating systems! :smiley:

(full code is dropped below)

https://github.com/DuctTapedGoat/antigravity-bigint-patcher-cleanup

Antigravity Cleanup Script and BigInt Patcher Suite

This repository contains a suite of scripts designed to patch the Antigravity application to handle BigInt values correctly when using JSON.stringify. This is a common issue that can cause crashes or data loss, and these tools provide a robust, cross-platform solution.

This suite was created by Duct with research and insights from the r/Google_Antigravity community.

Features

  • Intelligent Patching: The patcher analyzes all JSON.stringify calls and intelligently classifies them as “Easy” or “Risky” to ensure the correct patching method is used.

  • Interactive Tools: The patcher, unpatcher, and checker are all fully interactive, with color-coded menus and clear instructions.

  • Safe by Design: The patcher requires a security key confirmation for potentially dangerous “Risky” patches, preventing accidental application.

  • Cross-Platform: The toolset is available for Windows, macOS, and Linux, with identical functionality on all three platforms.

  • Full Suite: Includes a patcher, unpatcher, a diagnostic checker, and a cleanup utility.

How to Use

Download the appropriate files for your operating system. The scripts are organized into windows, macos, and linux directories.

Windows

Navigate to the windows directory. The easiest way to use the tools is to run the .bat launcher files:

  • bigint-patcher.bat: Starts the interactive patcher.

  • bigint-unpatcher.bat: Starts the interactive unpatcher.

  • bigint-checker.bat: Starts the interactive diagnostic checker.

  • ag-cleanup.bat: Starts the cleanup utility to remove configuration and backup files.

macOS

Navigate to the macos directory. You can run the tools directly from the terminal, or you can use the convenient .command launchers.

First time use: Before you can use the .command files, you must make them executable. Open a Terminal window, navigate to the macos directory, and run the following command:

chmod +x *.command

After that, you can simply double-click any of the following files to launch them:

  • bigint-patcher.command: Starts the interactive patcher.

  • bigint-unpatcher.command: Starts the interactive unpatcher.

  • bigint-checker.command: Starts the interactive diagnostic checker.

  • ag-cleanup.command: Starts the cleanup utility.

Linux

Navigate to the linux directory and run the scripts directly from your terminal.

First time use: You may need to make the scripts executable. Run the following command:

chmod +x *.sh

Then, run the desired tool:

  • ./bigint-patcher.sh: Starts the interactive patcher.

  • ./bigint-unpatcher.sh: Starts the interactive unpatcher.

  • ./bigint-checker.sh: Starts the interactive diagnostic checker.

  • ./ag-cleanup.sh: Starts the cleanup utility.

Script Descriptions

  • Patcher: The main tool for applying the BigInt patch. It will scan the Antigravity application, classify all JSON.stringify calls, and allow you to apply the correct patch.

  • Unpatcher: Reverts any changes made by the patcher, restoring the Antigravity application to its original state.

  • Checker: A diagnostic tool that scans the application and provides a detailed, color-coded report on the status of all JSON.stringify calls without making any changes.

  • Cleanup: A utility to remove all user-level configuration files, caches, and leftover backup files for clean uninstallation and reinstallation of Antigravity.

Windows

ag-cleanup.ps1

# =====================================================================================
#  Antigravity Aggressive Cleanup for Windows
# =====================================================================================

function Clear-HostWrite-Header {
    Clear-Host
    Write-Host ""
    Write-Host "  ============================================================" -ForegroundColor Cyan
    Write-Host "        Antigravity Aggressive Cleanup for Windows"              -ForegroundColor Cyan
    Write-Host "  ============================================================" -ForegroundColor Cyan
    Write-Host ""
    Write-Host "  This script is based on the amazing research by DuctTapedGoat" -ForegroundColor Yellow
    Write-Host "  from the r/google_antigravity community." -ForegroundColor Yellow
    Write-Host ""
}

# --- Main Script ---

Clear-HostWrite-Header

Write-Host "  This script will perform the Aggressive Cleanup to remove all"
Write-Host "  Antigravity cache and data files from your system."
Write-Host ""
Write-Host "  Please ensure you have UNINSTALLED Antigravity before proceeding." -ForegroundColor Yellow
Write-Host ""

$confirmation = Read-Host "  Are you ready to proceed? (y/n)"

if ($confirmation -ne 'y') {
    Write-Host ""
    Write-Host "  Aborting script. No files were changed." -ForegroundColor Red
    Write-Host ""
    exit
}

$foldersToDelete = @()
$foldersToDelete += Join-Path $env:LOCALAPPDATA 'Programs\Antigravity'
$foldersToDelete += Join-Path $env:APPDATA 'Antigravity'
$foldersToDelete += Join-Path $env:USERPROFILE '.gemini'
$foldersToDelete += Join-Path $env:USERPROFILE '.antigravity'

Clear-HostWrite-Header

Write-Host "  The following directories (and all their contents) will be deleted:" -ForegroundColor White
Write-Host ""

foreach ($folder in $foldersToDelete) {
    if (Test-Path $folder) {
        Write-Host "  - $folder" -ForegroundColor Yellow
    } else {
        Write-Host "  - $folder (Not Found)" -ForegroundColor DarkGray
    }
}

Write-Host ""
$finalConfirmation = Read-Host "  THIS IS YOUR FINAL WARNING. Continue? (y/n)"

if ($finalConfirmation -ne 'y') {
    Write-Host ""
    Write-Host "  Aborting script. No files were changed." -ForegroundColor Red
    Write-Host ""
    exit
}

Write-Host ""
Write-Host "  Deleting files..." -ForegroundColor Green

foreach ($folder in $foldersToDelete) {
    if (Test-Path $folder) {
        try {
            Remove-Item -Path $folder -Recurse -Force -ErrorAction Stop
            Write-Host "    - DELETED: $folder" -ForegroundColor Green
        } catch {
            Write-Host "    - FAILED to delete: $folder" -ForegroundColor Red
            Write-Host "      Error: $_" -ForegroundColor DarkRed
        }
    }
}

Write-Host ""
Write-Host "  ============================================================" -ForegroundColor Cyan
Write-Host "                  CLEANUP COMPLETE!" -ForegroundColor Cyan
Write-Host "  ============================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "  What to do next:" -ForegroundColor White
Write-Host ""
Write-Host "  1. Set your DEFAULT SYSTEM BROWSER to a clean new browser"
Write-Host "     with ONLY your paid Antigravity Google account signed in."
Write-Host "     (Using Chrome Canary is a great way to keep this separate)."
Write-Host ""
Write-Host "  2. Reinstall Google Antigravity (do NOT run as Administrator)."
Write-Host ""
Write-Host "  3. Launch Antigravity and sign in. Your timers should now be truthful!"
Write-Host ""
Write-Host "  4. Once Antigravity is reinstalled, you can run the 'bigint-patch.bat'"
Write-Host "     to fix the BigInt serialization bug."
Write-Host ""
Write-Host "  5. If that doesn't work try creating a new OS user account and sign in."
Write-Host ""
Read-Host "  Press Enter to exit."


bigint-patcher.ps1


# =====================================================================================
#  Antigravity BigInt Patcher for Windows
# =====================================================================================

$targetFile = Join-Path $env:LOCALAPPDATA 'Programs\Antigravity\resources\app\out\main.js'
$backupFile = "$targetFile.bak"
$patchedLogic = '(_k, v) => typeof v === "bigint" ? v.toString() : v'

# --- Utility Functions ---

function Write-Header($title) {
    Clear-Host
    Write-Host ""
    Write-Host "  ==============================================================" -ForegroundColor Cyan
    Write-Host "             $title" -ForegroundColor Cyan
    Write-Host "  ==============================================================" -ForegroundColor Cyan
    Write-Host ""
}

function Get-Classification {
    param($text)

    if ($text -notmatch '^JSON\.stringify\((.*)\)$') { return @{ Type = 'unknown' } }
    $argsContent = $Matches[1].Trim()

    # If it contains any of these characters, it's not a simple variable, so it's risky.
    if ($argsContent -match '[\{\(\[\]\}\,]') {
        return @{ Type = 'risky' }
    } else {
        return @{ Type = 'easy' }
    }
}


# --- Main Application Loop ---

if (-not (Test-Path $targetFile)) {
    Write-Header "Error"
    Write-Host "  Antigravity main.js not found at $targetFile" -ForegroundColor Red
    exit
}

$content = Get-Content -Raw $targetFile

while ($true) {
    Write-Header "Windows BigInt Omni-Patcher v8 (Final)"

    # --- Analysis Phase ---
    # This section is now IDENTICAL to the checker and unpatcher for unified logic.
    $allRegex = 'JSON\.stringify\((?:[^()]|\([^()]*\))*\)'
    $allFoundMatches = [regex]::Matches($content, $allRegex)
    $allItems = @()
    $lineNumber = 1
    $currentPos = 0

    foreach ($m in $allFoundMatches) {
        $text = $m.Value
        $index = $m.Index
        $gap = $content.Substring($currentPos, $index - $currentPos)
        $lineNumber += ($gap -split "`n").Length - 1
        $currentPos = $index
        
        $item = [PSCustomObject]@{ Line = $lineNumber; Position = $index; Text = $text; Type = ''; Color = 'Gray' }

        if ($text -like '*(typeof _r ===*bigint*)*') { # Check for the most specific patch first (Risky-Wrapped)
            $item.Type = 'Patched (Risky-Wrapped)'; $item.Color = 'Cyan'
        } elseif ($text -like 'JSON.stringify(*, (_k, v) => typeof v === "bigint"*') { # Easy or Risky-Added
            $unpatchedVersion = $text -replace ',\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v', ''
            $classification = Get-Classification -text $unpatchedVersion
            if ($classification.Type -eq 'easy') {
                $item.Type = 'Patched (Easy)'; $item.Color = 'Green'
            } else {
                $item.Type = 'Patched (Risky-Added)'; $item.Color = 'Yellow'
            }
        } else { # Unpatched
            $classification = Get-Classification -text $text
            if ($classification.Type -eq 'easy') {
                $item.Type = 'Unpatched (Easy)'; $item.Color = 'Red'
            } else {
                $item.Type = 'Unpatched (Risky)'; $item.Color = 'Yellow'
            }
        }
        $allItems += $item
    }

    # --- Count Categories ---
    $patchedEasyCount = ($allItems | Where-Object { $_.Type -eq 'Patched (Easy)' }).Count
    $patchedRiskyAddedCount = ($allItems | Where-Object { $_.Type -eq 'Patched (Risky-Added)' }).Count
    $patchedRiskyWrappedCount = ($allItems | Where-Object { $_.Type -eq 'Patched (Risky-Wrapped)' }).Count
    $unpatchedEasyCount = ($allItems | Where-Object { $_.Type -eq 'Unpatched (Easy)' }).Count
    $unpatchedRiskyCount = ($allItems | Where-Object { $_.Type -eq 'Unpatched (Risky)' }).Count

    Write-Host "  Scan Complete!"
    Write-Host "  - Patched (Easy):          $patchedEasyCount" -ForegroundColor Green
    Write-Host "  - Patched (Risky-Added):   $patchedRiskyAddedCount" -ForegroundColor Yellow
    Write-Host "  - Patched (Risky-Wrapped): $patchedRiskyWrappedCount" -ForegroundColor Cyan
    Write-Host "  - Unpatched (Easy):        $unpatchedEasyCount" -ForegroundColor Red
    Write-Host "  - Unpatched (Risky):       $unpatchedRiskyCount" -ForegroundColor Yellow
    Write-Host ""
    Write-Host "  OPTIONS:" -ForegroundColor Gray
    Write-Host "  1. Bulk Patch all EASY ($unpatchedEasyCount)"
    Write-Host "  2. Bulk Patch all RISKY ($unpatchedRiskyCount)" -ForegroundColor Yellow
    Write-Host "  3. Exit"
    Write-Host ""

    $choice = Read-Host "  Enter Option#"

    if ($choice -eq "3") { exit }

    if (-not (Test-Path $backupFile)) {
        Write-Host "  Creating backup of fresh install..." -ForegroundColor Yellow
        Copy-Item $targetFile $backupFile -Force
    }

    $patcherRegex = '^JSON\.stringify\((.*)\)$';

    if ($choice -eq "1") {
        if ($unpatchedEasyCount -eq 0) { Write-Host "  No easy patches available."; Start-Sleep 1; continue }
        $newContent = $content
        $sortedEasy = $allItems | Where-Object { $_.Type -eq 'Unpatched (Easy)' } | Sort-Object Position -Descending

        foreach ($h in $sortedEasy) {
            if ($h.Text -match $patcherRegex) {
                $argsContent = $Matches[1]
                $replacement = "JSON.stringify($argsContent, $patchedLogic)"
                $newContent = $newContent.Remove($h.Position, $h.Text.Length).Insert($h.Position, $replacement)
            }
        }
        $content = $newContent
        Set-Content -Path $targetFile -Value $content -NoNewline -Encoding UTF8
        Write-Host "  Easy Bulk Patch Applied!" -ForegroundColor Green; Start-Sleep 2
    }

    if ($choice -eq "2") {
        if ($unpatchedRiskyCount -eq 0) { Write-Host "  No risky patches available."; Start-Sleep 1; continue }
        $riskyHits = $allItems | Where-Object { $_.Type -eq 'Unpatched (Risky)' }
        $lineSum = ($riskyHits | Measure-Object -Property Line -Sum).Sum
        $indexSum = ($riskyHits | Measure-Object -Property Position -Sum).Sum
        $securityKey = "${lineSum}:${indexSum}"

        Write-Host ""
        Write-Host "  DANGEROUS: To confirm this risky patch, type the following key and press Enter:" -ForegroundColor Yellow
        Write-Host "  $securityKey" -ForegroundColor Cyan
        $userInput = Read-Host "  Enter security key"

        if ($userInput -ne $securityKey) { Write-Host "  Incorrect key."; Start-Sleep 2; continue }

        $newContent = $content
        $sortedRisky = $riskyHits | Sort-Object Position -Descending

        foreach ($h in $sortedRisky) {
             if ($h.Text -match $patcherRegex) {
                $argsContent = $Matches[1]

                # Determine if this is a single-arg or multi-arg risky call
                $isSingleArg = $true
                if ($argsContent -match '[\{\(\[\]\}]\s*,.+') {
                    $isSingleArg = $false
                }

                if ($isSingleArg) {
                    # It's a single, complex argument. Add our replacer.
                    $newText = "JSON.stringify($argsContent, $patchedLogic)"
                    $newContent = $newContent.Remove($h.Position, $h.Text.Length).Insert($h.Position, $newText)
                } else {
                    # It's a multi-argument call. Wrap the existing replacer.
                    $depth = 0; $inString = $false; $stringChar = ''; $isEscaped = $false; ${first_comm-index} = -1
                    for ($i = 0; $i -lt $argsContent.Length; $i++) {
                        $char = $argsContent[$i]
                        if ($isEscaped) { $isEscaped = $false; continue }
                        if ($char -eq '\') { $isEscaped = $true; continue }
                        if (($char -eq "'" -or $char -eq '"' -or $char -eq '`')) {
                            if ($inString -and $char -eq $stringChar) { $inString = $false } elseif (-not $inString) { $inString = $true; $stringChar = $char }
                        }
                        if ($inString) { continue }
                        if ($char -eq '(' -or $char -eq '{' -or $char -eq '[') { $depth++ }
                        elseif ($char -eq ')' -or $char -eq '}' -or $char -eq ']') { $depth-- }
                        if ($char -eq ',' -and $depth -eq 0) { ${first_comm-index} = $i; break }
                    }

                    if (${first_comm-index} -ne -1) {
                        $arg1 = $argsContent.Substring(0, ${first_comm-index}).Trim()
                        $rest = $argsContent.Substring(${first_comm-index} + 1).Trim()
                        $replacer = $rest
                        $restOfArgs = ''

                        # Find the second comma to isolate the replacer
                        $depth = 0; $inString = $false; $stringChar = ''; $isEscaped = $false; ${second_comm-index} = -1
                        for ($i = 0; $i -lt $rest.Length; $i++) {
                             $char = $rest[$i]
                             if ($isEscaped) { $isEscaped = $false; continue }
                             if ($char -eq '\') { $isEscaped = $true; continue }
                             if (($char -eq "'" -or $char -eq '"' -or $char -eq '`')) {
                                if ($inString -and $char -eq $stringChar) { $inString = $false } elseif (-not $inString) { $inString = $true; $stringChar = $char }
                             }
                             if ($inString) { continue }
                             if ($char -eq '(' -or $char -eq '{' -or $char -eq '[') { $depth++ }
                             elseif ($char -eq ')' -or $char -eq '}' -or $char -eq ']') { $depth-- }
                             if ($char -eq ',' -and $depth -eq 0) { ${second_comm-index} = $i; break }
                        }

                        if (${second_comm-index} -ne -1) {
                            $replacer = $rest.Substring(0, ${second_comm-index}).Trim()
                            $restOfArgs = $rest.Substring(${second_comm-index})
                        }

                        $wrappedReplacer = "(_k, v) => { let _r = ($replacer)(_k, v); return typeof _r === `"bigint`" ? _r.toString() : _r; }"
                        $newText = "JSON.stringify($arg1, $wrappedReplacer$restOfArgs)"
                        $newContent = $newContent.Remove($h.Position, $h.Text.Length).Insert($h.Position, $newText)
                    }
                }
            }
        }
        $content = $newContent
        Set-Content -Path $targetFile -Value $content -NoNewline -Encoding UTF8
        Write-Host "  Risky Bulk Patch Applied!" -ForegroundColor Green; Start-Sleep 2
    }
}

bigint-checker.ps1

# =====================================================================================
#  Antigravity BigInt Checker for Windows
# =====================================================================================

$targetFile = Join-Path $env:LOCALAPPDATA 'Programs\Antigravity\resources\app\out\main.js'
$logFile = "$PSScriptRoot\bigint-scan.log"

# --- Regex for DETECTION ---
$easyPatchRegex = 'JSON\.stringify\(([^,]*?),\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v\)'
$riskyWrappedUnpatchRegex = 'JSON\.stringify\((.*?),\s*\(_k, v\)\s*=>\s*{\s*let\s*_r\s*=\s*\((.*?)\)\(_k, v\);\s*return\s*typeof\s*_r\s*===\s*"bigint"\s*\?\s*_r\.toString\(\)\s*:\s*_r;\s*}(,.*?)?\)'
$riskyAddedUnpatchRegex = 'JSON\.stringify\(([\{\(\[].*?[\}\)\]]),\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v\)'

# --- Utility Functions ---
function Write-Header($title) {
    Clear-Host
    Write-Host ""
    Write-Host "  ==============================================================" -ForegroundColor Cyan
    Write-Host "             $title" -ForegroundColor Cyan
    Write-Host "  ==============================================================" -ForegroundColor Cyan
    Write-Host ""
}

# --- Main Application Loop ---
if (-not (Test-Path $targetFile)) { Write-Header "Error"; Write-Host "  Antigravity main.js not found at $targetFile" -ForegroundColor Red; exit }

while ($true) {
    Write-Header "Windows BigInt Checker"
    $content = Get-Content -Raw $targetFile

    # --- Analysis Phase ---
    $allRegex = 'JSON\.stringify\((?:[^()]|\([^()]*\))*\)'
    $allFoundMatches = [regex]::Matches($content, $allRegex)
    $allItems = @()
    $lineNumber = 1
    $currentPos = 0

    # This classification function must be IDENTICAL to the one in the patcher.
    function Get-Classification {
        param($text)
        if ($text -notmatch '^JSON\.stringify\((.*)\)$') { return @{ Type = 'unknown' } }
        $argsContent = $Matches[1].Trim()
        if ($argsContent -match '[\{\(\[\]\}\,]') { return @{ Type = 'risky' } } else { return @{ Type = 'easy' } }
    }

    foreach ($m in $allFoundMatches) {
        $text = $m.Value
        $index = $m.Index
        $gap = $content.Substring($currentPos, $index - $currentPos)
        $lineNumber += ($gap -split "`n").Length - 1
        $currentPos = $index
        
        $item = [PSCustomObject]@{ Line = $lineNumber; Position = $index; Text = $text; Type = ''; Color = 'Gray' }

        if ($text -like '*(typeof _r ===*bigint*)*') { # Check for the most specific patch first
            $item.Type = 'Patched (Risky-Wrapped)'; $item.Color = 'Cyan'
        } elseif ($text -like 'JSON.stringify(*, (_k, v) => typeof v === "bigint"*)') {
            # This is a broad check. We need to see if it was a risky-add or an easy-add.
            $unpatchedVersion = $text -replace ',\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v', ''
            $classification = Get-Classification -text $unpatchedVersion
            if ($classification.Type -eq 'easy') {
                $item.Type = 'Patched (Easy)'; $item.Color = 'Green'
            } else {
                $item.Type = 'Patched (Risky-Added)'; $item.Color = 'Yellow'
            }
        } else {
            $classification = Get-Classification -text $text
            if ($classification.Type -eq 'easy') {
                $item.Type = 'Unpatched (Easy)'; $item.Color = 'Red'
            } else {
                $item.Type = 'Unpatched (Risky)'; $item.Color = 'Yellow'
            }
        }
        $allItems += $item
    }

    # --- UI & Menu ---
    $patchedEasyCount = ($allItems | Where-Object { $_.Type -eq 'Patched (Easy)' }).Count
    $patchedRiskyAddedCount = ($allItems | Where-Object { $_.Type -eq 'Patched (Risky-Added)' }).Count
    $patchedRiskyWrappedCount = ($allItems | Where-Object { $_.Type -eq 'Patched (Risky-Wrapped)' }).Count
    $unpatchedEasyCount = ($allItems | Where-Object { $_.Type -eq 'Unpatched (Easy)' }).Count
    $unpatchedRiskyCount = ($allItems | Where-Object { $_.Type -eq 'Unpatched (Risky)' }).Count

    Write-Host "  Scan Complete!"
    Write-Host "  - Patched (Easy):          $patchedEasyCount" -ForegroundColor Green
    Write-Host "  - Patched (Risky-Added):   $patchedRiskyAddedCount" -ForegroundColor Yellow
    Write-Host "  - Patched (Risky-Wrapped): $patchedRiskyWrappedCount" -ForegroundColor Cyan
    Write-Host "  - Unpatched (Easy):        $unpatchedEasyCount" -ForegroundColor Red
    Write-Host "  - Unpatched (Risky):       $unpatchedRiskyCount" -ForegroundColor Yellow
    Write-Host ""
    
    Write-Host "  OPTIONS:" -ForegroundColor Gray
    Write-Host "  1. Show All items"
    Write-Host "  2. Show Patched items"
    Write-Host "  3. Show Unpatched items"
    Write-Host "  4. Save log and Exit"
    $choice = Read-Host "  Enter Option#"

    switch ($choice) {
        '1' {
            Write-Header "All JSON.stringify Calls ($($allItems.Count))"
            $allItems | ForEach-Object { Write-Host "  [L:$($_.Line)|P:$($_.Position)] $($_.Text)" -ForegroundColor $_.Color }
            Read-Host "`n  Press Enter to return to menu"
        }
        '2' {
            Write-Header "Patched Calls ($($patchedEasyCount + $patchedRiskyAddedCount + $patchedRiskyWrappedCount))"
            ($allItems | Where-Object { $_.Type -like 'Patched*' }) | ForEach-Object { Write-Host "  [L:$($_.Line)|P:$($_.Position)] $($_.Text)" -ForegroundColor $_.Color }
            Read-Host "`n  Press Enter to return to menu"
        }
        '3' {
            Write-Header "Unpatched Calls ($unpatchedCount)"
            ($allItems | Where-Object { $_.Type -eq 'Unpatched' }) | ForEach-Object { Write-Host "  [L:$($_.Line)|P:$($_.Position)] $($_.Text)" -ForegroundColor $_.Color }
            Read-Host "`n  Press Enter to return to menu"
        }
'''        '4' {
            $logContent = @()
            $logContent += "Antigravity BigInt Scan Results"
            $logContent += "================================================="
            $logContent += "Scan Date: $(Get-Date)"
            $logContent += "Target File: $targetFile"
            $logContent += ""
            $logContent += "Summary:"
            $logContent += "- Patched (Easy):          $patchedEasyCount"
            $logContent += "- Patched (Risky-Added):   $patchedRiskyAddedCount"
            $logContent += "- Patched (Risky-Wrapped): $patchedRiskyWrappedCount"
            $logContent += "- Unpatched (Easy):        $unpatchedEasyCount"
            $logContent += "- Unpatched (Risky):       $unpatchedRiskyCount"
            $logContent += ""
            $logContent += "Details:"
            $logContent += "================================================="
            $allItems | ForEach-Object {
                $logContent += "[L:$($_.Line)|P:$($_.Position)] [$($_.Type)] - $($_.Text)"
            }
            $logContent | Set-Content -Path $logFile -Encoding UTF8
            Write-Host "`n  Log saved to $logFile" -ForegroundColor Green
            Start-Sleep 2
            exit
        }'''}
    }
}

bigint-unpatcher.ps1

# =====================================================================================
#  Antigravity BigInt Unpatcher for Windows
# =====================================================================================

$targetFile = Join-Path $env:LOCALAPPDATA 'Programs\Antigravity\resources\app\out\main.js'
$backupFile = "$targetFile.bak"
$patchedBackupFile = "$targetFile.patched.bak" # A backup of the patched file, if one exists
$easyPatchLogic = '(_k, v) => typeof v === "bigint" ? v.toString() : v'

# --- Regex for UNPATCHING ---
# This will find an easy patch and capture the single argument before it.
$easyUnpatchRegex = 'JSON\.stringify\(([^,]*?),\s*' + [regex]::escape($easyPatchLogic) + '\)'

# This will find a risky patch where we wrapped a replacer, and extract the original three parts.
$riskyWrappedUnpatchRegex = 'JSON\.stringify\((.*?),\s*\(_k, v\)\s*=>\s*{\s*let\s*_r\s*=\s*\((.*?)\)\(_k, v\);\s*return\s*typeof\s*_r\s*===\s*"bigint"\s*\?\s*_r\.toString\(\)\s*:\s*_r;\s*}(,.*?)?\)'

# This will find a risky patch where we ADDED a replacer to a complex single argument.
$riskyAddedUnpatchRegex = 'JSON\.stringify\(([\{\(\[].*?[\}\)\]]),\s*' + [regex]::escape($easyPatchLogic) + '\)'

# --- Utility Functions ---
function Write-Header($title) {
    Clear-Host
    Write-Host ""
    Write-Host "  ==============================================================" -ForegroundColor Cyan
    Write-Host "             $title" -ForegroundColor Cyan
    Write-Host "  ==============================================================" -ForegroundColor Cyan
    Write-Host ""
}

# --- Main Application Loop ---
if (-not (Test-Path $targetFile)) { Write-Header "Error"; Write-Host "  Antigravity main.js not found at $targetFile" -ForegroundColor Red; exit }

while ($true) {
    Write-Header "Windows BigInt Omni-Unpatcher"
    $content = Get-Content -Raw $targetFile

    # --- Analysis Phase ---
    $allRegex = 'JSON\.stringify\((?:[^()]|\([^()]*\))*\)'
    $allFoundMatches = [regex]::Matches($content, $allRegex)
    $allItems = @()
    $lineNumber = 1
    $currentPos = 0

    # This classification function must be IDENTICAL to the one in the patcher and checker.
    function Get-Classification {
        param($text)
        if ($text -notmatch '^JSON\.stringify\((.*)\)$') { return @{ Type = 'unknown' } }
        $argsContent = $Matches[1].Trim()
        if ($argsContent -match '[\{\(\[\]\}\,]') { return @{ Type = 'risky' } } else { return @{ Type = 'easy' } }
    }

    foreach ($m in $allFoundMatches) {
        $text = $m.Value
        $index = $m.Index
        $gap = $content.Substring($currentPos, $index - $currentPos)
        $lineNumber += ($gap -split "`n").Length - 1
        $currentPos = $index
        
        $item = [PSCustomObject]@{ Line = $lineNumber; Position = $index; Text = $text; Type = ''; Color = 'Gray' }

        if ($text -like '*(typeof _r ===*bigint*)*') { # Check for the most specific patch first (Risky-Wrapped)
            $item.Type = 'Patched (Risky-Wrapped)'; $item.Color = 'Cyan'
        } elseif ($text -like 'JSON.stringify(*, (_k, v) => typeof v === "bigint"*') { # Easy or Risky-Added
            $unpatchedVersion = $text -replace ',\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v', ''
            $classification = Get-Classification -text $unpatchedVersion
            if ($classification.Type -eq 'easy') {
                $item.Type = 'Patched (Easy)'; $item.Color = 'Green'
            } else {
                $item.Type = 'Patched (Risky-Added)'; $item.Color = 'Yellow'
            }
        } else { # Unpatched
            $classification = Get-Classification -text $text
            if ($classification.Type -eq 'easy') {
                $item.Type = 'Unpatched (Easy)'; $item.Color = 'Red'
            } else {
                $item.Type = 'Unpatched (Risky)'; $item.Color = 'Yellow'
            }
        }
        $allItems += $item
    }

    # --- Count Categories ---
    $patchedEasyCount = ($allItems | Where-Object { $_.Type -eq 'Patched (Easy)' }).Count
    $patchedRiskyAddedCount = ($allItems | Where-Object { $_.Type -eq 'Patched (Risky-Added)' }).Count
    $patchedRiskyWrappedCount = ($allItems | Where-Object { $_.Type -eq 'Patched (Risky-Wrapped)' }).Count
    $unpatchedEasyCount = ($allItems | Where-Object { $_.Type -eq 'Unpatched (Easy)' }).Count
    $unpatchedRiskyCount = ($allItems | Where-Object { $_.Type -eq 'Unpatched (Risky)' }).Count
    $totalPatchedCount = $patchedEasyCount + $patchedRiskyAddedCount + $patchedRiskyWrappedCount

    # --- UI & Menu ---
    Write-Host "  File Scan Results:"
    Write-Host "  - Patched (Easy):          $patchedEasyCount" -ForegroundColor Green
    Write-Host "  - Patched (Risky-Added):   $patchedRiskyAddedCount" -ForegroundColor Yellow
    Write-Host "  - Patched (Risky-Wrapped): $patchedRiskyWrappedCount" -ForegroundColor Cyan
    Write-Host "  - Unpatched (Easy):        $unpatchedEasyCount" -ForegroundColor Red
    Write-Host "  - Unpatched (Risky):       $unpatchedRiskyCount" -ForegroundColor Yellow
    Write-Host ""
    Write-Host "  OPTIONS:" -ForegroundColor Gray
    Write-Host "  1. Unpatch ALL ($totalPatchedCount found)"
    Write-Host "  2. Unpatch Easy only ($patchedEasyCount found)"
    Write-Host "  3. Unpatch Risky-Added only ($patchedRiskyAddedCount found)"
    Write-Host "  4. Unpatch Risky-Wrapped only ($patchedRiskyWrappedCount found)"
    Write-Host "  5. Restore from backup ($backupFile)"
    Write-Host "  6. Exit"
    $choice = Read-Host "  Enter Option#"

    switch ($choice) {
        '1' { # UNPATCH ALL
            if ($totalPatchedCount -eq 0) { Write-Host "  No patches to remove."; Start-Sleep 1; continue }
            Write-Host "  Unpatching all found patches..." -ForegroundColor Yellow
            if (-not (Test-Path $patchedBackupFile)) { Copy-Item $targetFile $patchedBackupFile -Force -Encoding UTF8 }

            $newContent = $content
            # Order matters: Go from most specific to least specific regex.
            $newContent = $newContent -replace $riskyWrappedUnpatchRegex, 'JSON.stringify($1, $2$3)' 
            $newContent = $newContent -replace $riskyAddedUnpatchRegex, 'JSON.stringify($1)'
            $newContent = $newContent -replace $easyUnpatchRegex, 'JSON.stringify($1)'

            Set-Content -Path $targetFile -Value $newContent -NoNewline -Encoding UTF8
            Write-Host "  Bulk Unpatch Applied!" -ForegroundColor Green; Start-Sleep 2
        }
        '2' { # UNPATCH EASY
            if ($patchedEasyCount -eq 0) { Write-Host "  No easy patches to remove."; Start-Sleep 1; continue }
            if (-not (Test-Path $patchedBackupFile)) { Copy-Item $targetFile $patchedBackupFile -Force -Encoding UTF8 }
            $newContent = $content -replace $easyUnpatchRegex, 'JSON.stringify($1)'
            Set-Content -Path $targetFile -Value $newContent -NoNewline -Encoding UTF8
            Write-Host "  Easy patches removed!" -ForegroundColor Green; Start-Sleep 2
        }
        '3' { # UNPATCH RISKY-ADDED
            if ($patchedRiskyAddedCount -eq 0) { Write-Host "  No risky-added patches to remove."; Start-Sleep 1; continue }
            if (-not (Test-Path $patchedBackupFile)) { Copy-Item $targetFile $patchedBackupFile -Force -Encoding UTF8 }
            $newContent = $content -replace $riskyAddedUnpatchRegex, 'JSON.stringify($1)'
            Set-Content -Path $targetFile -Value $newContent -NoNewline -Encoding UTF8
            Write-Host "  Risky-added patches removed!" -ForegroundColor Green; Start-Sleep 2
        }
        '4' { # UNPATCH RISKY-WRAPPED
            if ($patchedRiskyWrappedCount -eq 0) { Write-Host "  No risky-wrapped patches to remove."; Start-Sleep 1; continue }
            if (-not (Test-Path $patchedBackupFile)) { Copy-Item $targetFile $patchedBackupFile -Force -Encoding UTF8 }
            $newContent = $content -replace $riskyWrappedUnpatchRegex, 'JSON.stringify($1, $2$3)'
            Set-Content -Path $targetFile -Value $newContent -NoNewline -Encoding UTF8
            Write-Host "  Risky-wrapped patches removed!" -ForegroundColor Green; Start-Sleep 2
        }
        '5' { # RESTORE BACKUP
            if (Test-Path $backupFile) {
                Write-Host "  Restoring original file from $backupFile..." -ForegroundColor Yellow
                Copy-Item $backupFile $targetFile -Force
                (Get-Content $targetFile -Raw) | Set-Content -Path $targetFile -NoNewline -Encoding utf8 # Ensure encoding is correct after restore
                Write-Host "  Restore complete!" -ForegroundColor Green
            } else {
                Write-Host "  Backup file not found ($backupFile)." -ForegroundColor Red
            }
            Start-Sleep 2
        }
        '6' { exit }
    }
}

MacOS

ag-cleanup.sh

#!/bin/bash

# =====================================================================================
#  Antigravity Cleanup Utility for macOS
# =====================================================================================

# --- Config ---
TARGET_DIR="$HOME/Library/Application Support/Antigravity/app/out"

# --- Colors ---
CYAN='\033[0;36m'
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # No Color

# --- Main ---
clear
echo -e "${CYAN}Antigravity Cleanup Utility${NC}"
echo -e "This will remove backup files created by the patcher/unpatcher."
echo -e ""

if [ ! -d "$TARGET_DIR" ]; then
    echo -e "${RED}Target directory not found: $TARGET_DIR${NC}"
    exit 1
fi

BACKUP_FILE="$TARGET_DIR/main.js.bak"
PATCHED_BACKUP_FILE="$TARGET_DIR/main.js.patched.bak"

found=0

if [ -f "$BACKUP_FILE" ]; then
    echo -e "Found: $BACKUP_FILE"
    found=1
fi

if [ -f "$PATCHED_BACKUP_FILE" ]; then
    echo -e "Found: $PATCHED_BACKUP_FILE"
    found=1
fi

if [ $found -eq 0 ]; then
    echo -e "${GREEN}No backup files found to clean up.${NC}"
    exit 0
fi

echo -e ""
read -p "Proceed with deleting the file(s) listed above? (y/n): " choice

if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
    if [ -f "$BACKUP_FILE" ]; then
        rm "$BACKUP_FILE"
        echo -e "Deleted: $BACKUP_FILE"
    fi
    if [ -f "$PATCHED_BACKUP_FILE" ]; then
        rm "$PATCHED_BACKUP_FILE"
        echo -e "Deleted: $PATCHED_BACKUP_FILE"
    fi
    echo -e "\n${GREEN}Cleanup complete!${NC}"
else
    echo -e "\nCleanup cancelled."
fi

bigint-patcher.sh

#!/bin/bash

# =====================================================================================
#  Antigravity BigInt Patcher for macOS
# =====================================================================================

# --- Config ---
TARGET_FILE="$HOME/Library/Application Support/Antigravity/app/out/main.js"
BACKUP_FILE="${TARGET_FILE}.bak"
PATCHED_LOGIC='(_k, v) => typeof v === "bigint" ? v.toString() : v'

# --- Colors ---
CYAN='\033[0;36m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
GRAY='\033[0;90m'
NC='\033[0m' # No Color

# --- Utility Functions ---
write_header() {
    clear
    echo -e ""
    echo -e "${CYAN}  ==============================================================${NC}"
    echo -e "${CYAN}             $1${NC}"
    echo -e "${CYAN}  ==============================================================${NC}"
    echo -e ""
}

get_classification() {
    local text="$1"
    local args_content=$(echo "$text" | perl -nE 'say $1 if /^JSON\.stringify\((.*)\)$/')
    if echo "$args_content" | grep -q -P '[\{\(\[\]\}\,]'; then
        echo "risky"
    else
        echo "easy"
    fi
}

# --- Main Application Loop ---
if [[ ! -f "$TARGET_FILE" ]]; then
    write_header "Error"
    echo -e "  ${RED}Antigravity main.js not found at $TARGET_FILE${NC}"
    exit 1
fi

while true; do
    write_header "macOS BigInt Omni-Patcher"
    
    # --- Analysis Phase ---
    # Use Perl to get all matches and their starting positions.
    mapfile -t all_found_matches_with_pos < <(perl -0777 -nE 'while (/JSON\.stringify\((?:[^()]|\([^()]*\))*\)/g) { say $& . "@@" . (pos() - length($&)) }' "$TARGET_FILE")

    patched_easy_count=0
    patched_risky_added_count=0
    patched_risky_wrapped_count=0
    unpatched_easy_count=0
    unpatched_risky_count=0
    unpatched_easy_items=()
    unpatched_risky_items=()

    for item_with_pos in "${all_found_matches_with_pos[@]}"; do
        text="${item_with_pos%@@*}"
        match_pos="${item_with_pos#*@@}"

        if [[ "$text" == *"typeof _r ==="*"bigint"* ]]; then
            ((patched_risky_wrapped_count++))
        elif [[ "$text" == *"$PATCHED_LOGIC"* ]]; then
            unpatched_version=$(echo "$text" | perl -pe "s/,\s*\Q$PATCHED_LOGIC\E//g")
            classification=$(get_classification "$unpatched_version")
            if [[ "$classification" == "easy" ]]; then
                ((patched_easy_count++))
            else
                ((patched_risky_added_count++))
            fi
        else
            classification=$(get_classification "$text")
            if [[ "$classification" == "easy" ]]; then
                unpatched_easy_items+=("$match_pos@@$text")
                ((unpatched_easy_count++))
            else
                unpatched_risky_items+=("$match_pos@@$text")
                ((unpatched_risky_count++))
            fi
        fi
    done

    # --- UI & Menu ---
    echo -e "  ${GREEN}Scan Complete!${NC}"
    echo -e "  - ${GREEN}Patched (Easy):          $patched_easy_count${NC}"
    echo -e "  - ${YELLOW}Patched (Risky-Added):   $patched_risky_added_count${NC}"
    echo -e "  - ${CYAN}Patched (Risky-Wrapped): $patched_risky_wrapped_count${NC}"
    echo -e "  - ${RED}Unpatched (Easy):        $unpatched_easy_count${NC}"
    echo -e "  - ${YELLOW}Unpatched (Risky):       $unpatched_risky_count${NC}"
    echo -e ""
    
    echo -e "  ${GRAY}OPTIONS:${NC}"
    echo -e "  1. Bulk Patch all EASY ($unpatched_easy_count)"
    echo -e "  2. Bulk Patch all RISKY ($unpatched_risky_count)"
    echo -e "  3. Exit"
    echo -e ""
    read -p "  Enter Option#: " choice

    if [[ "$choice" == "3" ]]; then exit 0; fi

    if [[ ! -f "$BACKUP_FILE" ]]; then
        echo -e "  ${YELLOW}Creating backup of fresh install...${NC}"
        cp "$TARGET_FILE" "$BACKUP_FILE"
    fi

    current_content=$(<"$TARGET_FILE")

    if [[ "$choice" == "1" ]]; then
        if [[ $unpatched_easy_count -eq 0 ]]; then echo "  No easy patches available."; sleep 1; continue; fi
        echo -e "  ${YELLOW}Applying easy patches...${NC}"

        IFS=$ '\n' sorted_easy=($(sort -t '@' -k1 -nr <<<"${unpatched_easy_items[*]}"))
        unset IFS

        for item in "${sorted_easy[@]}"; do
            pos_to_patch="${item%@@*}"
            text_to_patch="${item#*@@}"
            args_content=$(echo "$text_to_patch" | perl -nE 'say $1 if /^JSON\.stringify\((.*)\)$/')
            replacement="JSON.stringify($args_content, $PATCHED_LOGIC)"
            current_content=$(perl -0777 -pe 'my ($pos, $old_len, $new) = @ARGV; substr($_, $pos, $old_len) = $new;' -- "$pos_to_patch" "${#text_to_patch}" "$replacement" <<< "$current_content")
        done
        echo -n "$current_content" > "$TARGET_FILE"
        echo -e "  ${GREEN}Easy Bulk Patch Applied!${NC}"; sleep 2
    fi

    if [[ "$choice" == "2" ]]; then
        if [[ $unpatched_risky_count -eq 0 ]]; then echo "  No risky patches available."; sleep 1; continue; fi

        pos_sum=0
        for item in "${unpatched_risky_items[@]}"; do
            pos="${item%@@*}"
            pos_sum=$(($pos_sum + $pos))
        done
        line_sum=$(($pos_sum / 1000)) 
        security_key="${line_sum}:${pos_sum}"

        echo -e ""
        echo -e "  ${YELLOW}DANGEROUS: To confirm this risky patch, type the following key and press Enter:${NC}"
        echo -e "  ${CYAN}$security_key${NC}"
        read -p "  Enter security key: " user_input

        if [[ "$user_input" != "$security_key" ]]; then echo -e "  ${RED}Incorrect key.${NC}"; sleep 2; continue; fi
        
        echo -e "  ${YELLOW}Applying risky patches...${NC}"
        
        IFS=$ '\n' sorted_risky=($(sort -t '@' -k1 -nr <<<"${unpatched_risky_items[*]}"))
        unset IFS
        
        for item in "${sorted_risky[@]}"; do
            pos_to_patch="${item%@@*}"
            text_to_patch="${item#*@@}"
            args_content=$(echo "$text_to_patch" | perl -nE 'say $1 if /^JSON\.stringify\((.*)\)$/')
            
            is_single_arg="true"
            if echo "$args_content" | grep -q -P '[\{\(\[\]\}]\s*,.+'; then
                is_single_arg="false"
            fi
            
            replacement=""
            if [[ "$is_single_arg" == "true" ]]; then
                replacement="JSON.stringify($args_content, $PATCHED_LOGIC)"
            else
                replacement=$(perl -e '
                    my $args = shift;
                    my $patched_logic = q('"$PATCHED_LOGIC"');
                    my ($depth, $in_string, $first_comm-index) = (0, 0, -1);
                    my ($string_char, $is_escaped) = ("", 0);
                    my @chars = split //, $args;
                    for (my $i=0; $i < @chars; $i++) {
                        my $char = $chars[$i];
                        if ($is_escaped) { $is_escaped = 0; next; }
                        if ($char eq "\\") { $is_escaped = 1; next; }
                        if ($char eq "\'" or $char eq "\"" or $char eq "`") {
                            if ($in_string and $char eq $string_char) { $in_string = 0; } elsif (not $in_string) { $in_string = 1; $string_char = $char; }
                        }
                        if ($in_string) { next; }
                        if ($char eq "(" or $char eq "{" or $char eq "[") { $depth++; }
                        elsif ($char eq ")" or $char eq "}" or $char eq "]") { $depth--; }
                        if ($char eq "," and $depth == 0) { $first_comm-index = $i; last; }
                    }

                    if ($first_comm-index != -1) {
                        my $arg1 = substr($args, 0, $first_comm-index);
                        my $rest = substr($args, $first_comm-index + 1);
                        $arg1 =~ s/^\s+|\s+$//g;
                        $rest =~ s/^\s+|\s+$//g;
                        my $replacer = $rest;
                        my $rest_of_args = "";
                        ($depth, $in_string, $string_char, $is_escaped) = (0, 0, "", 0);
                        my $second_comm-index = -1;
                        @chars = split //, $rest;
                        for (my $i=0; $i < @chars; $i++) {
                             my $char = $chars[$i];
                             if ($is_escaped) { $is_escaped = 0; next; }
                             if ($char eq "\\") { $is_escaped = 1; next; }
                             if ($char eq "\'" or $char eq "\"" or $char eq "`") {
                                if ($in_string and $char eq $string_char) { $in_string = 0; } elsif (not $in_string) { $in_string = 1; $string_char = $char; }
                             }
                             if ($in_string) { continue; }
                             if ($char eq "(" or $char eq "{" or $char eq "[") { $depth++; }
                             elseif ($char eq ")" or $char eq "}" or $char eq "]") { $depth--; }
                             if ($char eq "," and $depth == 0) { $second_comm-index = $i; last; }
                        }

                        if ($second_comm-index != -1) {
                            $replacer = substr($rest, 0, $second_comm-index);
                            $replacer =~ s/^\s+|\s+$//g;
                            $rest_of_args = substr($rest, $second_comm-index);
                        }

                        my $wrapped_replacer = "(_k, v) => { let _r = ($replacer)(_k, v); return typeof _r === `bigint` ? _r.toString() : _r; }";
                        print "JSON.stringify($arg1, $wrapped_replacer$rest_of_args)";
                    } else {
                        print "JSON.stringify($args, $patched_logic)";
                    }
                ' "$args_content")
            fi
            current_content=$(perl -0777 -pe 'my ($pos, $old_len, $new) = @ARGV; substr($_, $pos, $old_len) = $new;' -- "$pos_to_patch" "${#text_to_patch}" "$replacement" <<< "$current_content")
        done

        echo -n "$current_content" > "$TARGET_FILE"
        echo -e "  ${GREEN}Risky Bulk Patch Applied!${NC}"; sleep 2
    fi
done

bigint-checker.sh

#!/bin/bash

# =====================================================================================
#  Antigravity BigInt Checker for macOS
# =====================================================================================

# --- Config ---
TARGET_FILE="$HOME/Library/Application Support/Antigravity/app/out/main.js"
LOG_FILE="$(dirname "$0")/bigint-scan.log"

# --- Colors ---
CYAN='\033[0;36m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
GRAY='\033[0;90m'
NC='\033[0m' # No Color

# --- Utility Functions ---
write_header() {
    clear
    echo -e ""
    echo -e "${CYAN}  ==============================================================${NC}"
    echo -e "${CYAN}             $1${NC}"
    echo -e "${CYAN}  ==============================================================${NC}"
    echo -e ""
}

# This is the core classification logic, translated from PowerShell.
# It uses perl for robust regex matching.
get_classification() {
    local text="$1"
    # Extract arguments from JSON.stringify(arguments)
    local args_content=$(echo "$text" | perl -nE 'say $1 if /^JSON\.stringify\((.*)\)$/')

    # Check if arguments contain characters that make it complex (risky)
    if echo "$args_content" | grep -q -P '[\{\(\[\]\}\,]'; then
        echo "risky"
    else
        echo "easy"
    fi
}

# --- Main Application Loop ---
if [[ ! -f "$TARGET_FILE" ]]; then
    write_header "Error"
    echo -e "  ${RED}Antigravity main.js not found at $TARGET_FILE${NC}"
    exit 1
fi

while true; do
    write_header "macOS BigInt Checker"
    
    # --- Analysis Phase ---
    # Use perl to find all instances of JSON.stringify(...), handling nested parentheses.
    mapfile -t all_found_matches < <(perl -0777 -nE 'say for /JSON\.stringify\((?:[^()]|\([^()]*\))*\)/g' "$TARGET_FILE")

    # Process matches to classify them
    all_items=()
    patched_easy_count=0
    patched_risky_added_count=0
    patched_risky_wrapped_count=0
    unpatched_easy_count=0
    unpatched_risky_count=0

    for text in "${all_found_matches[@]}"; do
        item_type=""
        item_color="$GRAY"

        if [[ "$text" == *"typeof _r ==="*"bigint"* ]]; then
            item_type="Patched (Risky-Wrapped)"
            item_color="$CYAN"
            ((patched_risky_wrapped_count++))
        elif [[ "$text" == *"(_k, v) => typeof v === \"bigint\""* ]]; then
            unpatched_version=$(echo "$text" | perl -pe 's/,\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v//g')
            classification=$(get_classification "$unpatched_version")
            if [[ "$classification" == "easy" ]]; then
                item_type="Patched (Easy)"
                item_color="$GREEN"
                ((patched_easy_count++))
            else
                item_type="Patched (Risky-Added)"
                item_color="$YELLOW"
                ((patched_risky_added_count++))
            fi
        else
            classification=$(get_classification "$text")
            if [[ "$classification" == "easy" ]]; then
                item_type="Unpatched (Easy)"
                item_color="$RED"
                ((unpatched_easy_count++))
            else
                item_type="Unpatched (Risky)"
                item_color="$YELLOW"
                ((unpatched_risky_count++))
            fi
        fi
        all_items+=("$(echo -e "${item_color}${text}${NC}")___${item_type}") # Store with color and type
    done

    # --- UI & Menu ---
    echo -e "  ${GREEN}Scan Complete!${NC}"
    echo -e "  - ${GREEN}Patched (Easy):          $patched_easy_count${NC}"
    echo -e "  - ${YELLOW}Patched (Risky-Added):   $patched_risky_added_count${NC}"
    echo -e "  - ${CYAN}Patched (Risky-Wrapped): $patched_risky_wrapped_count${NC}"
    echo -e "  - ${RED}Unpatched (Easy):        $unpatched_easy_count${NC}"
    echo -e "  - ${YELLOW}Unpatched (Risky):       $unpatched_risky_count${NC}"
    echo -e ""
    
    echo -e "  ${GRAY}OPTIONS:${NC}"
    echo -e "  1. Show All items"
    echo -e "  2. Show Patched items"
    echo -e "  3. Show Unpatched items"
    echo -e "  4. Save log and Exit"
    read -p "  Enter Option#: " choice

    case "$choice" in
        1)
            write_header "All JSON.stringify Calls (${#all_items[@]})"
            for item in "${all_items[@]}"; do
                text_part=$(echo "$item" | cut -d'_' -f1)
                echo -e "  $text_part"
            done
            read -p $ '\n  Press Enter to return to menu'
            ;;
        2)
            total_patched=$(($patched_easy_count + $patched_risky_added_count + $patched_risky_wrapped_count))
            write_header "Patched Calls ($total_patched)"
            for item in "${all_items[@]}"; do
                type_part=$(echo "$item" | cut -d'_' -f4)
                if [[ "$type_part" == Patched* ]]; then
                     text_part=$(echo "$item" | cut -d'_' -f1)
                     echo -e "  $text_part"
                fi
            done
            read -p $'\n  Press Enter to return to menu'
            ;;
        3)
            total_unpatched=$(($unpatched_easy_count + $unpatched_risky_count))
            write_header "Unpatched Calls ($total_unpatched)"
            for item in "${all_items[@]}"; do
                type_part=$(echo "$item" | cut -d'_' -f4)
                if [[ "$type_part" == Unpatched* ]]; then
                     text_part=$(echo "$item" | cut -d'_' -f1)
                     echo -e "  $text_part"
                fi
            done
            read -p $'\n  Press Enter to return to menu'
            ;;
        4)
            echo "Antigravity BigInt Scan Results" > "$LOG_FILE"
            echo "=================================================" >> "$LOG_FILE"
            echo "Scan Date: $(date)" >> "$LOG_FILE"
            echo "Target File: $TARGET_FILE" >> "$LOG_FILE"
            echo "" >> "$LOG_FILE"
            echo "Summary:" >> "$LOG_FILE"
            echo "- Patched (Easy):          $patched_easy_count" >> "$LOG_FILE"
            echo "- Patched (Risky-Added):   $patched_risky_added_count" >> "$LOG_FILE"
            echo "- Patched (Risky-Wrapped): $patched_risky_wrapped_count" >> "$LOG_FILE"
            echo "- Unpatched (Easy):        $unpatched_easy_count" >> "$LOG_FILE"
            echo "- Unpatched (Risky):       $unpatched_risky_count" >> "$LOG_FILE"
            echo "" >> "$LOG_FILE"
            echo "Details:" >> "$LOG_FILE"
            echo "=================================================" >> "$LOG_FILE"
            for item in "${all_items[@]}"; do
                text_part=$(echo "$item" | perl -pe 's/\x1b\[[0-9;]*[mG]//g' | cut -d'_' -f1)
                type_part=$(echo "$item" | cut -d'_' -f4)
                 echo "[$type_part] - $text_part" >> "$LOG_FILE"
            done
            echo -e "\n  ${GREEN}Log saved to $LOG_FILE${NC}"
            sleep 2
            exit 0
            ;;
    esac
done

bigint-unpatcher.sh

#!/bin/bash

# =====================================================================================
#  Antigravity BigInt Unpatcher for macOS
# =====================================================================================

# --- Config ---
TARGET_FILE="$HOME/Library/Application Support/Antigravity/app/out/main.js"
BACKUP_FILE="${TARGET_FILE}.bak"
PATCHED_BACKUP_FILE="${TARGET_FILE}.patched.bak"

# --- Regex for UNPATCHING ---
# These are perl-compatible regexes used for substitutions.
EASY_UNPATCH_REGEX='s/JSON\.stringify\(([^,]*?),\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v\)/JSON.stringify($1)/g'
RISKY_WRAPPED_UNPATCH_REGEX='s/JSON\.stringify\((.*?),\s*\(_k, v\)\s*=>\s*{\s*let\s*_r\s*=\s*\((.*?)\)\(_k, v\);\s*return\s*typeof\s*_r\s*===\s*"bigint"\s*\?\s*_r\.toString\(\)\s*:\s*_r;\s*}(,.*?)?\)/JSON.stringify($1, $2$3)/g'
RISKY_ADDED_UNPATCH_REGEX='s/JSON\.stringify\(([\{\(\[].*?[\}\)\]]),\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v\)/JSON.stringify($1)/g'

# --- Colors ---
CYAN='\033[0;36m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
GRAY='\033[0;90m'
NC='\033[0m' # No Color

# --- Utility Functions ---
write_header() {
    clear
    echo -e ""
    echo -e "${CYAN}  ==============================================================${NC}"
    echo -e "${CYAN}             $1${NC}"
    echo -e "${CYAN}  ==============================================================${NC}"
    echo -e ""
}

get_classification() {
    local text="$1"
    local args_content=$(echo "$text" | perl -nE 'say $1 if /^JSON\.stringify\((.*)\)$/')
    if echo "$args_content" | grep -q -P '[\{\(\[\]\}\,]'; then
        echo "risky"
    else
        echo "easy"
    fi
}

# --- Main Application Loop ---
if [[ ! -f "$TARGET_FILE" ]]; then
    write_header "Error"
    echo -e "  ${RED}Antigravity main.js not found at $TARGET_FILE${NC}"
    exit 1
fi

while true; do
    write_header "macOS BigInt Omni-Unpatcher"
    
    # --- Analysis Phase ---
    mapfile -t all_found_matches < <(perl -0777 -nE 'say for /JSON\.stringify\((?:[^()]|\([^()]*\))*\)/g' "$TARGET_FILE")

    patched_easy_count=0
    patched_risky_added_count=0
    patched_risky_wrapped_count=0
    unpatched_easy_count=0
    unpatched_risky_count=0

    for text in "${all_found_matches[@]}"; do
        if [[ "$text" == *"typeof _r ==="*"bigint"* ]]; then
            ((patched_risky_wrapped_count++))
        elif [[ "$text" == *"(_k, v) => typeof v === \"bigint\""* ]]; then
            unpatched_version=$(echo "$text" | perl -pe 's/,\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v//g')
            classification=$(get_classification "$unpatched_version")
            if [[ "$classification" == "easy" ]]; then
                ((patched_easy_count++))
            else
                ((patched_risky_added_count++))
            fi
        else
            classification=$(get_classification "$text")
            if [[ "$classification" == "easy" ]]; then
                ((unpatched_easy_count++))
            else
                ((unpatched_risky_count++))
            fi
        fi
    done

    total_patched_count=$(($patched_easy_count + $patched_risky_added_count + $patched_risky_wrapped_count))

    # --- UI & Menu ---
    echo -e "  ${GREEN}File Scan Results:${NC}"
    echo -e "  - ${GREEN}Patched (Easy):          $patched_easy_count${NC}"
    echo -e "  - ${YELLOW}Patched (Risky-Added):   $patched_risky_added_count${NC}"
    echo -e "  - ${CYAN}Patched (Risky-Wrapped): $patched_risky_wrapped_count${NC}"
    echo -e "  - ${RED}Unpatched (Easy):        $unpatched_easy_count${NC}"
    echo -e "  - ${YELLOW}Unpatched (Risky):       $unpatched_risky_count${NC}"
    echo -e ""
    
    echo -e "  ${GRAY}OPTIONS:${NC}"
    echo -e "  1. Unpatch ALL ($total_patched_count found)"
    echo -e "  2. Unpatch Easy only ($patched_easy_count found)"
    echo -e "  3. Unpatch Risky-Added only ($patched_risky_added_count found)"
    echo -e "  4. Unpatch Risky-Wrapped only ($patched_risky_wrapped_count found)"
    echo -e "  5. Restore from backup ($BACKUP_FILE)"
    echo -e "  6. Exit"
    read -p "  Enter Option#: " choice

    case "$choice" in
        1) # UNPATCH ALL
            if [[ $total_patched_count -eq 0 ]]; then echo "  No patches to remove."; sleep 1; continue; fi
            echo -e "  ${YELLOW}Unpatching all found patches...${NC}"
            if [[ ! -f "$PATCHED_BACKUP_FILE" ]]; then cp "$TARGET_FILE" "$PATCHED_BACKUP_FILE"; fi
            
            # Use perl for in-place editing for safety and power.
            perl -i -0777pe "$RISKY_WRAPPED_UNPATCH_REGEX" "$TARGET_FILE"
            perl -i -0777pe "$RISKY_ADDED_UNPATCH_REGEX" "$TARGET_FILE"
            perl -i -0777pe "$EASY_UNPATCH_REGEX" "$TARGET_FILE"
            
            echo -e "  ${GREEN}Bulk Unpatch Applied!${NC}"; sleep 2
            ;;
        2) # UNPATCH EASY
            if [[ $patched_easy_count -eq 0 ]]; then echo "  No easy patches to remove."; sleep 1; continue; fi
            if [[ ! -f "$PATCHED_BACKUP_FILE" ]]; then cp "$TARGET_FILE" "$PATCHED_BACKUP_FILE"; fi
            perl -i -0777pe "$EASY_UNPATCH_REGEX" "$TARGET_FILE"
            echo -e "  ${GREEN}Easy patches removed!${NC}"; sleep 2
            ;;
        3) # UNPATCH RISKY-ADDED
            if [[ $patched_risky_added_count -eq 0 ]]; then echo "  No risky-added patches to remove."; sleep 1; continue; fi
            if [[ ! -f "$PATCHED_BACKUP_FILE" ]]; then cp "$TARGET_FILE" "$PATCHED_BACKUP_FILE"; fi
            perl -i -0777pe "$RISKY_ADDED_UNPATCH_REGEX" "$TARGET_FILE"
            echo -e "  ${GREEN}Risky-added patches removed!${NC}"; sleep 2
            ;;
        4) # UNPATCH RISKY-WRAPPED
            if [[ $patched_risky_wrapped_count -eq 0 ]]; then echo "  No risky-wrapped patches to remove."; sleep 1; continue; fi
            if [[ ! -f "$PATCHED_BACKUP_FILE" ]]; then cp "$TARGET_FILE" "$PATCHED_BACKUP_FILE"; fi
            perl -i -0777pe "$RISKY_WRAPPED_UNPATCH_REGEX" "$TARGET_FILE"
            echo -e "  ${GREEN}Risky-wrapped patches removed!${NC}"; sleep 2
            ;;
        5) # RESTORE BACKUP
            if [[ -f "$BACKUP_FILE" ]]; then
                echo -e "  ${YELLOW}Restoring original file from $BACKUP_FILE...${NC}"
                cp "$BACKUP_FILE" "$TARGET_FILE"
                echo -e "  ${GREEN}Restore complete!${NC}"
            else
                echo -e "  ${RED}Backup file not found ($BACKUP_FILE).${NC}"
            fi
            sleep 2
            ;;
        6) exit 0 ;;
    esac
done

Linux

ag-cleanup.sh

#!/bin/bash

# =====================================================================================
#  Antigravity Cleanup Utility for Linux
# =====================================================================================

# --- Config ---
TARGET_DIR="$HOME/.config/Antigravity/app/out"

# --- Colors ---
CYAN='\033[0;36m'
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # No Color

# --- Main ---
clear
echo -e "${CYAN}Antigravity Cleanup Utility${NC}"
echo -e "This will remove backup files created by the patcher/unpatcher."
echo -e ""

if [ ! -d "$TARGET_DIR" ]; then
    # Fallback for snap installs
    TARGET_DIR="$HOME/snap/antigravity/current/.config/Antigravity/app/out"
     if [ ! -d "$TARGET_DIR" ]; then
        echo -e "${RED}Target directory not found.${NC}"
        exit 1
    fi
fi

BACKUP_FILE="$TARGET_DIR/main.js.bak"
PATCHED_BACKUP_FILE="$TARGET_DIR/main.js.patched.bak"

found=0

if [ -f "$BACKUP_FILE" ]; then
    echo -e "Found: $BACKUP_FILE"
    found=1
fi

if [ -f "$PATCHED_BACKUP_FILE" ]; then
    echo -e "Found: $PATCHED_BACKUP_FILE"
    found=1
fi

if [ $found -eq 0 ]; then
    echo -e "${GREEN}No backup files found to clean up.${NC}"
    exit 0
fi

echo -e ""
read -p "Proceed with deleting the file(s) listed above? (y/n): " choice

if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
    if [ -f "$BACKUP_FILE" ]; then
        rm "$BACKUP_FILE"
        echo -e "Deleted: $BACKUP_FILE"
    fi
    if [ -f "$PATCHED_BACKUP_FILE" ]; then
        rm "$PATCHED_BACKUP_FILE"
        echo -e "Deleted: $PATCHED_BACKUP_FILE"
    fi
    echo -e "\n${GREEN}Cleanup complete!${NC}"
else
    echo -e "\nCleanup cancelled."
fi

bigint-patcher.sh

#!/bin/bash

# =====================================================================================
#  Antigravity BigInt Patcher for Linux
# =====================================================================================

# --- Config ---
TARGET_FILE="$HOME/.config/Antigravity/app/out/main.js"
BACKUP_FILE="${TARGET_FILE}.bak"
PATCHED_LOGIC='(_k, v) => typeof v === "bigint" ? v.toString() : v'

# --- Colors ---
CYAN='\033[0;36m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
GRAY='\033[0;90m'
NC='\033[0m' # No Color

# --- Utility Functions ---
write_header() {
    clear
    echo -e ""
    echo -e "${CYAN}  ==============================================================${NC}"
    echo -e "${CYAN}             $1${NC}"
    echo -e "${CYAN}  ==============================================================${NC}"
    echo -e ""
}

get_classification() {
    local text="$1"
    local args_content=$(echo "$text" | perl -nE 'say $1 if /^JSON\.stringify\((.*)\)$/')
    if echo "$args_content" | grep -q -P '[\{\(\[\]\}\,]'; then
        echo "risky"
    else
        echo "easy"
    fi
}

# --- Main Application Loop ---
if [[ ! -f "$TARGET_FILE" ]]; then
    # Fallback for some distributions that might use a different path
    TARGET_FILE="$HOME/snap/antigravity/current/.config/Antigravity/app/out/main.js"
    if [[ ! -f "$TARGET_FILE" ]]; then
        write_header "Error"
        echo -e "  ${RED}Antigravity main.js not found.${NC}"
        echo -e "  Checked standard paths. If you have a custom installation, please update the TARGET_FILE variable in this script."
        exit 1
    fi
fi

while true; do
    write_header "Linux BigInt Omni-Patcher"
    
    # --- Analysis Phase ---
    # Use Perl to get all matches and their starting positions.
    mapfile -t all_found_matches_with_pos < <(perl -0777 -nE 'while (/JSON\.stringify\((?:[^()]|\([^()]*\))*\)/g) { say $& . "@@" . (pos() - length($&)) }' "$TARGET_FILE")

    patched_easy_count=0
    patched_risky_added_count=0
    patched_risky_wrapped_count=0
    unpatched_easy_count=0
    unpatched_risky_count=0
    unpatched_easy_items=()
    unpatched_risky_items=()

    for item_with_pos in "${all_found_matches_with_pos[@]}"; do
        text="${item_with_pos%@@*}"
        match_pos="${item_with_pos#*@@}"

        if [[ "$text" == *"typeof _r ==="*"bigint"* ]]; then
            ((patched_risky_wrapped_count++))
        elif [[ "$text" == *"$PATCHED_LOGIC"* ]]; then
            unpatched_version=$(echo "$text" | perl -pe "s/,\s*\Q$PATCHED_LOGIC\E//g")
            classification=$(get_classification "$unpatched_version")
            if [[ "$classification" == "easy" ]]; then
                ((patched_easy_count++))
            else
                ((patched_risky_added_count++))
            fi
        else
            classification=$(get_classification "$text")
            if [[ "$classification" == "easy" ]]; then
                unpatched_easy_items+=("$match_pos@@$text")
                ((unpatched_easy_count++))
            else
                unpatched_risky_items+=("$match_pos@@$text")
                ((unpatched_risky_count++))
            fi
        fi
    done

    # --- UI & Menu ---
    echo -e "  ${GREEN}Scan Complete!${NC}"
    echo -e "  - ${GREEN}Patched (Easy):          $patched_easy_count${NC}"
    echo -e "  - ${YELLOW}Patched (Risky-Added):   $patched_risky_added_count${NC}"
    echo -e "  - ${CYAN}Patched (Risky-Wrapped): $patched_risky_wrapped_count${NC}"
    echo -e "  - ${RED}Unpatched (Easy):        $unpatched_easy_count${NC}"
    echo -e "  - ${YELLOW}Unpatched (Risky):       $unpatched_risky_count${NC}"
    echo -e ""
    
    echo -e "  ${GRAY}OPTIONS:${NC}"
    echo -e "  1. Bulk Patch all EASY ($unpatched_easy_count)"
    echo -e "  2. Bulk Patch all RISKY ($unpatched_risky_count)"
    echo -e "  3. Exit"
    echo -e ""
    read -p "  Enter Option#: " choice

    if [[ "$choice" == "3" ]]; then exit 0; fi

    if [[ ! -f "$BACKUP_FILE" ]]; then
        echo -e "  ${YELLOW}Creating backup of fresh install...${NC}"
        cp "$TARGET_FILE" "$BACKUP_FILE"
    fi

    current_content=$(<"$TARGET_FILE")

    if [[ "$choice" == "1" ]]; then
        if [[ $unpatched_easy_count -eq 0 ]]; then echo "  No easy patches available."; sleep 1; continue; fi
        echo -e "  ${YELLOW}Applying easy patches...${NC}"

        IFS=$ '\n' sorted_easy=($(sort -t '@' -k1 -nr <<<"${unpatched_easy_items[*]}"))
        unset IFS

        for item in "${sorted_easy[@]}"; do
            pos_to_patch="${item%@@*}"
            text_to_patch="${item#*@@}"
            args_content=$(echo "$text_to_patch" | perl -nE 'say $1 if /^JSON\.stringify\((.*)\)$/')
            replacement="JSON.stringify($args_content, $PATCHED_LOGIC)"
            current_content=$(perl -0777 -pe 'my ($pos, $old_len, $new) = @ARGV; substr($_, $pos, $old_len) = $new;' -- "$pos_to_patch" "${#text_to_patch}" "$replacement" <<< "$current_content")
        done
        echo -n "$current_content" > "$TARGET_FILE"
        echo -e "  ${GREEN}Easy Bulk Patch Applied!${NC}"; sleep 2
    fi

    if [[ "$choice" == "2" ]]; then
        if [[ $unpatched_risky_count -eq 0 ]]; then echo "  No risky patches available."; sleep 1; continue; fi

        pos_sum=0
        for item in "${unpatched_risky_items[@]}"; do
            pos="${item%@@*}"
            pos_sum=$(($pos_sum + $pos))
        done
        line_sum=$(($pos_sum / 1000)) 
        security_key="${line_sum}:${pos_sum}"

        echo -e ""
        echo -e "  ${YELLOW}DANGEROUS: To confirm this risky patch, type the following key and press Enter:${NC}"
        echo -e "  ${CYAN}$security_key${NC}"
        read -p "  Enter security key: " user_input

        if [[ "$user_input" != "$security_key" ]]; then echo -e "  ${RED}Incorrect key.${NC}"; sleep 2; continue; fi
        
        echo -e "  ${YELLOW}Applying risky patches...${NC}"
        
        IFS=$ '\n' sorted_risky=($(sort -t '@' -k1 -nr <<<"${unpatched_risky_items[*]}"))
        unset IFS
        
        for item in "${sorted_risky[@]}"; do
            pos_to_patch="${item%@@*}"
            text_to_patch="${item#*@@}"
            args_content=$(echo "$text_to_patch" | perl -nE 'say $1 if /^JSON\.stringify\((.*)\)$/')
            
            is_single_arg="true"
            if echo "$args_content" | grep -q -P '[\{\(\[\]\}]\s*,.+'; then
                is_single_arg="false"
            fi
            
            replacement=""
            if [[ "$is_single_arg" == "true" ]]; then
                replacement="JSON.stringify($args_content, $PATCHED_LOGIC)"
            else
                replacement=$(perl -e '
                    my $args = shift;
                    my $patched_logic = q('"$PATCHED_LOGIC"');
                    my ($depth, $in_string, $first_comm-index) = (0, 0, -1);
                    my ($string_char, $is_escaped) = ("", 0);
                    my @chars = split //, $args;
                    for (my $i=0; $i < @chars; $i++) {
                        my $char = $chars[$i];
                        if ($is_escaped) { $is_escaped = 0; next; }
                        if ($char eq "\\") { $is_escaped = 1; next; }
                        if ($char eq "\'" or $char eq "\"" or $char eq "`") {
                            if ($in_string and $char eq $string_char) { $in_string = 0; } elsif (not $in_string) { $in_string = 1; $string_char = $char; }
                        }
                        if ($in_string) { next; }
                        if ($char eq "(" or $char eq "{" or $char eq "[") { $depth++; }
                        elsif ($char eq ")" or $char eq "}" or $char eq "]") { $depth--; }
                        if ($char eq "," and $depth == 0) { $first_comm-index = $i; last; }
                    }

                    if ($first_comm-index != -1) {
                        my $arg1 = substr($args, 0, $first_comm-index);
                        my $rest = substr($args, $first_comm-index + 1);
                        $arg1 =~ s/^\s+|\s+$//g;
                        $rest =~ s/^\s+|\s+$//g;
                        my $replacer = $rest;
                        my $rest_of_args = "";
                        ($depth, $in_string, $string_char, $is_escaped) = (0, 0, "", 0);
                        my $second_comm-index = -1;
                        @chars = split //, $rest;
                        for (my $i=0; $i < @chars; $i++) {
                             my $char = $chars[$i];
                             if ($is_escaped) { $is_escaped = 0; next; }
                             if ($char eq "\\") { $is_escaped = 1; next; }
                             if ($char eq "\'" or $char eq "\"" or $char eq "`") {
                                if ($in_string and $char eq $string_char) { $in_string = 0; } elsif (not $in_string) { $in_string = 1; $string_char = $char; }
                             }
                             if ($in_string) { continue; }
                             if ($char eq "(" or $char eq "{" or $char eq "[") { $depth++; }
                             elseif ($char eq ")" or $char eq "}" or $char eq "]") { $depth--; }
                             if ($char eq "," and $depth == 0) { $second_comm-index = $i; last; }
                        }

                        if ($second_comm-index != -1) {
                            $replacer = substr($rest, 0, $second_comm-index);
                            $replacer =~ s/^\s+|\s+$//g;
                            $rest_of_args = substr($rest, $second_comm-index);
                        }

                        my $wrapped_replacer = "(_k, v) => { let _r = ($replacer)(_k, v); return typeof _r === `bigint` ? _r.toString() : _r; }";
                        print "JSON.stringify($arg1, $wrapped_replacer$rest_of_args)";
                    } else {
                        print "JSON.stringify($args, $patched_logic)";
                    }
                ' "$args_content")
            fi
            current_content=$(perl -0777 -pe 'my ($pos, $old_len, $new) = @ARGV; substr($_, $pos, $old_len) = $new;' -- "$pos_to_patch" "${#text_to_patch}" "$replacement" <<< "$current_content")
        done

        echo -n "$current_content" > "$TARGET_FILE"
        echo -e "  ${GREEN}Risky Bulk Patch Applied!${NC}"; sleep 2
    fi
done

bigint-checker.sh

#!/bin/bash

# =====================================================================================
#  Antigravity BigInt Checker for Linux
# =====================================================================================

# --- Config ---
# The standard path for Electron apps on Linux.
TARGET_FILE="$HOME/.config/Antigravity/app/out/main.js"
LOG_FILE="$(dirname "$0")/bigint-scan.log"

# --- Colors ---
CYAN='\033[0;36m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
GRAY='\033[0;90m'
NC='\033[0m' # No Color

# --- Utility Functions ---
write_header() {
    clear
    echo -e ""
    echo -e "${CYAN}  ==============================================================${NC}"
    echo -e "${CYAN}             $1${NC}"
    echo -e "${CYAN}  ==============================================================${NC}"
    echo -e ""
}

# This is the core classification logic, translated from PowerShell.
# It uses perl for robust regex matching.
get_classification() {
    local text="$1"
    # Extract arguments from JSON.stringify(arguments)
    local args_content=$(echo "$text" | perl -nE 'say $1 if /^JSON\.stringify\((.*)\)$/')

    # Check if arguments contain characters that make it complex (risky)
    if echo "$args_content" | grep -q -P '[\{\(\[\]\}\,]'; then
        echo "risky"
    else
        echo "easy"
    fi
}

# --- Main Application Loop ---
if [[ ! -f "$TARGET_FILE" ]]; then
    # Fallback for some distributions that might use a different path
    TARGET_FILE="$HOME/snap/antigravity/current/.config/Antigravity/app/out/main.js"
    if [[ ! -f "$TARGET_FILE" ]]; then
        write_header "Error"
        echo -e "  ${RED}Antigravity main.js not found.${NC}"
        echo -e "  Checked standard paths. If you have a custom installation, please update the TARGET_FILE variable in this script."
        exit 1
    fi
fi

while true; do
    write_header "Linux BigInt Checker"
    
    # --- Analysis Phase ---
    # Use perl to find all instances of JSON.stringify(...), handling nested parentheses.
    mapfile -t all_found_matches < <(perl -0777 -nE 'say for /JSON\.stringify\((?:[^()]|\([^()]*\))*\)/g' "$TARGET_FILE")

    # Process matches to classify them
    all_items=()
    patched_easy_count=0
    patched_risky_added_count=0
    patched_risky_wrapped_count=0
    unpatched_easy_count=0
    unpatched_risky_count=0

    for text in "${all_found_matches[@]}"; do
        item_type=""
        item_color="$GRAY"

        if [[ "$text" == *"typeof _r ==="*"bigint"* ]]; then
            item_type="Patched (Risky-Wrapped)"
            item_color="$CYAN"
            ((patched_risky_wrapped_count++))
        elif [[ "$text" == *"(_k, v) => typeof v === \"bigint\""* ]]; then
            unpatched_version=$(echo "$text" | perl -pe 's/,\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v//g')
            classification=$(get_classification "$unpatched_version")
            if [[ "$classification" == "easy" ]]; then
                item_type="Patched (Easy)"
                item_color="$GREEN"
                ((patched_easy_count++))
            else
                item_type="Patched (Risky-Added)"
                item_color="$YELLOW"
                ((patched_risky_added_count++))
            fi
        else
            classification=$(get_classification "$text")
            if [[ "$classification" == "easy" ]]; then
                item_type="Unpatched (Easy)"
                item_color="$RED"
                ((unpatched_easy_count++))
            else
                item_type="Unpatched (Risky)"
                item_color="$YELLOW"
                ((unpatched_risky_count++))
            fi
        fi
        all_items+=("$(echo -e "${item_color}${text}${NC}")___${item_type}") # Store with color and type
    done

    # --- UI & Menu ---
    echo -e "  ${GREEN}Scan Complete!${NC}"
    echo -e "  - ${GREEN}Patched (Easy):          $patched_easy_count${NC}"
    echo -e "  - ${YELLOW}Patched (Risky-Added):   $patched_risky_added_count${NC}"
    echo -e "  - ${CYAN}Patched (Risky-Wrapped): $patched_risky_wrapped_count${NC}"
    echo -e "  - ${RED}Unpatched (Easy):        $unpatched_easy_count${NC}"
    echo -e "  - ${YELLOW}Unpatched (Risky):       $unpatched_risky_count${NC}"
    echo -e ""
    
    echo -e "  ${GRAY}OPTIONS:${NC}"
    echo -e "  1. Show All items"
    echo -e "  2. Show Patched items"
    echo -e "  3. Show Unpatched items"
    echo -e "  4. Save log and Exit"
    read -p "  Enter Option#: " choice

    case "$choice" in
        1)
            write_header "All JSON.stringify Calls (${#all_items[@]})"
            for item in "${all_items[@]}"; do
                text_part=$(echo "$item" | cut -d'_' -f1)
                echo -e "  $text_part"
            done
            read -p $ '\n  Press Enter to return to menu'
            ;;
        2)
            total_patched=$(($patched_easy_count + $patched_risky_added_count + $patched_risky_wrapped_count))
            write_header "Patched Calls ($total_patched)"
            for item in "${all_items[@]}"; do
                type_part=$(echo "$item" | cut -d'_' -f4)
                if [[ "$type_part" == Patched* ]]; then
                     text_part=$(echo "$item" | cut -d'_' -f1)
                     echo -e "  $text_part"
                fi
            done
            read -p $'\n  Press Enter to return to menu'
            ;;
        3)
            total_unpatched=$(($unpatched_easy_count + $unpatched_risky_count))
            write_header "Unpatched Calls ($total_unpatched)"
            for item in "${all_items[@]}"; do
                type_part=$(echo "$item" | cut -d'_' -f4)
                if [[ "$type_part" == Unpatched* ]]; then
                     text_part=$(echo "$item" | cut -d'_' -f1)
                     echo -e "  $text_part"
                fi
            done
            read -p $'\n  Press Enter to return to menu'
            ;;
        4)
            echo "Antigravity BigInt Scan Results" > "$LOG_FILE"
            echo "=================================================" >> "$LOG_FILE"
            echo "Scan Date: $(date)" >> "$LOG_FILE"
            echo "Target File: $TARGET_FILE" >> "$LOG_FILE"
            echo "" >> "$LOG_FILE"
            echo "Summary:" >> "$LOG_FILE"
            echo "- Patched (Easy):          $patched_easy_count" >> "$LOG_FILE"
            echo "- Patched (Risky-Added):   $patched_risky_added_count" >> "$LOG_FILE"
            echo "- Patched (Risky-Wrapped): $patched_risky_wrapped_count" >> "$LOG_FILE"
            echo "- Unpatched (Easy):        $unpatched_easy_count" >> "$LOG_FILE"
            echo "- Unpatched (Risky):       $unpatched_risky_count" >> "$LOG_FILE"
            echo "" >> "$LOG_FILE"
            echo "Details:" >> "$LOG_FILE"
            echo "=================================================" >> "$LOG_FILE"
            for item in "${all_items[@]}"; do
                text_part=$(echo "$item" | perl -pe 's/\x1b\[[0-9;]*[mG]//g' | cut -d'_' -f1)
                type_part=$(echo "$item" | cut -d'_' -f4)
                 echo "[$type_part] - $text_part" >> "$LOG_FILE"
            done
            echo -e "\n  ${GREEN}Log saved to $LOG_FILE${NC}"
            sleep 2
            exit 0
            ;;
    esac
done

bigint-unpatcher.sh

#!/bin/bash

# =====================================================================================
#  Antigravity BigInt Unpatcher for Linux
# =====================================================================================

# --- Config ---
TARGET_FILE="$HOME/.config/Antigravity/app/out/main.js"
BACKUP_FILE="${TARGET_FILE}.bak"
PATCHED_BACKUP_FILE="${TARGET_FILE}.patched.bak"

# --- Regex for UNPATCHING ---
# These are perl-compatible regexes used for substitutions.
EASY_UNPATCH_REGEX='s/JSON\.stringify\(([^,]*?),\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v\)/JSON.stringify($1)/g'
RISKY_WRAPPED_UNPATCH_REGEX='s/JSON\.stringify\((.*?),\s*\(_k, v\)\s*=>\s*{\s*let\s*_r\s*=\s*\((.*?)\)\(_k, v\);\s*return\s*typeof\s*_r\s*===\s*"bigint"\s*\?\s*_r\.toString\(\)\s*:\s*_r;\s*}(,.*?)?\)/JSON.stringify($1, $2$3)/g'
RISKY_ADDED_UNPATCH_REGEX='s/JSON\.stringify\(([\{\(\[].*?[\}\)\]]),\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v\)/JSON.stringify($1)/g'

# --- Colors ---
CYAN='\033[0;36m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
GRAY='\033[0;90m'
NC='\033[0m' # No Color

# --- Utility Functions ---
write_header() {
    clear
    echo -e ""
    echo -e "${CYAN}  ==============================================================${NC}"
    echo -e "${CYAN}             $1${NC}"
    echo -e "${CYAN}  ==============================================================${NC}"
    echo -e ""
}

get_classification() {
    local text="$1"
    local args_content=$(echo "$text" | perl -nE 'say $1 if /^JSON\.stringify\((.*)\)$/')
    if echo "$args_content" | grep -q -P '[\{\(\[\]\}\,]'; then
        echo "risky"
    else
        echo "easy"
    fi
}

# --- Main Application Loop ---
if [[ ! -f "$TARGET_FILE" ]]; then
    # Fallback for some distributions that might use a different path
    TARGET_FILE="$HOME/snap/antigravity/current/.config/Antigravity/app/out/main.js"
    if [[ ! -f "$TARGET_FILE" ]]; then
        write_header "Error"
        echo -e "  ${RED}Antigravity main.js not found.${NC}"
        echo -e "  Checked standard paths. If you have a custom installation, please update the TARGET_FILE variable in this script."
        exit 1
    fi
fi

while true; do
    write_header "Linux BigInt Omni-Unpatcher"
    
    # --- Analysis Phase ---
    mapfile -t all_found_matches < <(perl -0777 -nE 'say for /JSON\.stringify\((?:[^()]|\([^()]*\))*\)/g' "$TARGET_FILE")

    patched_easy_count=0
    patched_risky_added_count=0
    patched_risky_wrapped_count=0
    unpatched_easy_count=0
    unpatched_risky_count=0

    for text in "${all_found_matches[@]}"; do
        if [[ "$text" == *"typeof _r ==="*"bigint"* ]]; then
            ((patched_risky_wrapped_count++))
        elif [[ "$text" == *"(_k, v) => typeof v === \"bigint\""* ]]; then
            unpatched_version=$(echo "$text" | perl -pe 's/,\s*\(_k, v\) => typeof v === "bigint" \? v\.toString\(\) : v//g')
            classification=$(get_classification "$unpatched_version")
            if [[ "$classification" == "easy" ]]; then
                ((patched_easy_count++))
            else
                ((patched_risky_added_count++))
            fi
        else
            classification=$(get_classification "$text")
            if [[ "$classification" == "easy" ]]; then
                ((unpatched_easy_count++))
            else
                ((unpatched_risky_count++))
            fi
        fi
    done

    total_patched_count=$(($patched_easy_count + $patched_risky_added_count + $patched_risky_wrapped_count))

    # --- UI & Menu ---
    echo -e "  ${GREEN}File Scan Results:${NC}"
    echo -e "  - ${GREEN}Patched (Easy):          $patched_easy_count${NC}"
    echo -e "  - ${YELLOW}Patched (Risky-Added):   $patched_risky_added_count${NC}"
    echo -e "  - ${CYAN}Patched (Risky-Wrapped): $patched_risky_wrapped_count${NC}"
    echo -e "  - ${RED}Unpatched (Easy):        $unpatched_easy_count${NC}"
    echo -e "  - ${YELLOW}Unpatched (Risky):       $unpatched_risky_count${NC}"
    echo -e ""
    
    echo -e "  ${GRAY}OPTIONS:${NC}"
    echo -e "  1. Unpatch ALL ($total_patched_count found)"
    echo -e "  2. Unpatch Easy only ($patched_easy_count found)"
    echo -e "  3. Unpatch Risky-Added only ($patched_risky_added_count found)"
    echo -e "  4. Unpatch Risky-Wrapped only ($patched_risky_wrapped_count found)"
    echo -e "  5. Restore from backup ($BACKUP_FILE)"
    echo -e "  6. Exit"
    read -p "  Enter Option#: " choice

    case "$choice" in
        1) # UNPATCH ALL
            if [[ $total_patched_count -eq 0 ]]; then echo "  No patches to remove."; sleep 1; continue; fi
            echo -e "  ${YELLOW}Unpatching all found patches...${NC}"
            if [[ ! -f "$PATCHED_BACKUP_FILE" ]]; then cp "$TARGET_FILE" "$PATCHED_BACKUP_FILE"; fi
            
            # Use perl for in-place editing for safety and power.
            perl -i -0777pe "$RISKY_WRAPPED_UNPATCH_REGEX" "$TARGET_FILE"
            perl -i -0777pe "$RISKY_ADDED_UNPATCH_REGEX" "$TARGET_FILE"
            perl -i -0777pe "$EASY_UNPATCH_REGEX" "$TARGET_FILE"
            
            echo -e "  ${GREEN}Bulk Unpatch Applied!${NC}"; sleep 2
            ;;
        2) # UNPATCH EASY
            if [[ $patched_easy_count -eq 0 ]]; then echo "  No easy patches to remove."; sleep 1; continue; fi
            if [[ ! -f "$PATCHED_BACKUP_FILE" ]]; then cp "$TARGET_FILE" "$PATCHED_BACKUP_FILE"; fi
            perl -i -0777pe "$EASY_UNPATCH_REGEX" "$TARGET_FILE"
            echo -e "  ${GREEN}Easy patches removed!${NC}"; sleep 2
            ;;
        3) # UNPATCH RISKY-ADDED
            if [[ $patched_risky_added_count -eq 0 ]]; then echo "  No risky-added patches to remove."; sleep 1; continue; fi
            if [[ ! -f "$PATCHED_BACKUP_FILE" ]]; then cp "$TARGET_FILE" "$PATCHED_BACKUP_FILE"; fi
            perl -i -0777pe "$RISKY_ADDED_UNPATCH_REGEX" "$TARGET_FILE"
            echo -e "  ${GREEN}Risky-added patches removed!${NC}"; sleep 2
            ;;
        4) # UNPATCH RISKY-WRAPPED
            if [[ $patched_risky_wrapped_count -eq 0 ]]; then echo "  No risky-wrapped patches to remove."; sleep 1; continue; fi
            if [[ ! -f "$PATCHED_BACKUP_FILE" ]]; then cp "$TARGET_FILE" "$PATCHED_BACKUP_FILE"; fi
            perl -i -0777pe "$RISKY_WRAPPED_UNPATCH_REGEX" "$TARGET_FILE"
            echo -e "  ${GREEN}Risky-wrapped patches removed!${NC}"; sleep 2
            ;;
        5) # RESTORE BACKUP
            if [[ -f "$BACKUP_FILE" ]]; then
                echo -e "  ${YELLOW}Restoring original file from $BACKUP_FILE...${NC}"
                cp "$BACKUP_FILE" "$TARGET_FILE"
                echo -e "  ${GREEN}Restore complete!${NC}"
            else
                echo -e "  ${RED}Backup file not found ($BACKUP_FILE).${NC}"
            fi
            sleep 2
            ;;
        6) exit 0 ;;
    esac
done