antigravity-autopilot 1.1.0 → 1.2.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/extension.js +379 -96
- package/package.json +34 -7
package/extension.js
CHANGED
|
@@ -16,6 +16,142 @@ let isPatchApplied = false;
|
|
|
16
16
|
let panelProvider = null;
|
|
17
17
|
/** @type {{ basePath: string|null, files: any[], patched: boolean } | null} */
|
|
18
18
|
let _cachedStatus = null;
|
|
19
|
+
/** @type {boolean} */
|
|
20
|
+
let autoPilotEnabled = true;
|
|
21
|
+
/** @type {vscode.OutputChannel} */
|
|
22
|
+
let outputChannel;
|
|
23
|
+
|
|
24
|
+
// ─── Dangerous Command Blocking ───────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Built-in dangerous command patterns.
|
|
28
|
+
* Covers Linux/macOS/Windows destructive commands.
|
|
29
|
+
* Each entry: { pattern: RegExp, label: string, os: string[] }
|
|
30
|
+
*/
|
|
31
|
+
const BUILTIN_DANGEROUS_PATTERNS = [
|
|
32
|
+
// ── Linux / macOS ──
|
|
33
|
+
{ pattern: /rm\s+(-[a-zA-Z]*f[a-zA-Z]*\s+|--force\s+).*\/(\s|$)/, label: 'rm -rf /', os: ['linux', 'darwin'] },
|
|
34
|
+
{ pattern: /rm\s+-[a-zA-Z]*r[a-zA-Z]*\s+\/(\s|$)/, label: 'rm -r / (root wipe)', os: ['linux', 'darwin'] },
|
|
35
|
+
{ pattern: /rm\s+-[a-zA-Z]*r[a-zA-Z]*\s+~(\s|$|\/)/, label: 'rm -r ~ (home wipe)', os: ['linux', 'darwin'] },
|
|
36
|
+
{ pattern: /rm\s+.*--no-preserve-root/, label: 'rm --no-preserve-root', os: ['linux', 'darwin'] },
|
|
37
|
+
{ pattern: /:\(\)\s*\{.*:\|:&\s*\};\s*:/, label: 'Fork bomb :(){:|:&};:', os: ['linux', 'darwin'] },
|
|
38
|
+
{ pattern: /mkfs\.(ext[234]|xfs|btrfs|vfat|ntfs)\s+\/dev\/(sd|hd|nvme|vd)/, label: 'mkfs on block device', os: ['linux', 'darwin'] },
|
|
39
|
+
{ pattern: /dd\s+.*of=\/dev\/(sd[a-z]|hd[a-z]|nvme\d+|zero|null)/, label: 'dd overwrite device', os: ['linux', 'darwin'] },
|
|
40
|
+
{ pattern: />\s*\/dev\/(sd[a-z]|hd[a-z]|nvme\d+)/, label: 'Redirect to block device', os: ['linux', 'darwin'] },
|
|
41
|
+
{ pattern: /shred\s+(-[a-zA-Z]*n\s*\d+\s+)?\/dev\//, label: 'shred device', os: ['linux', 'darwin'] },
|
|
42
|
+
{ pattern: /mv\s+.*\s+\/dev\/null/, label: 'mv to /dev/null', os: ['linux', 'darwin'] },
|
|
43
|
+
{ pattern: /chmod\s+-[rR]\s+000\s+\//, label: 'chmod 000 recursive on /', os: ['linux', 'darwin'] },
|
|
44
|
+
{ pattern: /chmod\s+777\s+-R\s+\/(\s|$)/, label: 'chmod 777 -R /', os: ['linux', 'darwin'] },
|
|
45
|
+
{ pattern: /chown\s+.*-R\s+.*\s+\/(\s|$)/, label: 'chown -R on /', os: ['linux', 'darwin'] },
|
|
46
|
+
{ pattern: /passwd\s+root\s*$/, label: 'passwd root (no new password)', os: ['linux', 'darwin'] },
|
|
47
|
+
{ pattern: /sudo\s+rm\s+-[a-zA-Z]*rf?\s+\/(\s|$)/, label: 'sudo rm -rf /', os: ['linux', 'darwin'] },
|
|
48
|
+
{ pattern: /wget\s+.*\|\s*(ba)?sh/, label: 'wget pipe to shell', os: ['linux', 'darwin'] },
|
|
49
|
+
{ pattern: /curl\s+.*\|\s*(ba)?sh/, label: 'curl pipe to shell', os: ['linux', 'darwin'] },
|
|
50
|
+
{ pattern: /base64\s+-d.*\|\s*(ba)?sh/, label: 'base64 decode pipe to shell', os: ['linux', 'darwin'] },
|
|
51
|
+
{ pattern: /eval\s+\$\(.*\)/, label: 'eval $(...) subshell', os: ['linux', 'darwin'] },
|
|
52
|
+
{ pattern: /fdisk\s+\/dev\/(sd[a-z]|nvme\d+)/, label: 'fdisk on disk', os: ['linux', 'darwin'] },
|
|
53
|
+
{ pattern: /parted\s+\/dev\/(sd[a-z]|nvme\d+)/, label: 'parted on disk', os: ['linux', 'darwin'] },
|
|
54
|
+
{ pattern: /wipefs\s+.*\/dev\//, label: 'wipefs on device', os: ['linux', 'darwin'] },
|
|
55
|
+
{ pattern: /truncate\s+-s\s+0\s+\/dev\//, label: 'truncate device to 0', os: ['linux', 'darwin'] },
|
|
56
|
+
{ pattern: /echo\s+.*>\s*\/boot\//, label: 'overwrite /boot/', os: ['linux', 'darwin'] },
|
|
57
|
+
{ pattern: /cat\s+\/dev\/zero\s+>\s+\//, label: 'cat /dev/zero to /', os: ['linux', 'darwin'] },
|
|
58
|
+
{ pattern: /umount\s+-a/, label: 'umount -a (unmount all)', os: ['linux', 'darwin'] },
|
|
59
|
+
{ pattern: /init\s+0/, label: 'init 0 (halt system)', os: ['linux', 'darwin'] },
|
|
60
|
+
{ pattern: /poweroff|halt\s*$/, label: 'System shutdown command', os: ['linux', 'darwin'] },
|
|
61
|
+
{ pattern: /iptables\s+-F/, label: 'iptables -F (flush all rules)', os: ['linux', 'darwin'] },
|
|
62
|
+
{ pattern: /ufw\s+--force\s+reset/, label: 'ufw --force reset', os: ['linux', 'darwin'] },
|
|
63
|
+
// ── macOS specific ──
|
|
64
|
+
{ pattern: /diskutil\s+(eraseDisk|eraseVolume|partitionDisk)\s+/, label: 'diskutil erase/repartition', os: ['darwin'] },
|
|
65
|
+
{ pattern: /diskutil\s+zeroDisk\s+/, label: 'diskutil zeroDisk', os: ['darwin'] },
|
|
66
|
+
{ pattern: /csrutil\s+disable/, label: 'csrutil disable (SIP)', os: ['darwin'] },
|
|
67
|
+
// ── Windows (PowerShell / cmd) ──
|
|
68
|
+
{ pattern: /Format-Volume\s+.*-Confirm:\s*\$false/i, label: 'Format-Volume without confirm', os: ['win32'] },
|
|
69
|
+
{ pattern: /format\s+[cC]:\s*\/[qQy]/i, label: 'format C: /q or /y', os: ['win32'] },
|
|
70
|
+
{ pattern: /format\s+[a-zA-Z]:\s*\/[qQy]/i, label: 'format <drive> /q or /y', os: ['win32'] },
|
|
71
|
+
{ pattern: /del\s+\/[fsqSFQ]+\s+[cC]:\\/i, label: 'del /f/s/q C:\\ (wipe drive)', os: ['win32'] },
|
|
72
|
+
{ pattern: /rd\s+\/[sq]+\s+[cC]:\\/i, label: 'rd /s/q C:\\ (remove all)', os: ['win32'] },
|
|
73
|
+
{ pattern: /Remove-Item\s+.*-Recurse\s+.*-Force.*[cC]:\\/i, label: 'Remove-Item -Recurse -Force C:\\', os: ['win32'] },
|
|
74
|
+
{ pattern: /Remove-Item\s+.*-Recurse\s+.*-Force\s+\/\s/i, label: 'Remove-Item -Recurse -Force /', os: ['win32'] },
|
|
75
|
+
{ pattern: /Set-ExecutionPolicy\s+Unrestricted\s+-Force/i, label: 'Set-ExecutionPolicy Unrestricted -Force', os: ['win32'] },
|
|
76
|
+
{ pattern: /reg\s+(delete|add)\s+HKLM\\SYSTEM\\CurrentControlSet/i, label: 'reg delete HKLM\\SYSTEM critical', os: ['win32'] },
|
|
77
|
+
{ pattern: /bcdedit\s+\/deletevalue/i, label: 'bcdedit /deletevalue (boot config)', os: ['win32'] },
|
|
78
|
+
{ pattern: /bcdedit\s+\/set.*safeboot/i, label: 'bcdedit /set safeboot (forces safe mode)', os: ['win32'] },
|
|
79
|
+
{ pattern: /cipher\s+\/w:[cC]:\\/i, label: 'cipher /w:C:\\ (wipe free space)', os: ['win32'] },
|
|
80
|
+
{ pattern: /sfc\s+\/scannow.*\/offwindir/i, label: 'sfc offline (system repair risk)', os: ['win32'] },
|
|
81
|
+
{ pattern: /wmic\s+.*delete/i, label: 'wmic delete', os: ['win32'] },
|
|
82
|
+
{ pattern: /Invoke-Expression\s+\(.*Download.*\)/i, label: 'IEX download-and-execute', os: ['win32'] },
|
|
83
|
+
{ pattern: /iex\s+\(.*WebClient.*DownloadString/i, label: 'iex WebClient DownloadString (remote exec)', os: ['win32'] },
|
|
84
|
+
{ pattern: /powershell\s+.*-EncodedCommand/i, label: 'powershell -EncodedCommand (obfuscated)', os: ['win32'] },
|
|
85
|
+
{ pattern: /net\s+user\s+administrator\s+\*?\s*\/active:yes/i, label: 'net user administrator enable', os: ['win32'] },
|
|
86
|
+
{ pattern: /takeown\s+\/f\s+[cC]:\\/i, label: 'takeown /f C:\\ (ownership grab)', os: ['win32'] },
|
|
87
|
+
{ pattern: /icacls\s+[cC]:\\\s+\/grant/i, label: 'icacls C:\\ /grant (permission escalation)', os: ['win32'] },
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Checks a command string against built-in + custom dangerous patterns.
|
|
92
|
+
* @param {string} cmd
|
|
93
|
+
* @returns {{ matched: boolean, label: string, pattern: string }}
|
|
94
|
+
*/
|
|
95
|
+
function checkDangerousCommand(cmd) {
|
|
96
|
+
const cfg = vscode.workspace.getConfiguration('antigravityAutoAccept');
|
|
97
|
+
const enabled = cfg.get('dangerousCommandBlocking.enabled', true);
|
|
98
|
+
if (!enabled) return { matched: false, label: '', pattern: '' };
|
|
99
|
+
|
|
100
|
+
const platform = process.platform; // 'win32' | 'linux' | 'darwin'
|
|
101
|
+
const trimmed = cmd.trim();
|
|
102
|
+
|
|
103
|
+
// Check built-in patterns (platform-filtered)
|
|
104
|
+
for (const entry of BUILTIN_DANGEROUS_PATTERNS) {
|
|
105
|
+
if (!entry.os.includes(platform)) continue;
|
|
106
|
+
if (entry.pattern.test(trimmed)) {
|
|
107
|
+
return { matched: true, label: entry.label, pattern: entry.pattern.toString() };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Check custom user patterns
|
|
112
|
+
const customPatterns = /** @type {string[]} */ (cfg.get('dangerousCommandBlocking.customPatterns', []));
|
|
113
|
+
for (const raw of customPatterns) {
|
|
114
|
+
try {
|
|
115
|
+
const re = new RegExp(raw, 'i');
|
|
116
|
+
if (re.test(trimmed)) {
|
|
117
|
+
return { matched: true, label: `Custom: ${raw}`, pattern: raw };
|
|
118
|
+
}
|
|
119
|
+
} catch {
|
|
120
|
+
// Invalid regex — skip silently
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return { matched: false, label: '', pattern: '' };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Handles a detected dangerous command according to the configured action.
|
|
129
|
+
* @param {string} cmd - The full command text
|
|
130
|
+
* @param {string} label - Human-readable reason
|
|
131
|
+
*/
|
|
132
|
+
function handleDangerousCommand(cmd, label) {
|
|
133
|
+
const cfg = vscode.workspace.getConfiguration('antigravityAutoAccept');
|
|
134
|
+
const action = cfg.get('dangerousCommandBlocking.action', 'block');
|
|
135
|
+
const msg = `🛡️ Dangerous command detected: "${label}" — \`${cmd.trim().substring(0, 80)}\``;
|
|
136
|
+
|
|
137
|
+
outputChannel.appendLine(`[DangerBlock][${new Date().toISOString()}] ${action.toUpperCase()} | ${label} | CMD: ${cmd.trim()}`);
|
|
138
|
+
|
|
139
|
+
if (action === 'block') {
|
|
140
|
+
vscode.window.showErrorMessage(
|
|
141
|
+
`⛔ Blocked: ${label}`,
|
|
142
|
+
{ modal: false },
|
|
143
|
+
'View Details',
|
|
144
|
+
).then((choice) => {
|
|
145
|
+
if (choice === 'View Details') {
|
|
146
|
+
outputChannel.show(true);
|
|
147
|
+
outputChannel.appendLine(`[DangerBlock] Blocked command: ${cmd.trim()}`);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
} else if (action === 'warn') {
|
|
151
|
+
vscode.window.showWarningMessage(`⚠️ Warning: ${msg}`);
|
|
152
|
+
}
|
|
153
|
+
// 'log' — already logged above, no UI notification
|
|
154
|
+
}
|
|
19
155
|
|
|
20
156
|
// ─── Child Process Bridge ─────────────────────────────────────────────────────
|
|
21
157
|
|
|
@@ -28,21 +164,20 @@ let _cachedStatus = null;
|
|
|
28
164
|
function runPatcher(command) {
|
|
29
165
|
return new Promise((resolve, reject) => {
|
|
30
166
|
const child = fork(PATCHER, [], { silent: true });
|
|
31
|
-
const channel = vscode.window.createOutputChannel('AutoPilot');
|
|
32
167
|
|
|
33
168
|
child.on('message', (msg) => {
|
|
34
169
|
if (!msg || typeof msg !== 'object') return;
|
|
35
170
|
const m = /** @type {{type:string,msg?:string}} */(msg);
|
|
36
171
|
if (m.type === 'log') {
|
|
37
172
|
console.log(m.msg);
|
|
38
|
-
|
|
173
|
+
outputChannel.appendLine(m.msg || '');
|
|
39
174
|
} else {
|
|
40
|
-
resolve(msg);
|
|
175
|
+
resolve(msg);
|
|
41
176
|
}
|
|
42
177
|
});
|
|
43
178
|
|
|
44
179
|
child.on('error', (err) => {
|
|
45
|
-
|
|
180
|
+
outputChannel.appendLine(`[AutoPilot] fork error: ${err.message}`);
|
|
46
181
|
reject(err);
|
|
47
182
|
});
|
|
48
183
|
|
|
@@ -51,7 +186,7 @@ function runPatcher(command) {
|
|
|
51
186
|
resolve({
|
|
52
187
|
type: 'result',
|
|
53
188
|
success: false,
|
|
54
|
-
message: `Process exited with code ${code}. Check Output >
|
|
189
|
+
message: `Process exited with code ${code}. Check Output > AutoPilot for details.`,
|
|
55
190
|
});
|
|
56
191
|
}
|
|
57
192
|
});
|
|
@@ -116,7 +251,32 @@ async function refreshStatus() {
|
|
|
116
251
|
if (panelProvider) panelProvider.sendStatus(status);
|
|
117
252
|
}
|
|
118
253
|
|
|
119
|
-
// ───
|
|
254
|
+
// ─── Status Bar ───────────────────────────────────────────────────────────────
|
|
255
|
+
|
|
256
|
+
function updateStatusBarFromCache() {
|
|
257
|
+
if (!statusBarItem) return;
|
|
258
|
+
if (!autoPilotEnabled) {
|
|
259
|
+
statusBarItem.text = '$(debug-pause) AG Paused';
|
|
260
|
+
statusBarItem.tooltip = 'Antigravity AutoPilot is suspended';
|
|
261
|
+
statusBarItem.color = new vscode.ThemeColor('statusBarItem.warningForeground');
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (!_cachedStatus || !_cachedStatus.basePath) {
|
|
265
|
+
statusBarItem.text = '$(warning) AG: Not Found';
|
|
266
|
+
statusBarItem.tooltip = 'Antigravity not found on this system';
|
|
267
|
+
statusBarItem.color = new vscode.ThemeColor('statusBarItem.errorForeground');
|
|
268
|
+
} else if (_cachedStatus.patched) {
|
|
269
|
+
statusBarItem.text = '$(zap) AG: Active';
|
|
270
|
+
statusBarItem.tooltip = 'Antigravity AutoPilot — Patch Applied ✅';
|
|
271
|
+
statusBarItem.color = new vscode.ThemeColor('statusBarItem.prominentForeground');
|
|
272
|
+
} else {
|
|
273
|
+
statusBarItem.text = '$(circle-slash) AG: Inactive';
|
|
274
|
+
statusBarItem.tooltip = 'Antigravity AutoPilot — Patch Not Applied';
|
|
275
|
+
statusBarItem.color = undefined;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// ─── Sidebar WebView ──────────────────────────────────────────────────────────
|
|
120
280
|
|
|
121
281
|
class AntigravityPanelProvider {
|
|
122
282
|
/** @param {vscode.ExtensionContext} context */
|
|
@@ -144,11 +304,24 @@ class AntigravityPanelProvider {
|
|
|
144
304
|
} else if (msg.command === 'refresh') {
|
|
145
305
|
this._postLoading('⏳ Checking...');
|
|
146
306
|
await refreshStatus();
|
|
307
|
+
} else if (msg.command === 'toggleEnabled') {
|
|
308
|
+
autoPilotEnabled = !autoPilotEnabled;
|
|
309
|
+
updateStatusBarFromCache();
|
|
310
|
+
// Persist into workspace config
|
|
311
|
+
const cfg = vscode.workspace.getConfiguration('antigravityAutoAccept');
|
|
312
|
+
await cfg.update('enabledOnStartup', autoPilotEnabled, vscode.ConfigurationTarget.Global);
|
|
313
|
+
if (panelProvider) panelProvider.sendEnabled(autoPilotEnabled);
|
|
314
|
+
vscode.window.showInformationMessage(
|
|
315
|
+
autoPilotEnabled ? '⚡ AutoPilot resumed' : '⏸ AutoPilot suspended',
|
|
316
|
+
);
|
|
317
|
+
} else if (msg.command === 'openSettings') {
|
|
318
|
+
vscode.commands.executeCommand('workbench.action.openSettings', 'antigravityAutoAccept');
|
|
147
319
|
}
|
|
148
320
|
});
|
|
149
321
|
|
|
150
322
|
// Initial load
|
|
151
323
|
refreshStatus();
|
|
324
|
+
this.sendEnabled(autoPilotEnabled);
|
|
152
325
|
}
|
|
153
326
|
|
|
154
327
|
/** @param {string} text */
|
|
@@ -167,8 +340,11 @@ class AntigravityPanelProvider {
|
|
|
167
340
|
});
|
|
168
341
|
}
|
|
169
342
|
|
|
170
|
-
/** @
|
|
171
|
-
|
|
343
|
+
/** @param {boolean} enabled */
|
|
344
|
+
sendEnabled(enabled) {
|
|
345
|
+
if (!this._view) return;
|
|
346
|
+
this._view.webview.postMessage({ command: 'setEnabled', enabled });
|
|
347
|
+
}
|
|
172
348
|
|
|
173
349
|
_getHtml() {
|
|
174
350
|
return /* html */`<!DOCTYPE html>
|
|
@@ -182,80 +358,133 @@ class AntigravityPanelProvider {
|
|
|
182
358
|
font-family:'Segoe UI',sans-serif;
|
|
183
359
|
background:var(--vscode-sideBar-background);
|
|
184
360
|
color:var(--vscode-foreground);
|
|
185
|
-
padding:
|
|
361
|
+
padding:12px;user-select:none;
|
|
186
362
|
}
|
|
363
|
+
|
|
364
|
+
/* ── Header ── */
|
|
187
365
|
.header{
|
|
188
366
|
display:flex;align-items:center;gap:8px;
|
|
189
|
-
margin-bottom:
|
|
367
|
+
margin-bottom:12px;padding-bottom:10px;
|
|
190
368
|
border-bottom:1px solid var(--vscode-panel-border);
|
|
191
369
|
}
|
|
192
|
-
.header-icon{font-size:
|
|
370
|
+
.header-icon{font-size:18px}
|
|
193
371
|
.header-title{font-size:13px;font-weight:600;letter-spacing:.3px}
|
|
194
|
-
.header-sub{font-size:
|
|
372
|
+
.header-sub{font-size:10px;color:var(--vscode-descriptionForeground);margin-top:2px}
|
|
195
373
|
|
|
374
|
+
/* ── Toggle Row ── */
|
|
375
|
+
.toggle-row{
|
|
376
|
+
display:flex;align-items:center;justify-content:space-between;
|
|
377
|
+
background:var(--vscode-editor-background);
|
|
378
|
+
border:1px solid var(--vscode-panel-border);
|
|
379
|
+
border-radius:6px;padding:8px 10px;margin-bottom:10px;
|
|
380
|
+
}
|
|
381
|
+
.toggle-label{font-size:11px;font-weight:600}
|
|
382
|
+
.toggle-sub{font-size:10px;color:var(--vscode-descriptionForeground);margin-top:1px}
|
|
383
|
+
.switch{position:relative;display:inline-block;width:34px;height:18px;flex-shrink:0}
|
|
384
|
+
.switch input{opacity:0;width:0;height:0}
|
|
385
|
+
.slider{
|
|
386
|
+
position:absolute;cursor:pointer;inset:0;
|
|
387
|
+
background:#555;border-radius:18px;
|
|
388
|
+
transition:background .2s;
|
|
389
|
+
}
|
|
390
|
+
.slider:before{
|
|
391
|
+
position:absolute;content:'';height:14px;width:14px;
|
|
392
|
+
left:2px;bottom:2px;background:#fff;border-radius:50%;
|
|
393
|
+
transition:transform .2s;
|
|
394
|
+
}
|
|
395
|
+
input:checked + .slider{background:#4ec94e}
|
|
396
|
+
input:checked + .slider:before{transform:translateX(16px)}
|
|
397
|
+
|
|
398
|
+
/* ── Status card ── */
|
|
196
399
|
.status-card{
|
|
197
|
-
border-radius:
|
|
400
|
+
border-radius:6px;padding:12px;margin-bottom:10px;
|
|
198
401
|
background:var(--vscode-editor-background);
|
|
199
402
|
border:1px solid var(--vscode-panel-border);
|
|
200
403
|
transition:border-color .3s,background .3s;
|
|
201
404
|
}
|
|
202
405
|
.status-card.patched{border-color:#4ec94e;background:rgba(78,201,78,.07)}
|
|
203
406
|
.status-card.not-found{border-color:#e06c75;background:rgba(224,108,117,.07)}
|
|
204
|
-
.status-row{display:flex;align-items:center;gap:
|
|
407
|
+
.status-row{display:flex;align-items:center;gap:10px}
|
|
205
408
|
.dot{
|
|
206
|
-
width:
|
|
409
|
+
width:32px;height:32px;border-radius:50%;
|
|
207
410
|
display:flex;align-items:center;justify-content:center;
|
|
208
|
-
font-size:
|
|
411
|
+
font-size:16px;flex-shrink:0;background:#3c3c3c;
|
|
209
412
|
transition:background .3s;
|
|
210
413
|
}
|
|
211
414
|
.dot.patched{background:#4ec94e}
|
|
212
415
|
.dot.not-found{background:#e06c75}
|
|
213
|
-
.status-label{font-size:
|
|
416
|
+
.status-label{font-size:16px;font-weight:700;line-height:1}
|
|
214
417
|
.status-label.patched{color:#4ec94e}
|
|
215
418
|
.status-label.pending{color:#e5c07b}
|
|
216
419
|
.status-label.not-found{color:#e06c75}
|
|
217
420
|
.status-label.loading{color:var(--vscode-descriptionForeground)}
|
|
218
|
-
.status-desc{font-size:
|
|
421
|
+
.status-desc{font-size:10px;color:var(--vscode-descriptionForeground);margin-top:3px}
|
|
422
|
+
|
|
423
|
+
/* ── Security section ── */
|
|
424
|
+
.section{
|
|
425
|
+
border:1px solid var(--vscode-panel-border);
|
|
426
|
+
border-radius:6px;margin-bottom:10px;overflow:hidden;
|
|
427
|
+
}
|
|
428
|
+
.section-header{
|
|
429
|
+
display:flex;align-items:center;justify-content:space-between;
|
|
430
|
+
padding:7px 10px;
|
|
431
|
+
background:var(--vscode-editor-background);
|
|
432
|
+
font-size:11px;font-weight:600;
|
|
433
|
+
border-bottom:1px solid var(--vscode-panel-border);
|
|
434
|
+
}
|
|
435
|
+
.section-header .badge{
|
|
436
|
+
font-size:9px;padding:1px 6px;border-radius:10px;
|
|
437
|
+
background:#e06c75;color:#fff;font-weight:700;
|
|
438
|
+
}
|
|
439
|
+
.section-header .badge.on{background:#4ec94e}
|
|
440
|
+
.blocklist{padding:6px 10px}
|
|
441
|
+
.block-item{
|
|
442
|
+
display:flex;align-items:center;gap:5px;
|
|
443
|
+
font-size:10px;padding:2px 0;color:var(--vscode-descriptionForeground);
|
|
444
|
+
}
|
|
445
|
+
.block-dot{
|
|
446
|
+
width:5px;height:5px;border-radius:50%;background:#e5c07b;flex-shrink:0;
|
|
447
|
+
}
|
|
219
448
|
|
|
449
|
+
/* ── Path box ── */
|
|
220
450
|
.path-box{
|
|
221
|
-
font-size:
|
|
451
|
+
font-size:9px;color:var(--vscode-descriptionForeground);
|
|
222
452
|
background:var(--vscode-editor-background);
|
|
223
453
|
border:1px solid var(--vscode-panel-border);
|
|
224
|
-
border-radius:4px;padding:6px
|
|
454
|
+
border-radius:4px;padding:4px 6px;margin-bottom:8px;
|
|
225
455
|
word-break:break-all;
|
|
226
456
|
}
|
|
227
457
|
|
|
228
|
-
|
|
229
|
-
.file-item{
|
|
230
|
-
display:flex;align-items:center;gap:6px;
|
|
231
|
-
font-size:11px;padding:4px 0;
|
|
232
|
-
}
|
|
233
|
-
.file-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
|
|
234
|
-
.file-dot.patched{background:#4ec94e}
|
|
235
|
-
.file-dot.pending{background:#e5c07b}
|
|
236
|
-
|
|
458
|
+
/* ── Buttons ── */
|
|
237
459
|
.btn{
|
|
238
|
-
width:100%;padding:
|
|
239
|
-
font-size:
|
|
460
|
+
width:100%;padding:8px;border:none;border-radius:5px;
|
|
461
|
+
font-size:11px;font-weight:700;letter-spacing:.4px;
|
|
240
462
|
cursor:pointer;transition:background .2s,transform .1s;
|
|
241
|
-
font-family:inherit;margin-bottom:
|
|
463
|
+
font-family:inherit;margin-bottom:5px;
|
|
242
464
|
}
|
|
243
465
|
.btn:active{transform:scale(.98)}
|
|
244
|
-
.btn:disabled{opacity:.
|
|
466
|
+
.btn:disabled{opacity:.4;cursor:not-allowed}
|
|
245
467
|
.btn-apply{background:#0e7a4c;color:#fff}
|
|
246
468
|
.btn-apply:hover:not(:disabled){background:#0f9058}
|
|
247
469
|
.btn-revert{background:#5a1a1a;color:#fff}
|
|
248
470
|
.btn-revert:hover:not(:disabled){background:#7a2020}
|
|
249
471
|
.btn-refresh{background:var(--vscode-button-secondaryBackground);color:var(--vscode-button-secondaryForeground)}
|
|
472
|
+
.btn-settings{
|
|
473
|
+
background:transparent;color:var(--vscode-descriptionForeground);
|
|
474
|
+
border:1px solid var(--vscode-panel-border);font-size:10px;
|
|
475
|
+
margin-top:2px;
|
|
476
|
+
}
|
|
477
|
+
.btn-settings:hover{background:var(--vscode-editor-background)}
|
|
250
478
|
|
|
251
479
|
.note{
|
|
252
|
-
margin-top:
|
|
480
|
+
margin-top:8px;font-size:9px;
|
|
253
481
|
color:var(--vscode-descriptionForeground);
|
|
254
482
|
text-align:center;line-height:1.5;
|
|
255
483
|
}
|
|
256
484
|
</style>
|
|
257
485
|
</head>
|
|
258
486
|
<body>
|
|
487
|
+
|
|
259
488
|
<div class="header">
|
|
260
489
|
<span class="header-icon">⚡</span>
|
|
261
490
|
<div>
|
|
@@ -264,6 +493,19 @@ class AntigravityPanelProvider {
|
|
|
264
493
|
</div>
|
|
265
494
|
</div>
|
|
266
495
|
|
|
496
|
+
<!-- Enabled/Disabled toggle -->
|
|
497
|
+
<div class="toggle-row" id="toggleRow">
|
|
498
|
+
<div>
|
|
499
|
+
<div class="toggle-label">AutoPilot</div>
|
|
500
|
+
<div class="toggle-sub" id="toggleSub">Active — executing all commands</div>
|
|
501
|
+
</div>
|
|
502
|
+
<label class="switch" title="Toggle AutoPilot on/off">
|
|
503
|
+
<input type="checkbox" id="toggleCheck" checked onchange="send('toggleEnabled')">
|
|
504
|
+
<span class="slider"></span>
|
|
505
|
+
</label>
|
|
506
|
+
</div>
|
|
507
|
+
|
|
508
|
+
<!-- Patch Status -->
|
|
267
509
|
<div class="status-card" id="card">
|
|
268
510
|
<div class="status-row">
|
|
269
511
|
<div class="dot" id="dot">⊘</div>
|
|
@@ -276,26 +518,62 @@ class AntigravityPanelProvider {
|
|
|
276
518
|
|
|
277
519
|
<div class="path-box" id="pathBox" style="display:none"></div>
|
|
278
520
|
|
|
279
|
-
|
|
521
|
+
<!-- Dangerous Command Blocking section -->
|
|
522
|
+
<div class="section">
|
|
523
|
+
<div class="section-header">
|
|
524
|
+
🛡️ Command Blocking
|
|
525
|
+
<span class="badge on" id="blockBadge">ON</span>
|
|
526
|
+
</div>
|
|
527
|
+
<div class="blocklist">
|
|
528
|
+
<div class="block-item"><span class="block-dot"></span>rm -rf / and variants (Linux/macOS)</div>
|
|
529
|
+
<div class="block-item"><span class="block-dot"></span>dd / mkfs / wipefs on devices</div>
|
|
530
|
+
<div class="block-item"><span class="block-dot"></span>format C: / Remove-Item -Force (Windows)</div>
|
|
531
|
+
<div class="block-item"><span class="block-dot"></span>curl/wget pipe to shell</div>
|
|
532
|
+
<div class="block-item"><span class="block-dot"></span>Fork bombs, IEX download-exec</div>
|
|
533
|
+
<div class="block-item"><span class="block-dot"></span>diskutil erase, bcdedit delete</div>
|
|
534
|
+
<div class="block-item" style="color:var(--vscode-foreground);font-style:italic">+ 40 more built-in patterns</div>
|
|
535
|
+
</div>
|
|
536
|
+
</div>
|
|
280
537
|
|
|
281
|
-
<button class="btn btn-apply" id="btnApply"
|
|
282
|
-
<button class="btn btn-revert" id="btnRevert"
|
|
283
|
-
<button class="btn btn-refresh"
|
|
538
|
+
<button class="btn btn-apply" id="btnApply" style="display:none">⚡ APPLY PATCH</button>
|
|
539
|
+
<button class="btn btn-revert" id="btnRevert" style="display:none">↩ REVERT PATCH</button>
|
|
540
|
+
<button class="btn btn-refresh">🔄 Refresh Status</button>
|
|
541
|
+
<button class="btn btn-settings" onclick="send('openSettings')">⚙️ Open Settings</button>
|
|
284
542
|
|
|
285
543
|
<div class="note" id="noteBox"></div>
|
|
286
544
|
|
|
287
545
|
<script>
|
|
288
546
|
const vscode = acquireVsCodeApi();
|
|
547
|
+
|
|
289
548
|
function send(cmd) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
549
|
+
if (cmd !== 'openSettings' && cmd !== 'toggleEnabled' && cmd !== 'refresh') {
|
|
550
|
+
document.getElementById('btnApply').disabled = true;
|
|
551
|
+
document.getElementById('btnRevert').disabled = true;
|
|
552
|
+
}
|
|
293
553
|
vscode.postMessage({ command: cmd });
|
|
294
554
|
}
|
|
555
|
+
|
|
556
|
+
// Wire up buttons
|
|
557
|
+
document.getElementById('btnApply').addEventListener('click', () => send('apply'));
|
|
558
|
+
document.getElementById('btnRevert').addEventListener('click', () => send('revert'));
|
|
559
|
+
document.querySelector('.btn-refresh').addEventListener('click', () => {
|
|
560
|
+
send('refresh');
|
|
561
|
+
document.querySelector('.btn-refresh').disabled = true;
|
|
562
|
+
setTimeout(() => { document.querySelector('.btn-refresh').disabled = false; }, 2000);
|
|
563
|
+
});
|
|
564
|
+
|
|
295
565
|
send('refresh');
|
|
296
566
|
|
|
297
567
|
window.addEventListener('message', e => {
|
|
298
|
-
const { command, patched, basePath, files, text } = e.data;
|
|
568
|
+
const { command, patched, basePath, files, text, enabled } = e.data;
|
|
569
|
+
|
|
570
|
+
if (command === 'setEnabled') {
|
|
571
|
+
const chk = document.getElementById('toggleCheck');
|
|
572
|
+
chk.checked = enabled;
|
|
573
|
+
document.getElementById('toggleSub').textContent = enabled
|
|
574
|
+
? 'Active — executing all commands'
|
|
575
|
+
: 'Suspended — commands require confirmation';
|
|
576
|
+
}
|
|
299
577
|
|
|
300
578
|
if (command === 'loading') {
|
|
301
579
|
document.getElementById('lbl').className = 'status-label loading';
|
|
@@ -318,42 +596,24 @@ class AntigravityPanelProvider {
|
|
|
318
596
|
|
|
319
597
|
const lbl = document.getElementById('lbl');
|
|
320
598
|
lbl.className = 'status-label ' + (notFound ? 'not-found' : patched ? 'patched' : 'pending');
|
|
321
|
-
lbl.textContent = notFound ? '
|
|
599
|
+
lbl.textContent = notFound ? 'Not Found' : patched ? 'Patched' : 'Not Patched';
|
|
322
600
|
|
|
323
601
|
document.getElementById('desc').textContent = notFound
|
|
324
|
-
? 'Antigravity not
|
|
325
|
-
: patched
|
|
326
|
-
? 'useEffect added — restart Antigravity!'
|
|
327
|
-
: 'Patch not applied yet';
|
|
602
|
+
? 'Antigravity installation not detected'
|
|
603
|
+
: patched ? 'AutoPilot is active on this machine' : 'Click APPLY PATCH to activate';
|
|
328
604
|
|
|
329
|
-
const pathBox = document.getElementById('pathBox');
|
|
330
605
|
if (basePath) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
pathBox.style.display = 'none';
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
const filesList = document.getElementById('filesList');
|
|
338
|
-
filesList.innerHTML = '';
|
|
339
|
-
if (files && files.length) {
|
|
340
|
-
for (const f of files) {
|
|
341
|
-
const d = document.createElement('div');
|
|
342
|
-
d.className = 'file-item';
|
|
343
|
-
d.innerHTML = '<div class="file-dot ' + (f.patched ? 'patched' : 'pending') + '"></div>'
|
|
344
|
-
+ '<span>' + f.label + ': ' + (f.patched ? '✅ patched' : '⬜ not patched') + '</span>';
|
|
345
|
-
filesList.appendChild(d);
|
|
346
|
-
}
|
|
606
|
+
const pb = document.getElementById('pathBox');
|
|
607
|
+
pb.textContent = basePath;
|
|
608
|
+
pb.style.display = 'block';
|
|
347
609
|
}
|
|
348
610
|
|
|
349
|
-
document.getElementById('btnApply').style.display =
|
|
350
|
-
document.getElementById('btnRevert').style.display = patched ? '' : 'none';
|
|
611
|
+
document.getElementById('btnApply').style.display = notFound || patched ? 'none' : 'block';
|
|
612
|
+
document.getElementById('btnRevert').style.display = patched ? 'block' : 'none';
|
|
351
613
|
|
|
352
614
|
document.getElementById('noteBox').textContent = notFound
|
|
353
|
-
? '
|
|
354
|
-
: patched
|
|
355
|
-
? '💡 Re-run after Antigravity updates'
|
|
356
|
-
: '💡 Apply patch once, then restart Antigravity';
|
|
615
|
+
? 'Install Antigravity first, then click Refresh.'
|
|
616
|
+
: patched ? 'Restart Antigravity to apply changes.' : '';
|
|
357
617
|
});
|
|
358
618
|
</script>
|
|
359
619
|
</body>
|
|
@@ -361,38 +621,30 @@ class AntigravityPanelProvider {
|
|
|
361
621
|
}
|
|
362
622
|
}
|
|
363
623
|
|
|
364
|
-
// ─── Status Bar
|
|
365
|
-
|
|
366
|
-
function updateStatusBarFromCache() {
|
|
367
|
-
const status = _cachedStatus;
|
|
368
|
-
if (!status || !status.basePath) {
|
|
369
|
-
statusBarItem.text = `$(warning) AG Patch: Not Found`;
|
|
370
|
-
statusBarItem.tooltip = 'Antigravity not detected';
|
|
371
|
-
statusBarItem.backgroundColor = undefined;
|
|
372
|
-
} else if (status.patched) {
|
|
373
|
-
statusBarItem.text = `$(check) AG Patch: Active`;
|
|
374
|
-
statusBarItem.tooltip = 'Auto-Accept patch is applied — click to manage';
|
|
375
|
-
statusBarItem.backgroundColor = new vscode.ThemeColor('statusBarItem.warningBackground');
|
|
376
|
-
} else {
|
|
377
|
-
statusBarItem.text = `$(zap) AG Patch: OFF`;
|
|
378
|
-
statusBarItem.tooltip = 'Auto-Accept patch not applied — click to open panel';
|
|
379
|
-
statusBarItem.backgroundColor = undefined;
|
|
380
|
-
}
|
|
381
|
-
}
|
|
624
|
+
// ─── Status Bar (legacy helpers) ──────────────────────────────────────────────
|
|
382
625
|
|
|
383
626
|
/** @deprecated kept for backward compat */
|
|
384
627
|
function updateStatusBar() { updateStatusBarFromCache(); }
|
|
385
628
|
|
|
386
|
-
// ─── Activate / Deactivate
|
|
629
|
+
// ─── Activate / Deactivate ────────────────────────────────────────────────────
|
|
387
630
|
|
|
388
631
|
/** @param {vscode.ExtensionContext} context */
|
|
389
632
|
function activate(context) {
|
|
390
|
-
//
|
|
633
|
+
// Shared output channel
|
|
634
|
+
outputChannel = vscode.window.createOutputChannel('AutoPilot');
|
|
635
|
+
context.subscriptions.push(outputChannel);
|
|
636
|
+
|
|
637
|
+
// Read enabledOnStartup setting
|
|
638
|
+
const cfg = vscode.workspace.getConfiguration('antigravityAutoAccept');
|
|
639
|
+
autoPilotEnabled = cfg.get('enabledOnStartup', true);
|
|
640
|
+
|
|
641
|
+
// Status bar
|
|
391
642
|
statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
|
|
392
643
|
statusBarItem.command = 'antigravityAutoAccept.openPanel';
|
|
393
644
|
statusBarItem.text = `$(sync~spin) AG Patch`;
|
|
394
645
|
statusBarItem.tooltip = 'Checking patch status...';
|
|
395
646
|
statusBarItem.show();
|
|
647
|
+
context.subscriptions.push(statusBarItem);
|
|
396
648
|
|
|
397
649
|
// Sidebar
|
|
398
650
|
panelProvider = new AntigravityPanelProvider(context);
|
|
@@ -404,6 +656,36 @@ function activate(context) {
|
|
|
404
656
|
),
|
|
405
657
|
);
|
|
406
658
|
|
|
659
|
+
// ── Terminal command watcher (Dangerous Command Blocking) ──────────────────
|
|
660
|
+
// VS Code API: onDidWriteTerminalData captures output; we intercept typed
|
|
661
|
+
// commands via onDidStartTerminalShellExecution (VS Code 1.87+).
|
|
662
|
+
// Fallback: detect via terminal write events.
|
|
663
|
+
if (typeof vscode.window.onDidStartTerminalShellExecution === 'function') {
|
|
664
|
+
context.subscriptions.push(
|
|
665
|
+
vscode.window.onDidStartTerminalShellExecution((event) => {
|
|
666
|
+
const cmd = event.execution.commandLine?.value || '';
|
|
667
|
+
if (!cmd) return;
|
|
668
|
+
const check = checkDangerousCommand(cmd);
|
|
669
|
+
if (check.matched) {
|
|
670
|
+
handleDangerousCommand(cmd, check.label);
|
|
671
|
+
// Note: VS Code does not expose a cancellation API for shell exec;
|
|
672
|
+
// we log/warn/notify. For full blocking, pair with shell hook.
|
|
673
|
+
}
|
|
674
|
+
}),
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// Config change listener — react to user toggling blocking or action
|
|
679
|
+
context.subscriptions.push(
|
|
680
|
+
vscode.workspace.onDidChangeConfiguration((e) => {
|
|
681
|
+
if (e.affectsConfiguration('antigravityAutoAccept.enabledOnStartup')) {
|
|
682
|
+
autoPilotEnabled = vscode.workspace.getConfiguration('antigravityAutoAccept').get('enabledOnStartup', true);
|
|
683
|
+
updateStatusBarFromCache();
|
|
684
|
+
if (panelProvider) panelProvider.sendEnabled(autoPilotEnabled);
|
|
685
|
+
}
|
|
686
|
+
}),
|
|
687
|
+
);
|
|
688
|
+
|
|
407
689
|
// Commands
|
|
408
690
|
context.subscriptions.push(
|
|
409
691
|
vscode.commands.registerCommand('antigravityAutoAccept.applyPatch', async () => {
|
|
@@ -429,20 +711,21 @@ function activate(context) {
|
|
|
429
711
|
}),
|
|
430
712
|
);
|
|
431
713
|
|
|
432
|
-
context.subscriptions.push(statusBarItem);
|
|
433
|
-
|
|
434
714
|
// Async startup — never blocks extension host!
|
|
435
715
|
(async () => {
|
|
436
716
|
const status = await getPatchStatus();
|
|
437
717
|
isPatchApplied = status.patched;
|
|
438
718
|
updateStatusBarFromCache();
|
|
439
|
-
if (panelProvider)
|
|
719
|
+
if (panelProvider) {
|
|
720
|
+
panelProvider.sendStatus(status);
|
|
721
|
+
panelProvider.sendEnabled(autoPilotEnabled);
|
|
722
|
+
}
|
|
440
723
|
|
|
441
|
-
const
|
|
442
|
-
if (
|
|
724
|
+
const startCfg = vscode.workspace.getConfiguration('antigravityAutoAccept');
|
|
725
|
+
if (startCfg.get('applyOnStartup') && !status.patched && status.basePath) {
|
|
443
726
|
const result = await applyPatch();
|
|
444
727
|
if (result.success) {
|
|
445
|
-
|
|
728
|
+
outputChannel.appendLine('[AutoPilot] Auto-patch applied on startup');
|
|
446
729
|
}
|
|
447
730
|
}
|
|
448
731
|
})();
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "antigravity-autopilot",
|
|
3
3
|
"displayName": "Antigravity AutoPilot",
|
|
4
4
|
"description": "Enables autopilot mode for Antigravity: automatically executes all tool calls and terminal commands without manual confirmation. Patches the runtime JS bundle to inject auto-accept logic whenever the 'Always Proceed' policy is active — regex-based and version-agnostic.",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.2.0",
|
|
6
6
|
"publisher": "nguyen-hoang",
|
|
7
7
|
"bin": {
|
|
8
8
|
"antigravity-autopilot": "./cli.js"
|
|
@@ -33,19 +33,19 @@
|
|
|
33
33
|
{
|
|
34
34
|
"type": "webview",
|
|
35
35
|
"id": "antigravityAutoAccept.panel",
|
|
36
|
-
"name": "
|
|
36
|
+
"name": "AutoPilot"
|
|
37
37
|
}
|
|
38
38
|
]
|
|
39
39
|
},
|
|
40
40
|
"commands": [
|
|
41
41
|
{
|
|
42
42
|
"command": "antigravityAutoAccept.applyPatch",
|
|
43
|
-
"title": "Antigravity: Apply
|
|
43
|
+
"title": "Antigravity: Apply AutoPilot Patch",
|
|
44
44
|
"icon": "$(zap)"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"command": "antigravityAutoAccept.revertPatch",
|
|
48
|
-
"title": "Antigravity: Revert
|
|
48
|
+
"title": "Antigravity: Revert AutoPilot Patch",
|
|
49
49
|
"icon": "$(discard)"
|
|
50
50
|
},
|
|
51
51
|
{
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
"command": "antigravityAutoAccept.openPanel",
|
|
58
|
-
"title": "Antigravity: Open
|
|
58
|
+
"title": "Antigravity: Open AutoPilot Panel"
|
|
59
59
|
}
|
|
60
60
|
],
|
|
61
61
|
"keybindings": [
|
|
@@ -65,12 +65,39 @@
|
|
|
65
65
|
}
|
|
66
66
|
],
|
|
67
67
|
"configuration": {
|
|
68
|
-
"title": "Antigravity
|
|
68
|
+
"title": "Antigravity AutoPilot",
|
|
69
69
|
"properties": {
|
|
70
70
|
"antigravityAutoAccept.applyOnStartup": {
|
|
71
71
|
"type": "boolean",
|
|
72
72
|
"default": false,
|
|
73
|
-
"description": "Automatically apply the patch when
|
|
73
|
+
"description": "Automatically apply the AutoPilot patch when VS Code starts. Safe to enable — patch is idempotent."
|
|
74
|
+
},
|
|
75
|
+
"antigravityAutoAccept.enabledOnStartup": {
|
|
76
|
+
"type": "boolean",
|
|
77
|
+
"default": true,
|
|
78
|
+
"description": "Keep AutoPilot enabled (active) when VS Code starts. When disabled, AutoPilot will be suspended until manually turned on from the sidebar."
|
|
79
|
+
},
|
|
80
|
+
"antigravityAutoAccept.dangerousCommandBlocking.enabled": {
|
|
81
|
+
"type": "boolean",
|
|
82
|
+
"default": true,
|
|
83
|
+
"description": "Block dangerous terminal commands (e.g. rm -rf /, format C:) before they execute. Fully customizable via the blocklist setting."
|
|
84
|
+
},
|
|
85
|
+
"antigravityAutoAccept.dangerousCommandBlocking.action": {
|
|
86
|
+
"type": "string",
|
|
87
|
+
"enum": ["block", "warn", "log"],
|
|
88
|
+
"enumDescriptions": [
|
|
89
|
+
"Block the command entirely and show an error notification.",
|
|
90
|
+
"Show a warning notification but still allow the command to proceed.",
|
|
91
|
+
"Silently log the command to the output channel and allow it to proceed."
|
|
92
|
+
],
|
|
93
|
+
"default": "block",
|
|
94
|
+
"description": "Action to take when a dangerous command is detected."
|
|
95
|
+
},
|
|
96
|
+
"antigravityAutoAccept.dangerousCommandBlocking.customPatterns": {
|
|
97
|
+
"type": "array",
|
|
98
|
+
"items": { "type": "string" },
|
|
99
|
+
"default": [],
|
|
100
|
+
"description": "Additional regex patterns (JavaScript syntax) to treat as dangerous commands. Example: [\"^dd if=.*of=/dev/sd\", \"^shred\"]"
|
|
74
101
|
}
|
|
75
102
|
}
|
|
76
103
|
}
|