antigravity-autopilot 1.1.0 → 1.3.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 +44 -2
- package/cli.js +209 -67
- package/extension.js +526 -107
- package/icon.png +0 -0
- package/package.json +35 -7
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nguyen Hoang (nguyenhx2)
|
|
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
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/antigravity-autopilot)
|
|
6
6
|
[](https://github.com/nguyenhx2/Antigravity-AutoPilot)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
8
|
|
|
8
9
|
---
|
|
9
10
|
|
|
@@ -17,6 +18,8 @@ Antigravity has an **"Always Proceed"** terminal execution policy, but due to a
|
|
|
17
18
|
- ✅ Non-destructive — creates `.bak` backup before patching
|
|
18
19
|
- ✅ Reversible — restore originals anytime with `--revert`
|
|
19
20
|
- ✅ Available as VS Code Extension **and** CLI (`npx`)
|
|
21
|
+
- 🛡️ 54+ built-in dangerous command presets (Linux/macOS/Windows)
|
|
22
|
+
- ⚙️ Fully customizable preset management with Reset Defaults
|
|
20
23
|
|
|
21
24
|
---
|
|
22
25
|
|
|
@@ -49,7 +52,7 @@ Install the extension directly into Antigravity for a UI-based experience (sideb
|
|
|
49
52
|
|
|
50
53
|
```bash
|
|
51
54
|
# Download .vsix from GitHub Releases, then:
|
|
52
|
-
antigravity --install-extension antigravity-autopilot-1.
|
|
55
|
+
antigravity --install-extension antigravity-autopilot-1.3.0.vsix
|
|
53
56
|
```
|
|
54
57
|
|
|
55
58
|
**Extension features:**
|
|
@@ -57,6 +60,45 @@ antigravity --install-extension antigravity-autopilot-1.0.0.vsix
|
|
|
57
60
|
- 📊 Status bar showing current patch state
|
|
58
61
|
- ⌨️ Keyboard shortcut: `Ctrl+Shift+F12`
|
|
59
62
|
- ⚙️ `applyOnStartup` setting for fully automatic operation
|
|
63
|
+
- 🔘 `enabledOnStartup` — toggle AutoPilot active/suspended on launch
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 🛡️ Dangerous Command Blocking
|
|
68
|
+
|
|
69
|
+
Built-in protection against destructive commands. **54+ preset patterns** covering all major platforms:
|
|
70
|
+
|
|
71
|
+
| Platform | Examples |
|
|
72
|
+
|----------|----------|
|
|
73
|
+
| **Linux/macOS** | `rm -rf /`, `dd of=/dev/sda`, `mkfs`, fork bombs, `curl \| sh`, `chmod 777 -R /` |
|
|
74
|
+
| **macOS** | `diskutil eraseDisk`, `csrutil disable` |
|
|
75
|
+
| **Windows** | `format C:`, `Remove-Item -Recurse C:\`, `bcdedit /deletevalue`, `IEX download-and-exec` |
|
|
76
|
+
|
|
77
|
+
### Preset Management (Sidebar UI)
|
|
78
|
+
|
|
79
|
+
- 📋 **View all presets** — full list of blocked commands with OS badges (LNX/MAC/WIN)
|
|
80
|
+
- ✕ **Remove individual presets** — click the ✕ button to exclude a preset
|
|
81
|
+
- 🔄 **Reset Defaults** — restore all removed presets with one click
|
|
82
|
+
- 📊 **Active count** — always see how many presets are active
|
|
83
|
+
|
|
84
|
+
### Custom Patterns
|
|
85
|
+
|
|
86
|
+
Add your own patterns via Settings:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
"antigravityAutoAccept.dangerousCommandBlocking.customPatterns": [
|
|
90
|
+
"^my-dangerous-script",
|
|
91
|
+
"DROP TABLE"
|
|
92
|
+
]
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Action Modes
|
|
96
|
+
|
|
97
|
+
| Mode | Behavior |
|
|
98
|
+
|------|----------|
|
|
99
|
+
| `block` | Block command + show error notification (default) |
|
|
100
|
+
| `warn` | Show warning but allow command to proceed |
|
|
101
|
+
| `log` | Silently log to Output channel |
|
|
60
102
|
|
|
61
103
|
---
|
|
62
104
|
|
|
@@ -88,4 +130,4 @@ Variable names are resolved via regex at runtime, making the patch resilient to
|
|
|
88
130
|
|
|
89
131
|
## License
|
|
90
132
|
|
|
91
|
-
MIT
|
|
133
|
+
[MIT](LICENSE)
|
package/cli.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Antigravity AutoPilot — CLI
|
|
5
|
-
*
|
|
6
|
-
* Patches Antigravity's runtime JS bundle so that the
|
|
7
|
-
* "Always Proceed" terminal execution policy actually
|
|
8
|
-
* auto-executes commands without manual confirmation.
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
4
|
+
* Antigravity AutoPilot — CLI v1.3.0
|
|
5
|
+
* ====================================
|
|
11
6
|
* npx antigravity-autopilot Apply patch
|
|
12
|
-
* npx antigravity-autopilot --check Check
|
|
13
|
-
* npx antigravity-autopilot --revert Restore
|
|
7
|
+
* npx antigravity-autopilot --check Check status
|
|
8
|
+
* npx antigravity-autopilot --revert Restore originals
|
|
9
|
+
* npx antigravity-autopilot --help Show help
|
|
14
10
|
*/
|
|
15
11
|
|
|
16
12
|
'use strict';
|
|
@@ -19,7 +15,113 @@ const fs = require('fs');
|
|
|
19
15
|
const path = require('path');
|
|
20
16
|
const os = require('os');
|
|
21
17
|
|
|
22
|
-
// ───
|
|
18
|
+
// ─── ANSI Colors (auto-disable when not a TTY) ───────────────────────────────
|
|
19
|
+
|
|
20
|
+
const isTTY = process.stdout.isTTY;
|
|
21
|
+
const c = {
|
|
22
|
+
reset: isTTY ? '\x1b[0m' : '',
|
|
23
|
+
bold: isTTY ? '\x1b[1m' : '',
|
|
24
|
+
dim: isTTY ? '\x1b[2m' : '',
|
|
25
|
+
yellow: isTTY ? '\x1b[33m' : '',
|
|
26
|
+
cyan: isTTY ? '\x1b[36m' : '',
|
|
27
|
+
green: isTTY ? '\x1b[32m' : '',
|
|
28
|
+
red: isTTY ? '\x1b[31m' : '',
|
|
29
|
+
blue: isTTY ? '\x1b[34m' : '',
|
|
30
|
+
magenta: isTTY ? '\x1b[35m' : '',
|
|
31
|
+
white: isTTY ? '\x1b[97m' : '',
|
|
32
|
+
gray: isTTY ? '\x1b[90m' : '',
|
|
33
|
+
bgBlue: isTTY ? '\x1b[44m' : '',
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const W = 54; // box width (inner)
|
|
37
|
+
|
|
38
|
+
function repeat(ch, n) { return ch.repeat(Math.max(0, n)); }
|
|
39
|
+
function pad(str, n) {
|
|
40
|
+
const visible = str.replace(/\x1b\[[0-9;]*m/g, '');
|
|
41
|
+
return str + repeat(' ', Math.max(0, n - visible.length));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ─── Banner ───────────────────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
function printBanner() {
|
|
47
|
+
const top = `╔${repeat('═', W)}╗`;
|
|
48
|
+
const bot = `╚${repeat('═', W)}╝`;
|
|
49
|
+
const div = `╟${repeat('─', W)}╢`;
|
|
50
|
+
const empty = `║${repeat(' ', W)}║`;
|
|
51
|
+
|
|
52
|
+
const logoLines = [
|
|
53
|
+
' ██████╗ ██╗ ██╗████████╗ ██████╗',
|
|
54
|
+
' ██╔═══██╗ ██║ ██║╚══██╔══╝██╔═══██╗',
|
|
55
|
+
' ███████║ ██║ ██║ ██║ ██║ ██║',
|
|
56
|
+
' ██╔══██║ ██║ ██║ ██║ ██║ ██║',
|
|
57
|
+
' ██║ ██║ ╚██████╔╝ ██║ ╚██████╔╝',
|
|
58
|
+
' ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ',
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
const pkg = require('./package.json');
|
|
62
|
+
|
|
63
|
+
console.log('');
|
|
64
|
+
console.log(c.cyan + c.bold + top + c.reset);
|
|
65
|
+
console.log(c.cyan + c.bold + empty + c.reset);
|
|
66
|
+
|
|
67
|
+
for (const line of logoLines) {
|
|
68
|
+
const inner = pad(c.yellow + c.bold + line + c.reset, W + (c.yellow + c.bold + c.reset).length * 2);
|
|
69
|
+
console.log(c.cyan + c.bold + '║' + c.reset + inner + c.cyan + c.bold + '║' + c.reset);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Pilot subtitle
|
|
73
|
+
const subtitle = '⚡ A N T I G R A V I T Y A U T O P I L O T ⚡';
|
|
74
|
+
const subInner = pad(c.white + c.bold + subtitle.padStart(Math.floor((W + subtitle.length) / 2)).padEnd(W) + c.reset,
|
|
75
|
+
W + (c.white + c.bold + c.reset).length * 2);
|
|
76
|
+
console.log(c.cyan + c.bold + '║' + c.reset + c.cyan + c.bold + empty.slice(1, -1) + c.reset + c.cyan + c.bold + '║' + c.reset);
|
|
77
|
+
console.log(c.cyan + c.bold + '║' + c.reset + subInner + c.cyan + c.bold + '║' + c.reset);
|
|
78
|
+
|
|
79
|
+
// Version line
|
|
80
|
+
const ver = `v${pkg.version} · MIT License · github.com/nguyenhx2/Antigravity-AutoPilot`;
|
|
81
|
+
const verInner = pad(c.gray + ver.padStart(Math.floor((W + ver.length) / 2)).padEnd(W) + c.reset,
|
|
82
|
+
W + (c.gray + c.reset).length * 2);
|
|
83
|
+
console.log(c.cyan + c.bold + '║' + c.reset + verInner + c.cyan + c.bold + '║' + c.reset);
|
|
84
|
+
|
|
85
|
+
console.log(c.cyan + c.bold + empty + c.reset);
|
|
86
|
+
console.log(c.cyan + c.bold + bot + c.reset);
|
|
87
|
+
console.log('');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ─── Help Screen ──────────────────────────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
function printHelp() {
|
|
93
|
+
const cmds = [
|
|
94
|
+
['(no args)', 'Apply the AutoPilot patch'],
|
|
95
|
+
['--check', 'Check current patch status'],
|
|
96
|
+
['--revert', 'Restore original files'],
|
|
97
|
+
['--help', 'Show this help screen'],
|
|
98
|
+
];
|
|
99
|
+
console.log(c.bold + c.white + ' USAGE' + c.reset);
|
|
100
|
+
console.log(c.gray + ' ─────────────────────────────────────────────' + c.reset);
|
|
101
|
+
console.log(' ' + c.cyan + 'npx antigravity-autopilot' + c.reset + c.gray + ' [option]' + c.reset + '\n');
|
|
102
|
+
console.log(c.bold + c.white + ' OPTIONS' + c.reset);
|
|
103
|
+
console.log(c.gray + ' ─────────────────────────────────────────────' + c.reset);
|
|
104
|
+
for (const [flag, desc] of cmds) {
|
|
105
|
+
console.log(' ' + c.yellow + c.bold + flag.padEnd(12) + c.reset + ' ' + c.white + desc + c.reset);
|
|
106
|
+
}
|
|
107
|
+
console.log('');
|
|
108
|
+
console.log(c.bold + c.white + ' WORKFLOW' + c.reset);
|
|
109
|
+
console.log(c.gray + ' ─────────────────────────────────────────────' + c.reset);
|
|
110
|
+
console.log(' ' + c.green + '1.' + c.reset + ' Run ' + c.cyan + 'npx antigravity-autopilot' + c.reset + ' → patch applied');
|
|
111
|
+
console.log(' ' + c.green + '2.' + c.reset + ' Restart Antigravity → AutoPilot active 🚀');
|
|
112
|
+
console.log(' ' + c.green + '3.' + c.reset + ' Run ' + c.cyan + '--revert' + c.reset + ' → undo anytime');
|
|
113
|
+
console.log('');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ─── Section header ───────────────────────────────────────────────────────────
|
|
117
|
+
|
|
118
|
+
function section(title, icon) {
|
|
119
|
+
const line = `${icon} ${title}`;
|
|
120
|
+
console.log(c.bold + c.white + line + c.reset);
|
|
121
|
+
console.log(c.gray + ' ' + repeat('─', W - 2) + c.reset);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ─── Installation Detection ───────────────────────────────────────────────────
|
|
23
125
|
|
|
24
126
|
function findAntigravityPath() {
|
|
25
127
|
const candidates = [];
|
|
@@ -62,47 +164,36 @@ function getVersion(basePath) {
|
|
|
62
164
|
} catch { return 'unknown'; }
|
|
63
165
|
}
|
|
64
166
|
|
|
65
|
-
// ─── Core Patch Logic
|
|
167
|
+
// ─── Core Patch Logic ─────────────────────────────────────────────────────────
|
|
66
168
|
|
|
67
169
|
function analyzeFile(content, label) {
|
|
68
|
-
|
|
69
|
-
const onChangeRe = /(\w+)=(\w+)\((\w+)=>\{\w+\?\.setTerminalAutoExecutionPolicy\?\.\(\3\),\3===(\w+)\.EAGER&&(\w+)\(!0\)\},\[[\w,]*\]\)/;
|
|
170
|
+
const onChangeRe = /(\w+)=(\w+)\((\w+)=>\{\w+\?\.setTerminalAutoExecutionPolicy\?\.\(\3\),\3===(\w+)\.EAGER\&\&(\w+)\(!0\)\},\[[\w,]*\]\)/;
|
|
70
171
|
const onChangeMatch = content.match(onChangeRe);
|
|
71
|
-
if (!onChangeMatch) {
|
|
72
|
-
console.log(` ❌ [${label}] Could not find onChange handler pattern`);
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
172
|
+
if (!onChangeMatch) { return null; }
|
|
75
173
|
|
|
76
174
|
const [fullMatch, , callbackAlias, , enumAlias, confirmFn] = onChangeMatch;
|
|
77
175
|
const matchIndex = content.indexOf(fullMatch);
|
|
78
|
-
console.log(` 📋 [${label}] Found onChange at offset ${matchIndex}`);
|
|
79
|
-
console.log(` callback=${callbackAlias}, enum=${enumAlias}, confirm=${confirmFn}`);
|
|
80
176
|
|
|
81
|
-
|
|
82
|
-
const policyRe = new RegExp(`(\\w+)=\\w+\\?\\.terminalAutoExecutionPolicy\\?\\?${enumAlias}\\.OFF`);
|
|
177
|
+
const policyRe = new RegExp(`(\\w+)=\\w+\\.terminalAutoExecutionPolicy\\?\\?${enumAlias}\\.OFF`);
|
|
83
178
|
const policyMatch = content.substring(Math.max(0, matchIndex - 2000), matchIndex).match(policyRe);
|
|
84
|
-
if (!policyMatch)
|
|
179
|
+
if (!policyMatch) return null;
|
|
85
180
|
const policyVar = policyMatch[1];
|
|
86
|
-
console.log(` policyVar=${policyVar}`);
|
|
87
181
|
|
|
88
|
-
// 3. Find secureMode variable: VAR=HANDLER?.secureModeEnabled??!1
|
|
89
182
|
const secureRe = /(\w+)=\w+\?\.secureModeEnabled\?\?!1/;
|
|
90
183
|
const secureMatch = content.substring(Math.max(0, matchIndex - 2000), matchIndex).match(secureRe);
|
|
91
|
-
if (!secureMatch)
|
|
184
|
+
if (!secureMatch) return null;
|
|
92
185
|
const secureVar = secureMatch[1];
|
|
93
|
-
console.log(` secureVar=${secureVar}`);
|
|
94
186
|
|
|
95
|
-
// 4. Find useEffect alias via frequency counting
|
|
96
187
|
const nearbyCode = content.substring(Math.max(0, matchIndex - 5000), matchIndex + 5000);
|
|
97
188
|
const effectCandidates = {};
|
|
98
|
-
const effectRe = /\b(\w{2,3})\(
|
|
189
|
+
const effectRe = /\b(\w{2,3})\(()=>\{[^}]{3,80}\},\[/g;
|
|
99
190
|
let m;
|
|
100
191
|
while ((m = effectRe.exec(nearbyCode)) !== null) {
|
|
101
192
|
const alias = m[1];
|
|
102
193
|
if (alias !== callbackAlias && alias !== 'var' && alias !== 'new')
|
|
103
194
|
effectCandidates[alias] = (effectCandidates[alias] || 0) + 1;
|
|
104
195
|
}
|
|
105
|
-
const cleanupRe = /\b(\w{2,3})\(
|
|
196
|
+
const cleanupRe = /\b(\w{2,3})\(()=>\{[^}]*return\s*()=>/g;
|
|
106
197
|
while ((m = cleanupRe.exec(content)) !== null) {
|
|
107
198
|
const alias = m[1];
|
|
108
199
|
if (alias !== callbackAlias)
|
|
@@ -113,10 +204,8 @@ function analyzeFile(content, label) {
|
|
|
113
204
|
for (const [alias, count] of Object.entries(effectCandidates)) {
|
|
114
205
|
if (count > maxCount) { maxCount = count; useEffectAlias = alias; }
|
|
115
206
|
}
|
|
116
|
-
if (!useEffectAlias)
|
|
117
|
-
console.log(` useEffect=${useEffectAlias} (confidence: ${maxCount} hits)`);
|
|
207
|
+
if (!useEffectAlias) return null;
|
|
118
208
|
|
|
119
|
-
// 5. Build patch
|
|
120
209
|
const patchCode = `_aep=${useEffectAlias}(()=>{${policyVar}===${enumAlias}.EAGER&&!${secureVar}&&${confirmFn}(!0)},[]),`;
|
|
121
210
|
return {
|
|
122
211
|
target: fullMatch,
|
|
@@ -125,107 +214,160 @@ function analyzeFile(content, label) {
|
|
|
125
214
|
};
|
|
126
215
|
}
|
|
127
216
|
|
|
128
|
-
// ─── File Operations
|
|
217
|
+
// ─── File Operations ──────────────────────────────────────────────────────────
|
|
129
218
|
|
|
130
219
|
function isPatched(filePath) {
|
|
131
220
|
if (!fs.existsSync(filePath)) return false;
|
|
132
221
|
const c = fs.readFileSync(filePath, 'utf8');
|
|
133
|
-
return c.includes('_aep=') && /_aep=\w+\(
|
|
222
|
+
return c.includes('_aep=') && /_aep=\w+\(()=>\{[^}]+EAGER/.test(c);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function row(icon, color, label, msg) {
|
|
226
|
+
console.log(' ' + color + icon + c.reset + ' ' + c.bold + label.padEnd(14) + c.reset + c.gray + msg + c.reset);
|
|
134
227
|
}
|
|
135
228
|
|
|
136
229
|
function patchFile(filePath, label) {
|
|
137
230
|
if (!fs.existsSync(filePath)) {
|
|
138
|
-
|
|
231
|
+
row('⊘', c.gray, `[${label}]`, 'File not found — skipping');
|
|
139
232
|
return true;
|
|
140
233
|
}
|
|
141
234
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
142
235
|
if (isPatched(filePath)) {
|
|
143
|
-
|
|
236
|
+
row('✔', c.green, `[${label}]`, 'Already patched');
|
|
144
237
|
return true;
|
|
145
238
|
}
|
|
146
239
|
const analysis = analyzeFile(content, label);
|
|
147
|
-
if (!analysis)
|
|
240
|
+
if (!analysis) {
|
|
241
|
+
row('✖', c.red, `[${label}]`, 'Pattern not found — may be incompatible version');
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
148
244
|
|
|
149
245
|
const count = content.split(analysis.target).length - 1;
|
|
150
|
-
if (count !== 1) {
|
|
246
|
+
if (count !== 1) {
|
|
247
|
+
row('✖', c.red, `[${label}]`, `Target found ${count}× (expected 1)`);
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
151
250
|
|
|
152
251
|
const bak = filePath + '.bak';
|
|
153
|
-
if (!fs.existsSync(bak)) {
|
|
252
|
+
if (!fs.existsSync(bak)) {
|
|
253
|
+
fs.copyFileSync(filePath, bak);
|
|
254
|
+
row('◈', c.blue, `[${label}]`, 'Backup created (.bak)');
|
|
255
|
+
}
|
|
154
256
|
|
|
155
257
|
fs.writeFileSync(filePath, content.replace(analysis.target, analysis.replacement), 'utf8');
|
|
156
258
|
const diff = fs.statSync(filePath).size - fs.statSync(bak).size;
|
|
157
|
-
|
|
259
|
+
row('✔', c.green, `[${label}]`, `Patched successfully (+${diff} bytes)`);
|
|
158
260
|
return true;
|
|
159
261
|
}
|
|
160
262
|
|
|
161
263
|
function revertFile(filePath, label) {
|
|
162
264
|
const bak = filePath + '.bak';
|
|
163
|
-
if (!fs.existsSync(bak)) {
|
|
265
|
+
if (!fs.existsSync(bak)) {
|
|
266
|
+
row('⊘', c.gray, `[${label}]`, 'No backup found — skipping');
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
164
269
|
fs.copyFileSync(bak, filePath);
|
|
165
|
-
|
|
270
|
+
row('✔', c.green, `[${label}]`, 'Restored from backup');
|
|
166
271
|
}
|
|
167
272
|
|
|
168
273
|
function checkFile(filePath, label) {
|
|
169
|
-
if (!fs.existsSync(filePath)) {
|
|
274
|
+
if (!fs.existsSync(filePath)) {
|
|
275
|
+
row('✖', c.red, `[${label}]`, 'File not found');
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
170
278
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
171
279
|
const patched = isPatched(filePath);
|
|
172
280
|
const hasBak = fs.existsSync(filePath + '.bak');
|
|
281
|
+
const analysis = !patched ? analyzeFile(content, label) : null;
|
|
282
|
+
|
|
173
283
|
if (patched) {
|
|
174
|
-
|
|
284
|
+
row('✔', c.green, `[${label}]`, 'PATCHED' + (hasBak ? ' · backup exists' : ''));
|
|
285
|
+
} else if (analysis) {
|
|
286
|
+
row('○', c.yellow, `[${label}]`, 'NOT PATCHED · patchable, ready to apply');
|
|
175
287
|
} else {
|
|
176
|
-
|
|
177
|
-
console.log(analysis ? ` ⬜ [${label}] NOT PATCHED (patchable)` : ` ⚠️ [${label}] NOT PATCHED (may be incompatible)`);
|
|
288
|
+
row('⚠', c.yellow, `[${label}]`, 'NOT PATCHED · may be incompatible');
|
|
178
289
|
}
|
|
179
290
|
return patched;
|
|
180
291
|
}
|
|
181
292
|
|
|
182
|
-
// ─── Main
|
|
293
|
+
// ─── Main ─────────────────────────────────────────────────────────────────────
|
|
183
294
|
|
|
184
295
|
function main() {
|
|
185
296
|
const args = process.argv.slice(2);
|
|
186
|
-
const action = args.includes('--revert') ? 'revert'
|
|
297
|
+
const action = args.includes('--revert') ? 'revert'
|
|
298
|
+
: args.includes('--check') ? 'check'
|
|
299
|
+
: args.includes('--help') ? 'help'
|
|
300
|
+
: 'apply';
|
|
187
301
|
|
|
188
|
-
|
|
189
|
-
console.log('╔══════════════════════════════════════════╗');
|
|
190
|
-
console.log('║ ⚡ Antigravity AutoPilot ║');
|
|
191
|
-
console.log('╚══════════════════════════════════════════╝');
|
|
302
|
+
printBanner();
|
|
192
303
|
|
|
304
|
+
if (action === 'help') { printHelp(); return; }
|
|
305
|
+
|
|
306
|
+
// ── Locate Antigravity ──
|
|
193
307
|
const basePath = findAntigravityPath();
|
|
308
|
+
|
|
309
|
+
console.log(' ' + c.gray + '📍 Installation' + c.reset);
|
|
194
310
|
if (!basePath) {
|
|
195
|
-
console.log('
|
|
311
|
+
console.log(' ' + c.red + c.bold + '✖ Antigravity not found.' + c.reset);
|
|
312
|
+
console.log(' Install Antigravity from ' + c.cyan + 'https://antigravity.dev' + c.reset + ' first.\n');
|
|
196
313
|
process.exit(1);
|
|
197
314
|
}
|
|
198
|
-
|
|
199
|
-
console.log(
|
|
200
|
-
console.log(
|
|
315
|
+
console.log(' ' + c.white + basePath + c.reset);
|
|
316
|
+
console.log(' ' + c.gray + `Version: ${getVersion(basePath)}` + c.reset);
|
|
317
|
+
console.log('');
|
|
201
318
|
|
|
202
319
|
const files = getTargetFiles(basePath);
|
|
203
320
|
|
|
321
|
+
// ── Action ──
|
|
204
322
|
switch (action) {
|
|
205
|
-
case 'check':
|
|
206
|
-
|
|
323
|
+
case 'check': {
|
|
324
|
+
section('Status Check', '🔍');
|
|
325
|
+
console.log('');
|
|
207
326
|
files.forEach(f => checkFile(f.filePath, f.label));
|
|
327
|
+
console.log('');
|
|
328
|
+
const allPatched = files.every(f => isPatched(f.filePath));
|
|
329
|
+
if (allPatched) {
|
|
330
|
+
console.log(' ' + c.green + c.bold + '✔ AutoPilot is ACTIVE on this machine.' + c.reset);
|
|
331
|
+
console.log(' ' + c.gray + 'Restart Antigravity for changes to take effect.' + c.reset);
|
|
332
|
+
} else {
|
|
333
|
+
console.log(' ' + c.yellow + ' Run ' + c.cyan + 'npx antigravity-autopilot' + c.yellow + ' to activate AutoPilot.' + c.reset);
|
|
334
|
+
}
|
|
335
|
+
console.log('');
|
|
208
336
|
break;
|
|
337
|
+
}
|
|
209
338
|
|
|
210
|
-
case 'revert':
|
|
211
|
-
|
|
339
|
+
case 'revert': {
|
|
340
|
+
section('Reverting Patch', '↩');
|
|
341
|
+
console.log('');
|
|
212
342
|
files.forEach(f => revertFile(f.filePath, f.label));
|
|
213
|
-
console.log('
|
|
343
|
+
console.log('');
|
|
344
|
+
console.log(' ' + c.green + c.bold + '✔ Restored!' + c.reset + c.white + ' Restart Antigravity to apply changes.' + c.reset);
|
|
345
|
+
console.log('');
|
|
214
346
|
break;
|
|
347
|
+
}
|
|
215
348
|
|
|
216
349
|
case 'apply':
|
|
217
|
-
default:
|
|
218
|
-
|
|
350
|
+
default: {
|
|
351
|
+
section('Applying AutoPilot Patch', '⚡');
|
|
352
|
+
console.log('');
|
|
219
353
|
const ok = files.every(f => patchFile(f.filePath, f.label));
|
|
354
|
+
console.log('');
|
|
220
355
|
if (ok) {
|
|
221
|
-
console.log('
|
|
222
|
-
console.log('
|
|
223
|
-
console.log('
|
|
356
|
+
console.log(' ┌' + repeat('─', W - 2) + '┐');
|
|
357
|
+
console.log(' │' + pad(c.green + c.bold + ' ✔ Patch applied successfully!' + c.reset, W - 2 + (c.green + c.bold + c.reset).length * 2) + '│');
|
|
358
|
+
console.log(' │' + pad(c.white + ' Restart Antigravity to activate AutoPilot.' + c.reset, W - 2 + (c.white + c.reset).length * 2) + '│');
|
|
359
|
+
console.log(' │' + repeat(' ', W - 2) + '│');
|
|
360
|
+
console.log(' │' + pad(c.gray + ' 💡 Run with --revert to undo at any time.' + c.reset, W - 2 + (c.gray + c.reset).length * 2) + '│');
|
|
361
|
+
console.log(' │' + pad(c.gray + ' ⚠ Re-run this command after Antigravity updates.' + c.reset, W - 2 + (c.gray + c.reset).length * 2) + '│');
|
|
362
|
+
console.log(' └' + repeat('─', W - 2) + '┘');
|
|
224
363
|
} else {
|
|
225
|
-
console.log('
|
|
364
|
+
console.log(' ' + c.red + c.bold + '✖ Some files could not be patched.' + c.reset);
|
|
365
|
+
console.log(' ' + c.gray + 'Check output above for details.' + c.reset);
|
|
226
366
|
process.exit(1);
|
|
227
367
|
}
|
|
368
|
+
console.log('');
|
|
228
369
|
break;
|
|
370
|
+
}
|
|
229
371
|
}
|
|
230
372
|
}
|
|
231
373
|
|