I cannot confirm this fixed yet (on Windows 11. I had to create a patch of the minified JS file (now get a warning that my Antigravity may be corrupt, but it’s working flawlessly so far.
AG-PATCH — Antigravity infinite Preact re-render fix
Fixes the startup freeze caused by the server-synced “Gemini 3.6” tiered model catalog poisoning uss-userStatus (and uss-theme / uss-sidebarWorkspaces) and flooding Preact’s render queue (Z_t / PJr in the unresponsive stack).
Why a script instead of a .diff
The bundle is minified into lines up to ~800 KB long. A unified diff would embed each changed line twice (~4 MB) and break on any whitespace nuance, so the patch ships as an idempotent string-replacement script with exact-match anchors that aborts if the bundle doesn’t match.
What it changes (4 edits)
- Prepends
globalThis.__agDeepEq— bounded (depth 20, 20k-op budget), BigInt/Uint8Array/Date-aware deep-equality helper; bails to “not equal” (= original behavior) on cycles or functions. z0.setState(provider store feeding Preact): no-op when the new state deep-equals the current state → identical payloads no longer re-render.- Unified-state-sync ingestion handler: drops no-op topic updates before they touch the reactive store, for all
uss-*topics. uss-userStatusdecoder: filters model-catalog entries with no validmodelOrAliasand any label matching/gemini[\s._-]?3.6/i.
Apply
-
Quit Antigravity completely (check no background processes remain).
-
Locate the bundle, e.g. on Windows:
%LOCALAPPDATA%\Programs\Antigravity\resources\app\out\vs\workbench\workbench.desktop.main.js(macOS:Antigravity.app/Contents/Resources/app/out/vs/workbench/...) -
Run:
python apply-antigravity-patch.py "<path>\workbench.desktop.main.js"It creates
workbench.desktop.main.js.bakbeside the original and printsapplied: ...for each edit. Re-running prints “Already patched”. -
Optional sanity check:
node --check "<path>\workbench.desktop.main.js" -
Launch Antigravity. The server can keep re-syncing the corrupted state; identical payloads are now no-ops and the 3.6 entries never reach the sidebar component.
Roll back
Restore the .bak file over the patched one.
Caveats
- Any Antigravity update overwrites the bundle → re-run the script.
- Anchors are tied to this build’s minified identifiers (
z0,E2,hBe,Rp,hs). On a new build the script aborts safely with an anchor-count error rather than corrupting the file; anchors must then be re-derived. - If the app caches compiled code (
Code Cache/CachedDatain the user data dir), delete it if the patch doesn’t seem to take effect.
Python Script
#!/usr/bin/env python3
"""
AG-PATCH: fixes infinite Preact re-render loop in Antigravity IDE caused by
unvalidated 'Gemini 3.6' tiered model catalog in uss-userStatus sync payloads.
Applies 4 changes to workbench.desktop.main.js:
0. Prepends a bounded, cycle-safe deep-equality helper (globalThis.__agDeepEq)
1. z0.setState: skips firing when new provider state deep-equals current state
2. Unified-state-sync ingestion: drops no-op topic updates (identical row /
delete of missing key) before they hit the reactive store
3. uss-userStatus decoder (bYt): filters catalog entries with no valid
modelOrAlias and anything matching /gemini[\\s._-]?3.6/i
Usage:
python apply-antigravity-patch.py <path-to-workbench.desktop.main.js>
Idempotent: safe to re-run. Creates <file>.bak on first apply.
"""
import sys, os, shutil
MARKER = "/* AG-PATCH: deep-equality helper to dedupe identical state-sync payloads */"
HELPER = (
MARKER +
'globalThis.__agDeepEq||(globalThis.__agDeepEq=function(t,e){var B={n:2e4};'
'function q(a,b,d){if(B.n--<0)return!1;if(a===b)return!0;if(d>20)return!1;'
'if(!a||!b||typeof a!="object"||typeof b!="object")return a!==a&&b!==b;'
'if(Array.isArray(a)){if(!Array.isArray(b)||a.length!==b.length)return!1;'
'for(var i=0;i<a.length;i++)if(!q(a[i],b[i],d+1))return!1;return!0}'
'if(a instanceof Uint8Array||b instanceof Uint8Array){'
'if(!(a instanceof Uint8Array&&b instanceof Uint8Array)||a.length!==b.length)return!1;'
'for(var j=0;j<a.length;j++)if(a[j]!==b[j])return!1;return!0}'
'if(a instanceof Date||b instanceof Date)return a instanceof Date&&b instanceof Date&&a.getTime()===b.getTime();'
'if(Object.getPrototypeOf(a)!==Object.getPrototypeOf(b))return!1;'
'var ka=Object.keys(a),kb=Object.keys(b);if(ka.length!==kb.length)return!1;'
'for(var m=0;m<ka.length;m++){var k=ka[m];'
'if(!Object.prototype.hasOwnProperty.call(b,k)||!q(a[k],b[k],d+1))return!1}return!0}'
'return q(t,e,0)});\n'
)
# (name, old, new) — each `old` must occur exactly once in the unpatched bundle.
# NOTE: identifiers (z0, E2, hBe, Rp, hs...) are minifier-generated and will
# change between Antigravity releases; anchors must be re-derived after updates.
EDITS = [
("z0.setState equality guard",
'setState(t){this.state=t,this._onDidChange.fire(t)}',
'setState(t){if(globalThis.__agDeepEq&&globalThis.__agDeepEq(this.state,t))return;'
'this.state=t,this._onDidChange.fire(t)}'),
("uss ingestion dedupe",
'a.newRow?l.data[a.key]=a.newRow:delete l.data[a.key],r.set(l,void 0)',
'if(a.newRow?l.data[a.key]&&globalThis.__agDeepEq&&globalThis.__agDeepEq(l.data[a.key],a.newRow):!(a.key in l.data))return;'
'a.newRow?l.data[a.key]=a.newRow:delete l.data[a.key],r.set(l,void 0)'),
("uss-userStatus payload sanitizer",
'try{return E2(e,hBe)}catch{return hs(hBe)}',
'try{const w=E2(e,hBe),cf=w&&w.cascadeModelConfigData;'
'if(cf&&Array.isArray(cf.clientModelConfigs)){'
'const ok=q=>{try{return!!(q&&q.modelOrAlias&&q.modelOrAlias.choice&&q.modelOrAlias.choice.case)'
'&&!/gemini[\\s._-]?3\\.6/i.test(String(q.label||""))}catch{return!1}};'
'cf.clientModelConfigs=cf.clientModelConfigs.filter(ok)}'
'return w}catch{return hs(hBe)}'),
]
def main():
if len(sys.argv) != 2:
sys.exit(__doc__)
path = sys.argv[1]
if not os.path.isfile(path):
sys.exit(f"error: no such file: {path}")
with open(path, encoding="utf-8") as f:
s = f.read()
if MARKER in s:
sys.exit("Already patched — nothing to do.")
for name, old, _ in EDITS:
n = s.count(old)
if n != 1:
sys.exit(f"error: anchor for '{name}' found {n} times (expected 1).\n"
"The bundle version differs from the one this patch targets; "
"identifiers must be re-derived.")
bak = path + ".bak"
if not os.path.exists(bak):
shutil.copy2(path, bak)
print(f"backup: {bak}")
s = HELPER + s
for name, old, new in EDITS:
s = s.replace(old, new)
print(f"applied: {name}")
with open(path, "w", encoding="utf-8") as f:
f.write(s)
print(f"patched: {path}")
if __name__ == "__main__":
main()