better-antigravity 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +168 -0
- package/cli.js +61 -0
- package/fixes/auto-run-fix/patch.js +284 -0
- package/package.json +38 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kanezal
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# ā” Better Antigravity
|
|
4
|
+
|
|
5
|
+
**Community-driven fixes and improvements for [Antigravity IDE](https://antigravity.dev)**
|
|
6
|
+
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://github.com/AkaNPC/better-antigravity/pulls)
|
|
9
|
+
[](https://antigravity.dev)
|
|
10
|
+
|
|
11
|
+
*Antigravity is great. We just make it a little better.*
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## š¤ What is this?
|
|
18
|
+
|
|
19
|
+
A collection of **hotfixes and patches** for bugs in Antigravity IDE that haven't been officially resolved yet. Each fix is a standalone script you can apply and revert safely.
|
|
20
|
+
|
|
21
|
+
> **Note:** These are unofficial community patches. Use at your own risk. All fixes create automatic backups and can be reverted with a single command.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## š¦ Available Fixes
|
|
26
|
+
|
|
27
|
+
| Fix | Description | Status |
|
|
28
|
+
|-----|-------------|--------|
|
|
29
|
+
| [**auto-run-fix**](#-auto-run-fix) | "Always Proceed" terminal policy doesn't auto-execute commands | š¢ Working |
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## š§ Auto-Run Fix
|
|
34
|
+
|
|
35
|
+
### The Problem
|
|
36
|
+
|
|
37
|
+
You set **Settings ā Agent ā Terminal Execution ā "Always Proceed"**, but Antigravity **still asks you to click "Run"** on every single terminal command. Every. Single. Time.
|
|
38
|
+
|
|
39
|
+
The setting saves correctly, Strict Mode is off ā it just doesn't work.
|
|
40
|
+
|
|
41
|
+
### Root Cause
|
|
42
|
+
|
|
43
|
+
Found in the source code: the `run_command` step renderer component has an `onChange` handler that auto-confirms commands when you switch the dropdown to "Always run" **on a specific step**. But there's **no `useEffect` hook** that checks the saved policy at mount time and auto-confirms **new steps**.
|
|
44
|
+
|
|
45
|
+
In other words: the UI reads your setting, displays the correct dropdown value, but never actually acts on it automatically.
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
// What exists (only fires on dropdown CHANGE):
|
|
49
|
+
y = Mt(_ => {
|
|
50
|
+
setTerminalAutoExecutionPolicy(_),
|
|
51
|
+
_ === EAGER && confirm(true) // ā only when you manually switch
|
|
52
|
+
}, [])
|
|
53
|
+
|
|
54
|
+
// What's MISSING (should fire on component mount):
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (policy === EAGER && !secureMode) confirm(true) // ā auto-confirm new steps
|
|
57
|
+
}, [])
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### The Fix
|
|
61
|
+
|
|
62
|
+
Our patcher adds the missing `useEffect`. It uses **regex pattern matching** to find code by structure ā not by minified variable names ā so it works across Antigravity versions.
|
|
63
|
+
|
|
64
|
+
### Usage
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Make sure Node.js 16+ is installed
|
|
68
|
+
|
|
69
|
+
# Apply the fix
|
|
70
|
+
node fixes/auto-run-fix/patch.js
|
|
71
|
+
|
|
72
|
+
# Check if it's applied
|
|
73
|
+
node fixes/auto-run-fix/patch.js --check
|
|
74
|
+
|
|
75
|
+
# Revert to original
|
|
76
|
+
node fixes/auto-run-fix/patch.js --revert
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Example Output
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
83
|
+
ā Antigravity "Always Proceed" Auto-Run Fix ā
|
|
84
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
85
|
+
|
|
86
|
+
š C:\Users\user\AppData\Local\Programs\Antigravity
|
|
87
|
+
š¦ Version: 1.107.0 (IDE 1.19.5)
|
|
88
|
+
|
|
89
|
+
š [workbench] Found onChange at offset 12362782
|
|
90
|
+
callback=Mt, enum=Dhe, confirm=b
|
|
91
|
+
policyVar=u
|
|
92
|
+
secureVar=d
|
|
93
|
+
useEffect=mn (confidence: 30 hits)
|
|
94
|
+
ā
[workbench] Patched (+43 bytes)
|
|
95
|
+
š [jetskiAgent] Found onChange at offset 8388797
|
|
96
|
+
callback=ve, enum=rx, confirm=F
|
|
97
|
+
policyVar=d
|
|
98
|
+
secureVar=f
|
|
99
|
+
useEffect=At (confidence: 55 hits)
|
|
100
|
+
ā
[jetskiAgent] Patched (+42 bytes)
|
|
101
|
+
|
|
102
|
+
⨠Done! Restart Antigravity.
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Compatibility
|
|
106
|
+
|
|
107
|
+
| Antigravity Version | Status |
|
|
108
|
+
|---------------------|--------|
|
|
109
|
+
| 1.107.0 | ā
Tested |
|
|
110
|
+
| Other versions | š” Should work (dynamic pattern matching) |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## š”ļø Safety
|
|
115
|
+
|
|
116
|
+
- **Automatic backups** ā original files are saved as `.bak` before patching
|
|
117
|
+
- **One-command revert** ā run with `--revert` to restore originals instantly
|
|
118
|
+
- **Non-destructive** ā patches only add code, never remove existing logic
|
|
119
|
+
- **Version-resilient** ā uses structural regex matching, not hardcoded variable names
|
|
120
|
+
- **Syntax validation** ā verifies code structure before writing
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## š Project Structure
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
better-antigravity/
|
|
128
|
+
āāā README.md
|
|
129
|
+
āāā LICENSE
|
|
130
|
+
āāā fixes/
|
|
131
|
+
āāā auto-run-fix/
|
|
132
|
+
āāā patch.js # The patcher script
|
|
133
|
+
āāā README.md # Detailed fix documentation
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## š¤ Contributing
|
|
139
|
+
|
|
140
|
+
Found another Antigravity bug? Have a fix? PRs are welcome!
|
|
141
|
+
|
|
142
|
+
### Adding a new fix:
|
|
143
|
+
|
|
144
|
+
1. Create a folder under `fixes/` with a descriptive name
|
|
145
|
+
2. Include a `patch.js` that supports `--check` and `--revert` flags
|
|
146
|
+
3. Add a `README.md` with root cause analysis
|
|
147
|
+
4. Update the main README's fix table
|
|
148
|
+
|
|
149
|
+
### Guidelines:
|
|
150
|
+
|
|
151
|
+
- Always create backups before patching
|
|
152
|
+
- Use structural pattern matching, not hardcoded variable names
|
|
153
|
+
- Support `--check` and `--revert` flags
|
|
154
|
+
- Test on a clean Antigravity installation
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## ā ļø Disclaimer
|
|
159
|
+
|
|
160
|
+
This project is not affiliated with Google or the Antigravity team. These are community patches for known bugs. If Antigravity updates and the patches break, simply revert and re-apply (or wait for an updated patch).
|
|
161
|
+
|
|
162
|
+
**Always report bugs officially** at [antigravity.google/support](https://antigravity.google/support) ā community patches are temporary solutions, not replacements for official fixes.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## š License
|
|
167
|
+
|
|
168
|
+
[MIT](LICENSE) ā do whatever you want with it.
|
package/cli.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* better-antigravity CLI
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx better-antigravity ā list available fixes
|
|
7
|
+
* npx better-antigravity auto-run ā apply auto-run fix
|
|
8
|
+
* npx better-antigravity auto-run --check ā check status
|
|
9
|
+
* npx better-antigravity auto-run --revert ā revert fix
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
|
|
15
|
+
const fixes = {
|
|
16
|
+
'auto-run': {
|
|
17
|
+
script: path.join(__dirname, 'fixes', 'auto-run-fix', 'patch.js'),
|
|
18
|
+
description: '"Always Proceed" terminal policy doesn\'t auto-execute commands'
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const args = process.argv.slice(2);
|
|
23
|
+
const fixName = args[0];
|
|
24
|
+
const flags = args.slice(1);
|
|
25
|
+
|
|
26
|
+
// Header
|
|
27
|
+
console.log('');
|
|
28
|
+
console.log(' better-antigravity ā community fixes for Antigravity IDE');
|
|
29
|
+
console.log(' https://github.com/Kanezal/better-antigravity');
|
|
30
|
+
console.log('');
|
|
31
|
+
|
|
32
|
+
if (!fixName || fixName === '--help' || fixName === '-h') {
|
|
33
|
+
console.log(' Available fixes:');
|
|
34
|
+
console.log('');
|
|
35
|
+
for (const [name, fix] of Object.entries(fixes)) {
|
|
36
|
+
console.log(` ${name.padEnd(15)} ${fix.description}`);
|
|
37
|
+
}
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log(' Usage:');
|
|
40
|
+
console.log(' npx better-antigravity <fix-name> Apply fix');
|
|
41
|
+
console.log(' npx better-antigravity <fix-name> --check Check status');
|
|
42
|
+
console.log(' npx better-antigravity <fix-name> --revert Revert fix');
|
|
43
|
+
console.log('');
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const fix = fixes[fixName];
|
|
48
|
+
if (!fix) {
|
|
49
|
+
console.log(` Unknown fix: "${fixName}"`);
|
|
50
|
+
console.log(` Available: ${Object.keys(fixes).join(', ')}`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!fs.existsSync(fix.script)) {
|
|
55
|
+
console.log(` Fix script not found: ${fix.script}`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Forward to the fix script with flags
|
|
60
|
+
process.argv = [process.argv[0], fix.script, ...flags];
|
|
61
|
+
require(fix.script);
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Antigravity "Always Proceed" Auto-Run Fix
|
|
5
|
+
* ==========================================
|
|
6
|
+
*
|
|
7
|
+
* Fixes a bug where the "Always Proceed" terminal execution policy doesn't
|
|
8
|
+
* actually auto-execute commands. Uses regex patterns to find code structures
|
|
9
|
+
* regardless of minified variable names ā works across versions.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* node patch.js - Apply patch
|
|
13
|
+
* node patch.js --revert - Restore original files
|
|
14
|
+
* node patch.js --check - Check patch status
|
|
15
|
+
*
|
|
16
|
+
* License: MIT
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
const os = require('os');
|
|
22
|
+
|
|
23
|
+
// āāā Installation Detection āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
24
|
+
|
|
25
|
+
function findAntigravityPath() {
|
|
26
|
+
const candidates = [];
|
|
27
|
+
if (process.platform === 'win32') {
|
|
28
|
+
candidates.push(
|
|
29
|
+
path.join(process.env.LOCALAPPDATA || '', 'Programs', 'Antigravity'),
|
|
30
|
+
path.join(process.env.PROGRAMFILES || '', 'Antigravity'),
|
|
31
|
+
);
|
|
32
|
+
} else if (process.platform === 'darwin') {
|
|
33
|
+
candidates.push(
|
|
34
|
+
'/Applications/Antigravity.app/Contents/Resources',
|
|
35
|
+
path.join(os.homedir(), 'Applications', 'Antigravity.app', 'Contents', 'Resources')
|
|
36
|
+
);
|
|
37
|
+
} else {
|
|
38
|
+
candidates.push('/usr/share/antigravity', '/opt/antigravity',
|
|
39
|
+
path.join(os.homedir(), '.local', 'share', 'antigravity'));
|
|
40
|
+
}
|
|
41
|
+
for (const c of candidates) {
|
|
42
|
+
const f = path.join(c, 'resources', 'app', 'out', 'vs', 'workbench', 'workbench.desktop.main.js');
|
|
43
|
+
if (fs.existsSync(f)) return c;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// āāā Smart Pattern Matching āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Finds the onChange handler for terminalAutoExecutionPolicy and extracts
|
|
52
|
+
* variable names from context, regardless of minification.
|
|
53
|
+
*
|
|
54
|
+
* Pattern we're looking for (structure, not exact names):
|
|
55
|
+
* <VAR_CONFIRM>=<useCallback>((<ARG>)=>{
|
|
56
|
+
* <stepHandler>?.setTerminalAutoExecutionPolicy?.(<ARG>),
|
|
57
|
+
* <ARG>===<ENUM>.EAGER&&<CONFIRM_FN>(!0)
|
|
58
|
+
* },[...])
|
|
59
|
+
*
|
|
60
|
+
* From the surrounding context we also extract:
|
|
61
|
+
* <POLICY_VAR> = <stepHandler>?.terminalAutoExecutionPolicy ?? <ENUM>.OFF
|
|
62
|
+
* <SECURE_VAR> = <stepHandler>?.secureModeEnabled ?? !1
|
|
63
|
+
*/
|
|
64
|
+
function analyzeFile(content, label) {
|
|
65
|
+
// 1. Find the onChange handler: contains setTerminalAutoExecutionPolicy AND .EAGER
|
|
66
|
+
// Pattern: VARNAME=CALLBACK(ARG=>{...setTerminalAutoExecutionPolicy...,ARG===ENUM.EAGER&&CONFIRM(!0)},[...])
|
|
67
|
+
const onChangeRe = /(\w+)=(\w+)\((\w+)=>\{\w+\?\.setTerminalAutoExecutionPolicy\?\.\(\3\),\3===(\w+)\.EAGER&&(\w+)\(!0\)\},\[[\w,]*\]\)/;
|
|
68
|
+
const onChangeMatch = content.match(onChangeRe);
|
|
69
|
+
|
|
70
|
+
if (!onChangeMatch) {
|
|
71
|
+
console.log(` ā [${label}] Could not find onChange handler pattern`);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const [fullMatch, assignVar, callbackAlias, argName, enumAlias, confirmFn] = onChangeMatch;
|
|
76
|
+
const matchIndex = content.indexOf(fullMatch);
|
|
77
|
+
|
|
78
|
+
console.log(` š [${label}] Found onChange at offset ${matchIndex}`);
|
|
79
|
+
console.log(` callback=${callbackAlias}, enum=${enumAlias}, confirm=${confirmFn}`);
|
|
80
|
+
|
|
81
|
+
// 2. Find policy variable: VARNAME=HANDLER?.terminalAutoExecutionPolicy??ENUM.OFF
|
|
82
|
+
const policyRe = new RegExp(`(\\w+)=\\w+\\?\\.terminalAutoExecutionPolicy\\?\\?${enumAlias}\\.OFF`);
|
|
83
|
+
const policyMatch = content.substring(Math.max(0, matchIndex - 2000), matchIndex).match(policyRe);
|
|
84
|
+
|
|
85
|
+
if (!policyMatch) {
|
|
86
|
+
console.log(` ā [${label}] Could not find policy variable`);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const policyVar = policyMatch[1];
|
|
90
|
+
console.log(` policyVar=${policyVar}`);
|
|
91
|
+
|
|
92
|
+
// 3. Find secureMode variable: VARNAME=HANDLER?.secureModeEnabled??!1
|
|
93
|
+
const secureRe = /(\w+)=\w+\?\.secureModeEnabled\?\?!1/;
|
|
94
|
+
const secureMatch = content.substring(Math.max(0, matchIndex - 2000), matchIndex).match(secureRe);
|
|
95
|
+
|
|
96
|
+
if (!secureMatch) {
|
|
97
|
+
console.log(` ā [${label}] Could not find secureMode variable`);
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const secureVar = secureMatch[1];
|
|
101
|
+
console.log(` secureVar=${secureVar}`);
|
|
102
|
+
|
|
103
|
+
// 4. Find useEffect alias: look for ALIAS(()=>{...},[...]) calls nearby (not useCallback/useMemo)
|
|
104
|
+
const nearbyCode = content.substring(Math.max(0, matchIndex - 5000), matchIndex + 5000);
|
|
105
|
+
const effectCandidates = {};
|
|
106
|
+
const effectRe = /\b(\w{2,3})\(\(\)=>\{[^}]{3,80}\},\[/g;
|
|
107
|
+
let m;
|
|
108
|
+
while ((m = effectRe.exec(nearbyCode)) !== null) {
|
|
109
|
+
const alias = m[1];
|
|
110
|
+
if (alias !== callbackAlias && alias !== 'var' && alias !== 'new') {
|
|
111
|
+
effectCandidates[alias] = (effectCandidates[alias] || 0) + 1;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Also check broader file for common useEffect patterns (with cleanup return)
|
|
116
|
+
const cleanupRe = /\b(\w{2,3})\(\(\)=>\{[^}]*return\s*\(\)=>/g;
|
|
117
|
+
while ((m = cleanupRe.exec(content)) !== null) {
|
|
118
|
+
const alias = m[1];
|
|
119
|
+
if (alias !== callbackAlias) {
|
|
120
|
+
effectCandidates[alias] = (effectCandidates[alias] || 0) + 5; // higher weight
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Remove known non-useEffect aliases (useMemo patterns)
|
|
125
|
+
// useMemo: alias(()=>EXPRESSION,[deps]) ā returns a value, often assigned
|
|
126
|
+
// useEffect: alias(()=>{STATEMENTS},[deps]) ā no return value
|
|
127
|
+
|
|
128
|
+
// Pick the most common candidate
|
|
129
|
+
let useEffectAlias = null;
|
|
130
|
+
let maxCount = 0;
|
|
131
|
+
for (const [alias, count] of Object.entries(effectCandidates)) {
|
|
132
|
+
if (count > maxCount) {
|
|
133
|
+
maxCount = count;
|
|
134
|
+
useEffectAlias = alias;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (!useEffectAlias) {
|
|
139
|
+
console.log(` ā [${label}] Could not determine useEffect alias`);
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
console.log(` useEffect=${useEffectAlias} (confidence: ${maxCount} hits)`);
|
|
143
|
+
|
|
144
|
+
// 5. Build patch
|
|
145
|
+
const patchCode = `_aep=${useEffectAlias}(()=>{${policyVar}===${enumAlias}.EAGER&&!${secureVar}&&${confirmFn}(!0)},[]),`;
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
target: fullMatch,
|
|
149
|
+
replacement: patchCode + fullMatch,
|
|
150
|
+
patchMarker: `_aep=${useEffectAlias}(()=>{${policyVar}===${enumAlias}.EAGER`,
|
|
151
|
+
label
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// āāā File Operations āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
156
|
+
|
|
157
|
+
function patchFile(filePath, label) {
|
|
158
|
+
if (!fs.existsSync(filePath)) {
|
|
159
|
+
console.log(` ā [${label}] File not found: ${filePath}`);
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
164
|
+
|
|
165
|
+
// Check if already patched
|
|
166
|
+
if (content.includes('_aep=')) {
|
|
167
|
+
const existingPatch = content.match(/_aep=\w+\(\(\)=>\{[^}]+EAGER[^}]+\},\[\]\)/);
|
|
168
|
+
if (existingPatch) {
|
|
169
|
+
console.log(` āļø [${label}] Already patched`);
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const analysis = analyzeFile(content, label);
|
|
175
|
+
if (!analysis) return false;
|
|
176
|
+
|
|
177
|
+
// Verify target is unique
|
|
178
|
+
const count = content.split(analysis.target).length - 1;
|
|
179
|
+
if (count !== 1) {
|
|
180
|
+
console.log(` ā [${label}] Target found ${count} times (expected 1)`);
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Backup
|
|
185
|
+
if (!fs.existsSync(filePath + '.bak')) {
|
|
186
|
+
fs.copyFileSync(filePath, filePath + '.bak');
|
|
187
|
+
console.log(` š¦ [${label}] Backup created`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Apply
|
|
191
|
+
const patched = content.replace(analysis.target, analysis.replacement);
|
|
192
|
+
fs.writeFileSync(filePath, patched, 'utf8');
|
|
193
|
+
|
|
194
|
+
const diff = fs.statSync(filePath).size - fs.statSync(filePath + '.bak').size;
|
|
195
|
+
console.log(` ā
[${label}] Patched (+${diff} bytes)`);
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function revertFile(filePath, label) {
|
|
200
|
+
const bak = filePath + '.bak';
|
|
201
|
+
if (!fs.existsSync(bak)) {
|
|
202
|
+
console.log(` āļø [${label}] No backup, skipping`);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
fs.copyFileSync(bak, filePath);
|
|
206
|
+
console.log(` ā
[${label}] Restored`);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function checkFile(filePath, label) {
|
|
210
|
+
if (!fs.existsSync(filePath)) {
|
|
211
|
+
console.log(` ā [${label}] Not found`);
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
215
|
+
const patched = content.includes('_aep=') && /_aep=\w+\(\(\)=>\{[^}]+EAGER/.test(content);
|
|
216
|
+
const hasBak = fs.existsSync(filePath + '.bak');
|
|
217
|
+
|
|
218
|
+
if (patched) {
|
|
219
|
+
console.log(` ā
[${label}] PATCHED` + (hasBak ? ' (backup exists)' : ''));
|
|
220
|
+
} else {
|
|
221
|
+
const analysis = analyzeFile(content, label);
|
|
222
|
+
if (analysis) {
|
|
223
|
+
console.log(` ⬠[${label}] NOT PATCHED (patchable)`);
|
|
224
|
+
} else {
|
|
225
|
+
console.log(` ā ļø [${label}] NOT PATCHED (may be incompatible)`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return patched;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// āāā Version Info āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
232
|
+
|
|
233
|
+
function getVersion(basePath) {
|
|
234
|
+
try {
|
|
235
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(basePath, 'resources', 'app', 'package.json'), 'utf8'));
|
|
236
|
+
const product = JSON.parse(fs.readFileSync(path.join(basePath, 'resources', 'app', 'product.json'), 'utf8'));
|
|
237
|
+
return `${pkg.version} (IDE ${product.ideVersion})`;
|
|
238
|
+
} catch { return 'unknown'; }
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// āāā Main āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
242
|
+
|
|
243
|
+
function main() {
|
|
244
|
+
const args = process.argv.slice(2);
|
|
245
|
+
const action = args.includes('--revert') ? 'revert' : args.includes('--check') ? 'check' : 'apply';
|
|
246
|
+
|
|
247
|
+
console.log('');
|
|
248
|
+
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā');
|
|
249
|
+
console.log('ā Antigravity "Always Proceed" Auto-Run Fix ā');
|
|
250
|
+
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā');
|
|
251
|
+
|
|
252
|
+
const basePath = findAntigravityPath();
|
|
253
|
+
if (!basePath) {
|
|
254
|
+
console.log('\nā Antigravity not found! Install it or run from its directory.');
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
console.log(`\nš ${basePath}`);
|
|
259
|
+
console.log(`š¦ Version: ${getVersion(basePath)}`);
|
|
260
|
+
console.log('');
|
|
261
|
+
|
|
262
|
+
const files = [
|
|
263
|
+
{ path: path.join(basePath, 'resources', 'app', 'out', 'vs', 'workbench', 'workbench.desktop.main.js'), label: 'workbench' },
|
|
264
|
+
{ path: path.join(basePath, 'resources', 'app', 'out', 'jetskiAgent', 'main.js'), label: 'jetskiAgent' },
|
|
265
|
+
];
|
|
266
|
+
|
|
267
|
+
switch (action) {
|
|
268
|
+
case 'check':
|
|
269
|
+
files.forEach(f => checkFile(f.path, f.label));
|
|
270
|
+
break;
|
|
271
|
+
case 'revert':
|
|
272
|
+
files.forEach(f => revertFile(f.path, f.label));
|
|
273
|
+
console.log('\n⨠Restored! Restart Antigravity.');
|
|
274
|
+
break;
|
|
275
|
+
case 'apply':
|
|
276
|
+
const ok = files.every(f => patchFile(f.path, f.label));
|
|
277
|
+
console.log(ok
|
|
278
|
+
? '\n⨠Done! Restart Antigravity.\nš” Run with --revert to undo.\nā ļø Re-run after Antigravity updates.'
|
|
279
|
+
: '\nā ļø Some patches failed.');
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "better-antigravity",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Community-driven fixes and improvements for Antigravity IDE",
|
|
5
|
+
"main": "fixes/auto-run-fix/patch.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"better-antigravity": "cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"fix:auto-run": "node fixes/auto-run-fix/patch.js",
|
|
11
|
+
"fix:auto-run:check": "node fixes/auto-run-fix/patch.js --check",
|
|
12
|
+
"fix:auto-run:revert": "node fixes/auto-run-fix/patch.js --revert"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"antigravity",
|
|
16
|
+
"antigravity-ide",
|
|
17
|
+
"google-antigravity",
|
|
18
|
+
"fix",
|
|
19
|
+
"patch",
|
|
20
|
+
"auto-run",
|
|
21
|
+
"terminal",
|
|
22
|
+
"always-proceed",
|
|
23
|
+
"community"
|
|
24
|
+
],
|
|
25
|
+
"author": "Kanezal",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/Kanezal/better-antigravity"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/Kanezal/better-antigravity#readme",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/Kanezal/better-antigravity/issues"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=16.0.0"
|
|
37
|
+
}
|
|
38
|
+
}
|