@solongate/proxy 0.82.11 → 0.82.12
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/dist/audit/index.js +74 -61
- package/dist/audit/types.d.ts +3 -3
- package/dist/create.js +1 -1
- package/dist/global-install.d.ts +3 -3
- package/dist/global-install.js +30 -38
- package/dist/index.js +30 -38
- package/dist/lib.js +1 -1
- package/dist/login.js +21 -22
- package/dist/tui/index.js +27 -35
- package/hooks/guard.bundled.mjs +30 -8
- package/hooks/guard.mjs +37 -10
- package/package.json +1 -1
package/dist/audit/index.js
CHANGED
|
@@ -84,7 +84,7 @@ function listDirs() {
|
|
|
84
84
|
const home = homedir();
|
|
85
85
|
console.log("\n Default log directories:");
|
|
86
86
|
console.log(` Claude Code \u2192 ${resolve(home, ".claude", "projects")}`);
|
|
87
|
-
console.log(`
|
|
87
|
+
console.log(` Antigravity \u2192 ${resolve(home, ".gemini", "antigravity", "brain")}`);
|
|
88
88
|
console.log(` OpenClaw \u2192 ${resolve(home, ".openclaw", "agents", "main", "sessions")}`);
|
|
89
89
|
if (config.customDirs.length === 0) {
|
|
90
90
|
console.log("\n Custom directories: (none)");
|
|
@@ -106,7 +106,7 @@ function searchLogs() {
|
|
|
106
106
|
console.log("\n Searching for AI tool logs...\n");
|
|
107
107
|
const defaults = [
|
|
108
108
|
{ name: "Claude Code", path: resolve(home, ".claude", "projects") },
|
|
109
|
-
{ name: "
|
|
109
|
+
{ name: "Antigravity", path: resolve(home, ".gemini", "antigravity", "brain") },
|
|
110
110
|
{ name: "OpenClaw", path: resolve(home, ".openclaw", "agents", "main", "sessions") }
|
|
111
111
|
];
|
|
112
112
|
for (const d of defaults) {
|
|
@@ -129,7 +129,7 @@ function searchLogs() {
|
|
|
129
129
|
}
|
|
130
130
|
const otherPaths = [
|
|
131
131
|
{ name: `Claude Code (${user})`, path: resolve(userHome, ".claude", "projects") },
|
|
132
|
-
{ name: `
|
|
132
|
+
{ name: `Antigravity (${user})`, path: resolve(userHome, ".gemini", "antigravity", "brain") },
|
|
133
133
|
{ name: `OpenClaw (${user})`, path: resolve(userHome, ".openclaw", "agents", "main", "sessions") }
|
|
134
134
|
];
|
|
135
135
|
for (const d of otherPaths) {
|
|
@@ -152,7 +152,7 @@ function searchLogs() {
|
|
|
152
152
|
if (userHome === home) continue;
|
|
153
153
|
const otherPaths = [
|
|
154
154
|
{ name: `Claude Code (${user})`, path: resolve(userHome, ".claude", "projects") },
|
|
155
|
-
{ name: `
|
|
155
|
+
{ name: `Antigravity (${user})`, path: resolve(userHome, ".gemini", "antigravity", "brain") },
|
|
156
156
|
{ name: `OpenClaw (${user})`, path: resolve(userHome, ".openclaw", "agents", "main", "sessions") }
|
|
157
157
|
];
|
|
158
158
|
for (const d of otherPaths) {
|
|
@@ -261,61 +261,74 @@ function collectClaude() {
|
|
|
261
261
|
}
|
|
262
262
|
return sessions;
|
|
263
263
|
}
|
|
264
|
-
function
|
|
264
|
+
function collectAntigravity() {
|
|
265
265
|
const sessions = [];
|
|
266
|
-
const
|
|
267
|
-
if (!existsSync2(
|
|
268
|
-
for (const
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
266
|
+
const brainDir = resolve2(homedir2(), ".gemini", "antigravity", "brain");
|
|
267
|
+
if (!existsSync2(brainDir)) return sessions;
|
|
268
|
+
for (const convId of readdirSync(brainDir)) {
|
|
269
|
+
const convPath = join2(brainDir, convId);
|
|
270
|
+
try {
|
|
271
|
+
if (!statSync(convPath).isDirectory()) continue;
|
|
272
|
+
} catch {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
const transcript = join2(convPath, ".system_generated", "logs", "transcript.jsonl");
|
|
276
|
+
if (!existsSync2(transcript)) continue;
|
|
277
|
+
try {
|
|
278
|
+
const lines = readFileSync2(transcript, "utf-8").split("\n").filter(Boolean);
|
|
279
|
+
const toolCalls = [];
|
|
280
|
+
const userMessages = [];
|
|
281
|
+
let startTime = "";
|
|
282
|
+
let endTime = "";
|
|
283
|
+
let model = "";
|
|
284
|
+
for (const line of lines) {
|
|
285
|
+
try {
|
|
286
|
+
const entry = JSON.parse(line);
|
|
287
|
+
const ts = entry.timestamp || entry.time || entry.ts || "";
|
|
288
|
+
if (ts) {
|
|
289
|
+
if (!startTime) startTime = ts;
|
|
290
|
+
endTime = ts;
|
|
285
291
|
}
|
|
286
|
-
if (!
|
|
287
|
-
|
|
292
|
+
if (!model && typeof entry.model === "string") model = entry.model;
|
|
293
|
+
const tc = entry.toolCall || (entry.type === "tool_call" ? entry : null);
|
|
294
|
+
if (tc && typeof tc === "object" && (tc.name || tc.toolName)) {
|
|
288
295
|
toolCalls.push({
|
|
289
|
-
id: tc.id || "",
|
|
290
|
-
toolName: tc.name || "",
|
|
296
|
+
id: tc.id || (entry.stepIdx != null ? String(entry.stepIdx) : ""),
|
|
297
|
+
toolName: tc.name || tc.toolName || "",
|
|
291
298
|
arguments: tc.args || tc.arguments || {},
|
|
292
|
-
result:
|
|
293
|
-
isError:
|
|
294
|
-
timestamp:
|
|
295
|
-
source: "
|
|
296
|
-
sessionId
|
|
299
|
+
result: entry.result ? JSON.stringify(entry.result).slice(0, 2e3) : void 0,
|
|
300
|
+
isError: entry.status === "error" || entry.isError === true,
|
|
301
|
+
timestamp: ts,
|
|
302
|
+
source: "antigravity",
|
|
303
|
+
sessionId: convId
|
|
297
304
|
});
|
|
298
305
|
}
|
|
306
|
+
const role = entry.role || entry.type;
|
|
307
|
+
if ((role === "user" || role === "user_message") && (entry.text || entry.content)) {
|
|
308
|
+
const text = String(entry.text || entry.content).slice(0, 500);
|
|
309
|
+
if (text.length > 0) userMessages.push({ timestamp: ts, text });
|
|
310
|
+
}
|
|
311
|
+
} catch {
|
|
299
312
|
}
|
|
300
|
-
for (const um of userMessages) {
|
|
301
|
-
const umTime = new Date(um.timestamp).getTime();
|
|
302
|
-
const nextIdx = toolCalls.findIndex((tc) => new Date(tc.timestamp).getTime() > umTime);
|
|
303
|
-
if (nextIdx >= 0) um.nextToolCallIndex = nextIdx;
|
|
304
|
-
}
|
|
305
|
-
if (toolCalls.length > 0) {
|
|
306
|
-
sessions.push({
|
|
307
|
-
id: sessionId,
|
|
308
|
-
source: "gemini",
|
|
309
|
-
startTime: data.startTime || "",
|
|
310
|
-
endTime: data.lastUpdated || "",
|
|
311
|
-
model: data.messages?.[0]?.model || "",
|
|
312
|
-
toolCalls,
|
|
313
|
-
userMessages,
|
|
314
|
-
filePath
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
} catch {
|
|
318
313
|
}
|
|
314
|
+
for (const um of userMessages) {
|
|
315
|
+
const umTime = new Date(um.timestamp).getTime();
|
|
316
|
+
const nextIdx = toolCalls.findIndex((tc) => new Date(tc.timestamp).getTime() > umTime);
|
|
317
|
+
if (nextIdx >= 0) um.nextToolCallIndex = nextIdx;
|
|
318
|
+
}
|
|
319
|
+
if (toolCalls.length > 0) {
|
|
320
|
+
sessions.push({
|
|
321
|
+
id: convId,
|
|
322
|
+
source: "antigravity",
|
|
323
|
+
startTime,
|
|
324
|
+
endTime,
|
|
325
|
+
model,
|
|
326
|
+
toolCalls,
|
|
327
|
+
userMessages,
|
|
328
|
+
filePath: transcript
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
} catch {
|
|
319
332
|
}
|
|
320
333
|
}
|
|
321
334
|
return sessions;
|
|
@@ -485,11 +498,11 @@ function collectCustomDirs() {
|
|
|
485
498
|
for (const msg of data.messages) {
|
|
486
499
|
if (!msg.toolCalls || !Array.isArray(msg.toolCalls)) continue;
|
|
487
500
|
for (const tc of msg.toolCalls) {
|
|
488
|
-
toolCalls.push({ id: tc.id || "", toolName: tc.name || "", arguments: tc.args || tc.arguments || {}, result: tc.result ? JSON.stringify(tc.result).slice(0, 2e3) : void 0, isError: tc.status === "error", timestamp: tc.timestamp || msg.timestamp || data.startTime || "", source: "
|
|
501
|
+
toolCalls.push({ id: tc.id || "", toolName: tc.name || "", arguments: tc.args || tc.arguments || {}, result: tc.result ? JSON.stringify(tc.result).slice(0, 2e3) : void 0, isError: tc.status === "error", timestamp: tc.timestamp || msg.timestamp || data.startTime || "", source: "antigravity", sessionId });
|
|
489
502
|
}
|
|
490
503
|
}
|
|
491
504
|
if (toolCalls.length > 0) {
|
|
492
|
-
sessions.push({ id: sessionId, source: "
|
|
505
|
+
sessions.push({ id: sessionId, source: "antigravity", startTime: data.startTime || "", endTime: data.lastUpdated || "", model: data.messages?.[0]?.model || "", toolCalls, filePath });
|
|
493
506
|
}
|
|
494
507
|
} catch {
|
|
495
508
|
}
|
|
@@ -502,13 +515,13 @@ function collectCustomDirs() {
|
|
|
502
515
|
}
|
|
503
516
|
function collectLogs() {
|
|
504
517
|
const claudeSessions = collectClaude();
|
|
505
|
-
const
|
|
518
|
+
const antigravitySessions = collectAntigravity();
|
|
506
519
|
const openclawSessions = collectOpenClaw();
|
|
507
520
|
const customSessions = collectCustomDirs();
|
|
508
|
-
const sessions = [...claudeSessions, ...
|
|
521
|
+
const sessions = [...claudeSessions, ...antigravitySessions, ...openclawSessions, ...customSessions].sort((a, b) => (a.startTime || "").localeCompare(b.startTime || ""));
|
|
509
522
|
const sources = [];
|
|
510
523
|
if (claudeSessions.length > 0) sources.push("Claude Code");
|
|
511
|
-
if (
|
|
524
|
+
if (antigravitySessions.length > 0) sources.push("Antigravity");
|
|
512
525
|
if (openclawSessions.length > 0) sources.push("OpenClaw");
|
|
513
526
|
const allCalls = sessions.flatMap((s) => s.toolCalls);
|
|
514
527
|
const timestamps = allCalls.map((t) => t.timestamp).filter(Boolean).sort();
|
|
@@ -2599,12 +2612,12 @@ function printFooter(results) {
|
|
|
2599
2612
|
}
|
|
2600
2613
|
var SOURCE_COLOR = {
|
|
2601
2614
|
claude: source_default.magenta,
|
|
2602
|
-
|
|
2615
|
+
antigravity: source_default.blue,
|
|
2603
2616
|
openclaw: source_default.green
|
|
2604
2617
|
};
|
|
2605
2618
|
var SOURCE_LABEL = {
|
|
2606
2619
|
claude: "Claude",
|
|
2607
|
-
|
|
2620
|
+
antigravity: "Antigravity",
|
|
2608
2621
|
openclaw: "OClaw"
|
|
2609
2622
|
};
|
|
2610
2623
|
function truncate(s, max) {
|
|
@@ -2807,7 +2820,7 @@ function exportHTML({ data, results }) {
|
|
|
2807
2820
|
};
|
|
2808
2821
|
const sourceLabel = {
|
|
2809
2822
|
claude: "Claude",
|
|
2810
|
-
|
|
2823
|
+
antigravity: "Antigravity",
|
|
2811
2824
|
openclaw: "OpenClaw"
|
|
2812
2825
|
};
|
|
2813
2826
|
const pillClass = {
|
|
@@ -2922,7 +2935,7 @@ function exportHTML({ data, results }) {
|
|
|
2922
2935
|
.code-tag { color: var(--accent); font-weight: 600; font-size: 11px; }
|
|
2923
2936
|
.src-tag { display: inline-block; padding: 1px 7px; border-radius: 3px; font-size: 10px; font-weight: 600; }
|
|
2924
2937
|
.src-claude { background: rgba(192,132,252,0.12); color: #c084fc; }
|
|
2925
|
-
.src-
|
|
2938
|
+
.src-antigravity { background: rgba(96,165,250,0.12); color: #60a5fa; }
|
|
2926
2939
|
.src-openclaw { background: rgba(74,222,128,0.12); color: #4ade80; }
|
|
2927
2940
|
.err-tag { background: rgba(239,68,68,0.15); color: #f87171; padding: 0 5px; border-radius: 3px; font-size: 9px; font-weight: 700; margin-left: 4px; }
|
|
2928
2941
|
.cat { font-weight: 500; }
|
|
@@ -3038,7 +3051,7 @@ function exportHTML({ data, results }) {
|
|
|
3038
3051
|
<div class="sec-hdr">Tool Calls <span class="sec-count">${allCalls.length.toLocaleString()}</span></div>
|
|
3039
3052
|
<div class="filters">
|
|
3040
3053
|
<input type="text" id="q" placeholder="Search..." oninput="applyFilters()">
|
|
3041
|
-
<select id="sf" onchange="applyFilters()"><option value="">All sources</option><option value="claude">Claude</option><option value="
|
|
3054
|
+
<select id="sf" onchange="applyFilters()"><option value="">All sources</option><option value="claude">Claude</option><option value="antigravity">Antigravity</option><option value="openclaw">OpenClaw</option></select>
|
|
3042
3055
|
<select id="ef" onchange="applyFilters()"><option value="">All</option><option value="e">Errors</option><option value="s">Success</option></select>
|
|
3043
3056
|
<select id="df" onchange="applyFilters()"><option value="">All dates</option></select>
|
|
3044
3057
|
</div>
|
package/dist/audit/types.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export interface ToolCall {
|
|
|
19
19
|
result?: string;
|
|
20
20
|
isError?: boolean;
|
|
21
21
|
timestamp: string;
|
|
22
|
-
source: 'claude' | '
|
|
22
|
+
source: 'claude' | 'antigravity' | 'openclaw';
|
|
23
23
|
sessionId: string;
|
|
24
24
|
}
|
|
25
25
|
export interface UserMessage {
|
|
@@ -29,7 +29,7 @@ export interface UserMessage {
|
|
|
29
29
|
}
|
|
30
30
|
export interface SessionInfo {
|
|
31
31
|
id: string;
|
|
32
|
-
source: 'claude' | '
|
|
32
|
+
source: 'claude' | 'antigravity' | 'openclaw';
|
|
33
33
|
startTime: string;
|
|
34
34
|
endTime?: string;
|
|
35
35
|
model?: string;
|
|
@@ -74,7 +74,7 @@ export interface PermissionDrift {
|
|
|
74
74
|
newToolTypes: string[];
|
|
75
75
|
}
|
|
76
76
|
export interface SessionBaseline {
|
|
77
|
-
source: 'claude' | '
|
|
77
|
+
source: 'claude' | 'antigravity' | 'openclaw' | 'all';
|
|
78
78
|
avgToolCalls: number;
|
|
79
79
|
stddevToolCalls: number;
|
|
80
80
|
toolTypeDistribution: Record<string, number>;
|
package/dist/create.js
CHANGED
|
@@ -213,7 +213,7 @@ console.log('MCP servers communicate over stdin/stdout \u2014 not HTTP.');
|
|
|
213
213
|
console.log('You need an MCP client to connect:');
|
|
214
214
|
console.log('');
|
|
215
215
|
console.log(' Claude Code Open this folder, .mcp.json is auto-detected');
|
|
216
|
-
console.log('
|
|
216
|
+
console.log(' Antigravity .agents/mcp_config.json (or ~/.gemini/config/mcp_config.json)');
|
|
217
217
|
console.log(' OpenClaw Uses openclaw.plugin.json config');
|
|
218
218
|
console.log('');
|
|
219
219
|
console.log('Press Ctrl+C to stop.');
|
package/dist/global-install.d.ts
CHANGED
|
@@ -5,12 +5,12 @@ export declare function globalPaths(): {
|
|
|
5
5
|
sgDir: string;
|
|
6
6
|
hooksDir: string;
|
|
7
7
|
claudeDir: string;
|
|
8
|
-
|
|
8
|
+
antigravityDir: string;
|
|
9
9
|
settingsPath: string;
|
|
10
10
|
backupPath: string;
|
|
11
11
|
configPath: string;
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
antigravityHooksPath: string;
|
|
13
|
+
antigravityBackupPath: string;
|
|
14
14
|
};
|
|
15
15
|
export declare function clearGuardUpdateCheck(): boolean;
|
|
16
16
|
export declare function runGlobalRestore(): void;
|
package/dist/global-install.js
CHANGED
|
@@ -72,7 +72,7 @@ function protectedTargets() {
|
|
|
72
72
|
join(p.hooksDir, "shield.mjs"),
|
|
73
73
|
p.configPath,
|
|
74
74
|
p.settingsPath,
|
|
75
|
-
p.
|
|
75
|
+
p.antigravityHooksPath
|
|
76
76
|
];
|
|
77
77
|
}
|
|
78
78
|
function lockProtected() {
|
|
@@ -86,21 +86,21 @@ function globalPaths() {
|
|
|
86
86
|
const sgDir = join(home, ".solongate");
|
|
87
87
|
const hooksDir = join(sgDir, "hooks");
|
|
88
88
|
const claudeDir = join(home, ".claude");
|
|
89
|
-
const
|
|
89
|
+
const antigravityDir = join(home, ".gemini", "config");
|
|
90
90
|
return {
|
|
91
91
|
home,
|
|
92
92
|
sgDir,
|
|
93
93
|
hooksDir,
|
|
94
94
|
claudeDir,
|
|
95
|
-
|
|
95
|
+
antigravityDir,
|
|
96
96
|
settingsPath: join(claudeDir, "settings.json"),
|
|
97
97
|
backupPath: join(claudeDir, "settings.solongate.bak"),
|
|
98
98
|
configPath: join(sgDir, "cloud-guard.json"),
|
|
99
|
-
//
|
|
100
|
-
// guard is registered there (
|
|
101
|
-
// covered by the passive session-log collector
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
// Antigravity reads global hooks from ~/.gemini/config/hooks.json. Only the
|
|
100
|
+
// guard is registered there (PreToolUse); Antigravity's ALLOW-path audit is
|
|
101
|
+
// covered by the passive session-log collector, not a hook.
|
|
102
|
+
antigravityHooksPath: join(antigravityDir, "hooks.json"),
|
|
103
|
+
antigravityBackupPath: join(antigravityDir, "hooks.solongate.bak")
|
|
104
104
|
};
|
|
105
105
|
}
|
|
106
106
|
function clearGuardUpdateCheck() {
|
|
@@ -118,47 +118,39 @@ function readGuard() {
|
|
|
118
118
|
const bundled = join(HOOKS_DIR, "guard.bundled.mjs");
|
|
119
119
|
return existsSync(bundled) ? readFileSync(bundled, "utf-8") : readHook("guard.mjs");
|
|
120
120
|
}
|
|
121
|
-
|
|
121
|
+
var ANTIGRAVITY_GROUP = "solongate-guard";
|
|
122
|
+
function antigravityHookCommand(guardAbs) {
|
|
122
123
|
const nodeBin = process.execPath.replace(/\\/g, "/");
|
|
123
124
|
const call = process.platform === "win32" ? "& " : "";
|
|
124
|
-
return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}"
|
|
125
|
+
return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}" antigravity "Antigravity"`;
|
|
125
126
|
}
|
|
126
|
-
function
|
|
127
|
-
mkdirSync(p.
|
|
127
|
+
function installAntigravityGuard(p, guardAbs) {
|
|
128
|
+
mkdirSync(p.antigravityDir, { recursive: true });
|
|
128
129
|
let existing = {};
|
|
129
|
-
if (existsSync(p.
|
|
130
|
-
const raw = readFileSync(p.
|
|
131
|
-
if (!existsSync(p.
|
|
130
|
+
if (existsSync(p.antigravityHooksPath)) {
|
|
131
|
+
const raw = readFileSync(p.antigravityHooksPath, "utf-8");
|
|
132
|
+
if (!existsSync(p.antigravityBackupPath)) writeFileSync(p.antigravityBackupPath, raw);
|
|
132
133
|
try {
|
|
133
134
|
existing = JSON.parse(raw);
|
|
134
135
|
} catch {
|
|
135
136
|
existing = {};
|
|
136
137
|
}
|
|
137
138
|
}
|
|
138
|
-
const existingHooks = existing.hooks && typeof existing.hooks === "object" ? existing.hooks : {};
|
|
139
139
|
const merged = {
|
|
140
140
|
...existing,
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
BeforeTool: [{ matcher: "", hooks: [{ type: "command", command: geminiHookCommand(guardAbs) }] }]
|
|
141
|
+
[ANTIGRAVITY_GROUP]: {
|
|
142
|
+
PreToolUse: [{ matcher: "", hooks: [{ type: "command", command: antigravityHookCommand(guardAbs) }] }]
|
|
144
143
|
}
|
|
145
144
|
};
|
|
146
|
-
writeFileSync(p.
|
|
145
|
+
writeFileSync(p.antigravityHooksPath, JSON.stringify(merged, null, 2) + "\n");
|
|
147
146
|
}
|
|
148
|
-
function
|
|
149
|
-
if (!existsSync(p.
|
|
147
|
+
function removeAntigravityGuard(p) {
|
|
148
|
+
if (!existsSync(p.antigravityHooksPath)) return;
|
|
150
149
|
try {
|
|
151
|
-
const s = JSON.parse(readFileSync(p.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const inner = Array.isArray(entry?.hooks) ? entry.hooks : [];
|
|
156
|
-
return !inner.some((h) => typeof h?.command === "string" && h.command.includes(".solongate"));
|
|
157
|
-
});
|
|
158
|
-
if (kept.length) hooks.BeforeTool = kept;
|
|
159
|
-
else delete hooks.BeforeTool;
|
|
160
|
-
if (Object.keys(hooks).length === 0) delete s.hooks;
|
|
161
|
-
writeFileSync(p.geminiSettingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
150
|
+
const s = JSON.parse(readFileSync(p.antigravityHooksPath, "utf-8"));
|
|
151
|
+
if (!(ANTIGRAVITY_GROUP in s)) return;
|
|
152
|
+
delete s[ANTIGRAVITY_GROUP];
|
|
153
|
+
writeFileSync(p.antigravityHooksPath, JSON.stringify(s, null, 2) + "\n");
|
|
162
154
|
} catch {
|
|
163
155
|
}
|
|
164
156
|
}
|
|
@@ -173,7 +165,7 @@ function runGlobalRestore() {
|
|
|
173
165
|
const p = globalPaths();
|
|
174
166
|
unlockProtected();
|
|
175
167
|
removeClaudeShim();
|
|
176
|
-
|
|
168
|
+
removeAntigravityGuard(p);
|
|
177
169
|
if (existsSync(p.backupPath)) {
|
|
178
170
|
writeFileSync(p.settingsPath, readFileSync(p.backupPath, "utf-8"));
|
|
179
171
|
console.log(` Restored ${p.settingsPath} from backup.`);
|
|
@@ -233,7 +225,7 @@ function installGlobalQuiet() {
|
|
|
233
225
|
};
|
|
234
226
|
writeFileSync(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
235
227
|
try {
|
|
236
|
-
|
|
228
|
+
installAntigravityGuard(p, join(p.hooksDir, "guard.mjs").replace(/\\/g, "/"));
|
|
237
229
|
} catch {
|
|
238
230
|
}
|
|
239
231
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") lockProtected();
|
|
@@ -276,7 +268,7 @@ function uninstallGlobalQuiet() {
|
|
|
276
268
|
unlockProtected();
|
|
277
269
|
removeClaudeShim();
|
|
278
270
|
try {
|
|
279
|
-
|
|
271
|
+
removeAntigravityGuard(p);
|
|
280
272
|
} catch {
|
|
281
273
|
}
|
|
282
274
|
if (!existsSync(p.settingsPath)) return { ok: true, message: "guard removed (open a new session)" };
|
|
@@ -418,8 +410,8 @@ async function runGlobalInstall(opts = {}) {
|
|
|
418
410
|
writeFileSync(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
419
411
|
console.log(` Registered global hooks \u2192 ${p.settingsPath}`);
|
|
420
412
|
try {
|
|
421
|
-
|
|
422
|
-
console.log(` Registered
|
|
413
|
+
installAntigravityGuard(p, guardAbs);
|
|
414
|
+
console.log(` Registered Antigravity CLI guard \u2192 ${p.antigravityHooksPath}`);
|
|
423
415
|
} catch {
|
|
424
416
|
}
|
|
425
417
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") {
|
package/dist/index.js
CHANGED
|
@@ -10211,7 +10211,7 @@ function protectedTargets() {
|
|
|
10211
10211
|
join11(p.hooksDir, "shield.mjs"),
|
|
10212
10212
|
p.configPath,
|
|
10213
10213
|
p.settingsPath,
|
|
10214
|
-
p.
|
|
10214
|
+
p.antigravityHooksPath
|
|
10215
10215
|
];
|
|
10216
10216
|
}
|
|
10217
10217
|
function lockProtected() {
|
|
@@ -10225,21 +10225,21 @@ function globalPaths() {
|
|
|
10225
10225
|
const sgDir = join11(home, ".solongate");
|
|
10226
10226
|
const hooksDir = join11(sgDir, "hooks");
|
|
10227
10227
|
const claudeDir = join11(home, ".claude");
|
|
10228
|
-
const
|
|
10228
|
+
const antigravityDir = join11(home, ".gemini", "config");
|
|
10229
10229
|
return {
|
|
10230
10230
|
home,
|
|
10231
10231
|
sgDir,
|
|
10232
10232
|
hooksDir,
|
|
10233
10233
|
claudeDir,
|
|
10234
|
-
|
|
10234
|
+
antigravityDir,
|
|
10235
10235
|
settingsPath: join11(claudeDir, "settings.json"),
|
|
10236
10236
|
backupPath: join11(claudeDir, "settings.solongate.bak"),
|
|
10237
10237
|
configPath: join11(sgDir, "cloud-guard.json"),
|
|
10238
|
-
//
|
|
10239
|
-
// guard is registered there (
|
|
10240
|
-
// covered by the passive session-log collector
|
|
10241
|
-
|
|
10242
|
-
|
|
10238
|
+
// Antigravity reads global hooks from ~/.gemini/config/hooks.json. Only the
|
|
10239
|
+
// guard is registered there (PreToolUse); Antigravity's ALLOW-path audit is
|
|
10240
|
+
// covered by the passive session-log collector, not a hook.
|
|
10241
|
+
antigravityHooksPath: join11(antigravityDir, "hooks.json"),
|
|
10242
|
+
antigravityBackupPath: join11(antigravityDir, "hooks.solongate.bak")
|
|
10243
10243
|
};
|
|
10244
10244
|
}
|
|
10245
10245
|
function readHook(filename) {
|
|
@@ -10249,47 +10249,38 @@ function readGuard() {
|
|
|
10249
10249
|
const bundled = join11(HOOKS_DIR, "guard.bundled.mjs");
|
|
10250
10250
|
return existsSync4(bundled) ? readFileSync9(bundled, "utf-8") : readHook("guard.mjs");
|
|
10251
10251
|
}
|
|
10252
|
-
function
|
|
10252
|
+
function antigravityHookCommand(guardAbs) {
|
|
10253
10253
|
const nodeBin = process.execPath.replace(/\\/g, "/");
|
|
10254
10254
|
const call = process.platform === "win32" ? "& " : "";
|
|
10255
|
-
return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}"
|
|
10255
|
+
return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}" antigravity "Antigravity"`;
|
|
10256
10256
|
}
|
|
10257
|
-
function
|
|
10258
|
-
mkdirSync8(p.
|
|
10257
|
+
function installAntigravityGuard(p, guardAbs) {
|
|
10258
|
+
mkdirSync8(p.antigravityDir, { recursive: true });
|
|
10259
10259
|
let existing = {};
|
|
10260
|
-
if (existsSync4(p.
|
|
10261
|
-
const raw = readFileSync9(p.
|
|
10262
|
-
if (!existsSync4(p.
|
|
10260
|
+
if (existsSync4(p.antigravityHooksPath)) {
|
|
10261
|
+
const raw = readFileSync9(p.antigravityHooksPath, "utf-8");
|
|
10262
|
+
if (!existsSync4(p.antigravityBackupPath)) writeFileSync9(p.antigravityBackupPath, raw);
|
|
10263
10263
|
try {
|
|
10264
10264
|
existing = JSON.parse(raw);
|
|
10265
10265
|
} catch {
|
|
10266
10266
|
existing = {};
|
|
10267
10267
|
}
|
|
10268
10268
|
}
|
|
10269
|
-
const existingHooks = existing.hooks && typeof existing.hooks === "object" ? existing.hooks : {};
|
|
10270
10269
|
const merged = {
|
|
10271
10270
|
...existing,
|
|
10272
|
-
|
|
10273
|
-
|
|
10274
|
-
BeforeTool: [{ matcher: "", hooks: [{ type: "command", command: geminiHookCommand(guardAbs) }] }]
|
|
10271
|
+
[ANTIGRAVITY_GROUP]: {
|
|
10272
|
+
PreToolUse: [{ matcher: "", hooks: [{ type: "command", command: antigravityHookCommand(guardAbs) }] }]
|
|
10275
10273
|
}
|
|
10276
10274
|
};
|
|
10277
|
-
writeFileSync9(p.
|
|
10275
|
+
writeFileSync9(p.antigravityHooksPath, JSON.stringify(merged, null, 2) + "\n");
|
|
10278
10276
|
}
|
|
10279
|
-
function
|
|
10280
|
-
if (!existsSync4(p.
|
|
10277
|
+
function removeAntigravityGuard(p) {
|
|
10278
|
+
if (!existsSync4(p.antigravityHooksPath)) return;
|
|
10281
10279
|
try {
|
|
10282
|
-
const s = JSON.parse(readFileSync9(p.
|
|
10283
|
-
|
|
10284
|
-
|
|
10285
|
-
|
|
10286
|
-
const inner = Array.isArray(entry?.hooks) ? entry.hooks : [];
|
|
10287
|
-
return !inner.some((h) => typeof h?.command === "string" && h.command.includes(".solongate"));
|
|
10288
|
-
});
|
|
10289
|
-
if (kept.length) hooks.BeforeTool = kept;
|
|
10290
|
-
else delete hooks.BeforeTool;
|
|
10291
|
-
if (Object.keys(hooks).length === 0) delete s.hooks;
|
|
10292
|
-
writeFileSync9(p.geminiSettingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
10280
|
+
const s = JSON.parse(readFileSync9(p.antigravityHooksPath, "utf-8"));
|
|
10281
|
+
if (!(ANTIGRAVITY_GROUP in s)) return;
|
|
10282
|
+
delete s[ANTIGRAVITY_GROUP];
|
|
10283
|
+
writeFileSync9(p.antigravityHooksPath, JSON.stringify(s, null, 2) + "\n");
|
|
10293
10284
|
} catch {
|
|
10294
10285
|
}
|
|
10295
10286
|
}
|
|
@@ -10336,7 +10327,7 @@ function installGlobalQuiet() {
|
|
|
10336
10327
|
};
|
|
10337
10328
|
writeFileSync9(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
10338
10329
|
try {
|
|
10339
|
-
|
|
10330
|
+
installAntigravityGuard(p, join11(p.hooksDir, "guard.mjs").replace(/\\/g, "/"));
|
|
10340
10331
|
} catch {
|
|
10341
10332
|
}
|
|
10342
10333
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") lockProtected();
|
|
@@ -10379,7 +10370,7 @@ function uninstallGlobalQuiet() {
|
|
|
10379
10370
|
unlockProtected();
|
|
10380
10371
|
removeClaudeShim();
|
|
10381
10372
|
try {
|
|
10382
|
-
|
|
10373
|
+
removeAntigravityGuard(p);
|
|
10383
10374
|
} catch {
|
|
10384
10375
|
}
|
|
10385
10376
|
if (!existsSync4(p.settingsPath)) return { ok: true, message: "guard removed (open a new session)" };
|
|
@@ -10424,12 +10415,13 @@ function removeClaudeShim() {
|
|
|
10424
10415
|
}
|
|
10425
10416
|
}
|
|
10426
10417
|
}
|
|
10427
|
-
var __dirname, HOOKS_DIR, SHIM_BEGIN, SHIM_END;
|
|
10418
|
+
var __dirname, HOOKS_DIR, ANTIGRAVITY_GROUP, SHIM_BEGIN, SHIM_END;
|
|
10428
10419
|
var init_global_install = __esm({
|
|
10429
10420
|
"src/global-install.ts"() {
|
|
10430
10421
|
"use strict";
|
|
10431
10422
|
__dirname = dirname3(fileURLToPath3(import.meta.url));
|
|
10432
10423
|
HOOKS_DIR = resolve4(__dirname, "..", "hooks");
|
|
10424
|
+
ANTIGRAVITY_GROUP = "solongate-guard";
|
|
10433
10425
|
SHIM_BEGIN = "# >>> SolonGate shield (auto secret redaction) >>>";
|
|
10434
10426
|
SHIM_END = "# <<< SolonGate shield <<<";
|
|
10435
10427
|
}
|
|
@@ -13513,7 +13505,7 @@ console.log('MCP servers communicate over stdin/stdout \u2014 not HTTP.');
|
|
|
13513
13505
|
console.log('You need an MCP client to connect:');
|
|
13514
13506
|
console.log('');
|
|
13515
13507
|
console.log(' Claude Code Open this folder, .mcp.json is auto-detected');
|
|
13516
|
-
console.log('
|
|
13508
|
+
console.log(' Antigravity .agents/mcp_config.json (or ~/.gemini/config/mcp_config.json)');
|
|
13517
13509
|
console.log(' OpenClaw Uses openclaw.plugin.json config');
|
|
13518
13510
|
console.log('');
|
|
13519
13511
|
console.log('Press Ctrl+C to stop.');
|
|
@@ -16450,7 +16442,7 @@ var SolonGateProxy = class {
|
|
|
16450
16442
|
const lower = raw.toLowerCase();
|
|
16451
16443
|
if (lower.includes("claude-code") || lower === "claude code") return { id: "claude-code", name: "Claude Code" };
|
|
16452
16444
|
if (lower.includes("claude")) return { id: "claude-desktop", name: "Claude Desktop" };
|
|
16453
|
-
if (lower.includes("
|
|
16445
|
+
if (lower.includes("antigravity") || lower === "agy") return { id: "antigravity", name: "Antigravity" };
|
|
16454
16446
|
return { id: raw.toLowerCase().replace(/\s+/g, "-"), name: raw };
|
|
16455
16447
|
}
|
|
16456
16448
|
/** Extract sub-agent identity from MCP _meta field */
|
package/dist/lib.js
CHANGED
|
@@ -9394,7 +9394,7 @@ var SolonGateProxy = class {
|
|
|
9394
9394
|
const lower = raw.toLowerCase();
|
|
9395
9395
|
if (lower.includes("claude-code") || lower === "claude code") return { id: "claude-code", name: "Claude Code" };
|
|
9396
9396
|
if (lower.includes("claude")) return { id: "claude-desktop", name: "Claude Desktop" };
|
|
9397
|
-
if (lower.includes("
|
|
9397
|
+
if (lower.includes("antigravity") || lower === "agy") return { id: "antigravity", name: "Antigravity" };
|
|
9398
9398
|
return { id: raw.toLowerCase().replace(/\s+/g, "-"), name: raw };
|
|
9399
9399
|
}
|
|
9400
9400
|
/** Extract sub-agent identity from MCP _meta field */
|
package/dist/login.js
CHANGED
|
@@ -99,7 +99,7 @@ function protectedTargets() {
|
|
|
99
99
|
join(p.hooksDir, "shield.mjs"),
|
|
100
100
|
p.configPath,
|
|
101
101
|
p.settingsPath,
|
|
102
|
-
p.
|
|
102
|
+
p.antigravityHooksPath
|
|
103
103
|
];
|
|
104
104
|
}
|
|
105
105
|
function lockProtected() {
|
|
@@ -113,21 +113,21 @@ function globalPaths() {
|
|
|
113
113
|
const sgDir = join(home, ".solongate");
|
|
114
114
|
const hooksDir = join(sgDir, "hooks");
|
|
115
115
|
const claudeDir = join(home, ".claude");
|
|
116
|
-
const
|
|
116
|
+
const antigravityDir = join(home, ".gemini", "config");
|
|
117
117
|
return {
|
|
118
118
|
home,
|
|
119
119
|
sgDir,
|
|
120
120
|
hooksDir,
|
|
121
121
|
claudeDir,
|
|
122
|
-
|
|
122
|
+
antigravityDir,
|
|
123
123
|
settingsPath: join(claudeDir, "settings.json"),
|
|
124
124
|
backupPath: join(claudeDir, "settings.solongate.bak"),
|
|
125
125
|
configPath: join(sgDir, "cloud-guard.json"),
|
|
126
|
-
//
|
|
127
|
-
// guard is registered there (
|
|
128
|
-
// covered by the passive session-log collector
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
// Antigravity reads global hooks from ~/.gemini/config/hooks.json. Only the
|
|
127
|
+
// guard is registered there (PreToolUse); Antigravity's ALLOW-path audit is
|
|
128
|
+
// covered by the passive session-log collector, not a hook.
|
|
129
|
+
antigravityHooksPath: join(antigravityDir, "hooks.json"),
|
|
130
|
+
antigravityBackupPath: join(antigravityDir, "hooks.solongate.bak")
|
|
131
131
|
};
|
|
132
132
|
}
|
|
133
133
|
function readHook(filename) {
|
|
@@ -137,32 +137,31 @@ function readGuard() {
|
|
|
137
137
|
const bundled = join(HOOKS_DIR, "guard.bundled.mjs");
|
|
138
138
|
return existsSync(bundled) ? readFileSync(bundled, "utf-8") : readHook("guard.mjs");
|
|
139
139
|
}
|
|
140
|
-
|
|
140
|
+
var ANTIGRAVITY_GROUP = "solongate-guard";
|
|
141
|
+
function antigravityHookCommand(guardAbs) {
|
|
141
142
|
const nodeBin = process.execPath.replace(/\\/g, "/");
|
|
142
143
|
const call = process.platform === "win32" ? "& " : "";
|
|
143
|
-
return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}"
|
|
144
|
+
return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}" antigravity "Antigravity"`;
|
|
144
145
|
}
|
|
145
|
-
function
|
|
146
|
-
mkdirSync(p.
|
|
146
|
+
function installAntigravityGuard(p, guardAbs) {
|
|
147
|
+
mkdirSync(p.antigravityDir, { recursive: true });
|
|
147
148
|
let existing = {};
|
|
148
|
-
if (existsSync(p.
|
|
149
|
-
const raw = readFileSync(p.
|
|
150
|
-
if (!existsSync(p.
|
|
149
|
+
if (existsSync(p.antigravityHooksPath)) {
|
|
150
|
+
const raw = readFileSync(p.antigravityHooksPath, "utf-8");
|
|
151
|
+
if (!existsSync(p.antigravityBackupPath)) writeFileSync(p.antigravityBackupPath, raw);
|
|
151
152
|
try {
|
|
152
153
|
existing = JSON.parse(raw);
|
|
153
154
|
} catch {
|
|
154
155
|
existing = {};
|
|
155
156
|
}
|
|
156
157
|
}
|
|
157
|
-
const existingHooks = existing.hooks && typeof existing.hooks === "object" ? existing.hooks : {};
|
|
158
158
|
const merged = {
|
|
159
159
|
...existing,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
BeforeTool: [{ matcher: "", hooks: [{ type: "command", command: geminiHookCommand(guardAbs) }] }]
|
|
160
|
+
[ANTIGRAVITY_GROUP]: {
|
|
161
|
+
PreToolUse: [{ matcher: "", hooks: [{ type: "command", command: antigravityHookCommand(guardAbs) }] }]
|
|
163
162
|
}
|
|
164
163
|
};
|
|
165
|
-
writeFileSync(p.
|
|
164
|
+
writeFileSync(p.antigravityHooksPath, JSON.stringify(merged, null, 2) + "\n");
|
|
166
165
|
}
|
|
167
166
|
function ask(question) {
|
|
168
167
|
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
@@ -293,8 +292,8 @@ async function runGlobalInstall(opts = {}) {
|
|
|
293
292
|
writeFileSync(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
294
293
|
console.log(` Registered global hooks \u2192 ${p.settingsPath}`);
|
|
295
294
|
try {
|
|
296
|
-
|
|
297
|
-
console.log(` Registered
|
|
295
|
+
installAntigravityGuard(p, guardAbs);
|
|
296
|
+
console.log(` Registered Antigravity CLI guard \u2192 ${p.antigravityHooksPath}`);
|
|
298
297
|
} catch {
|
|
299
298
|
}
|
|
300
299
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") {
|
package/dist/tui/index.js
CHANGED
|
@@ -3269,7 +3269,7 @@ function protectedTargets() {
|
|
|
3269
3269
|
join6(p.hooksDir, "shield.mjs"),
|
|
3270
3270
|
p.configPath,
|
|
3271
3271
|
p.settingsPath,
|
|
3272
|
-
p.
|
|
3272
|
+
p.antigravityHooksPath
|
|
3273
3273
|
];
|
|
3274
3274
|
}
|
|
3275
3275
|
function lockProtected() {
|
|
@@ -3283,21 +3283,21 @@ function globalPaths() {
|
|
|
3283
3283
|
const sgDir = join6(home, ".solongate");
|
|
3284
3284
|
const hooksDir = join6(sgDir, "hooks");
|
|
3285
3285
|
const claudeDir = join6(home, ".claude");
|
|
3286
|
-
const
|
|
3286
|
+
const antigravityDir = join6(home, ".gemini", "config");
|
|
3287
3287
|
return {
|
|
3288
3288
|
home,
|
|
3289
3289
|
sgDir,
|
|
3290
3290
|
hooksDir,
|
|
3291
3291
|
claudeDir,
|
|
3292
|
-
|
|
3292
|
+
antigravityDir,
|
|
3293
3293
|
settingsPath: join6(claudeDir, "settings.json"),
|
|
3294
3294
|
backupPath: join6(claudeDir, "settings.solongate.bak"),
|
|
3295
3295
|
configPath: join6(sgDir, "cloud-guard.json"),
|
|
3296
|
-
//
|
|
3297
|
-
// guard is registered there (
|
|
3298
|
-
// covered by the passive session-log collector
|
|
3299
|
-
|
|
3300
|
-
|
|
3296
|
+
// Antigravity reads global hooks from ~/.gemini/config/hooks.json. Only the
|
|
3297
|
+
// guard is registered there (PreToolUse); Antigravity's ALLOW-path audit is
|
|
3298
|
+
// covered by the passive session-log collector, not a hook.
|
|
3299
|
+
antigravityHooksPath: join6(antigravityDir, "hooks.json"),
|
|
3300
|
+
antigravityBackupPath: join6(antigravityDir, "hooks.solongate.bak")
|
|
3301
3301
|
};
|
|
3302
3302
|
}
|
|
3303
3303
|
function readHook(filename) {
|
|
@@ -3307,47 +3307,39 @@ function readGuard() {
|
|
|
3307
3307
|
const bundled = join6(HOOKS_DIR, "guard.bundled.mjs");
|
|
3308
3308
|
return existsSync2(bundled) ? readFileSync4(bundled, "utf-8") : readHook("guard.mjs");
|
|
3309
3309
|
}
|
|
3310
|
-
|
|
3310
|
+
var ANTIGRAVITY_GROUP = "solongate-guard";
|
|
3311
|
+
function antigravityHookCommand(guardAbs) {
|
|
3311
3312
|
const nodeBin = process.execPath.replace(/\\/g, "/");
|
|
3312
3313
|
const call = process.platform === "win32" ? "& " : "";
|
|
3313
|
-
return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}"
|
|
3314
|
+
return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}" antigravity "Antigravity"`;
|
|
3314
3315
|
}
|
|
3315
|
-
function
|
|
3316
|
-
mkdirSync4(p.
|
|
3316
|
+
function installAntigravityGuard(p, guardAbs) {
|
|
3317
|
+
mkdirSync4(p.antigravityDir, { recursive: true });
|
|
3317
3318
|
let existing = {};
|
|
3318
|
-
if (existsSync2(p.
|
|
3319
|
-
const raw = readFileSync4(p.
|
|
3320
|
-
if (!existsSync2(p.
|
|
3319
|
+
if (existsSync2(p.antigravityHooksPath)) {
|
|
3320
|
+
const raw = readFileSync4(p.antigravityHooksPath, "utf-8");
|
|
3321
|
+
if (!existsSync2(p.antigravityBackupPath)) writeFileSync5(p.antigravityBackupPath, raw);
|
|
3321
3322
|
try {
|
|
3322
3323
|
existing = JSON.parse(raw);
|
|
3323
3324
|
} catch {
|
|
3324
3325
|
existing = {};
|
|
3325
3326
|
}
|
|
3326
3327
|
}
|
|
3327
|
-
const existingHooks = existing.hooks && typeof existing.hooks === "object" ? existing.hooks : {};
|
|
3328
3328
|
const merged = {
|
|
3329
3329
|
...existing,
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
BeforeTool: [{ matcher: "", hooks: [{ type: "command", command: geminiHookCommand(guardAbs) }] }]
|
|
3330
|
+
[ANTIGRAVITY_GROUP]: {
|
|
3331
|
+
PreToolUse: [{ matcher: "", hooks: [{ type: "command", command: antigravityHookCommand(guardAbs) }] }]
|
|
3333
3332
|
}
|
|
3334
3333
|
};
|
|
3335
|
-
writeFileSync5(p.
|
|
3334
|
+
writeFileSync5(p.antigravityHooksPath, JSON.stringify(merged, null, 2) + "\n");
|
|
3336
3335
|
}
|
|
3337
|
-
function
|
|
3338
|
-
if (!existsSync2(p.
|
|
3336
|
+
function removeAntigravityGuard(p) {
|
|
3337
|
+
if (!existsSync2(p.antigravityHooksPath)) return;
|
|
3339
3338
|
try {
|
|
3340
|
-
const s = JSON.parse(readFileSync4(p.
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
const inner = Array.isArray(entry?.hooks) ? entry.hooks : [];
|
|
3345
|
-
return !inner.some((h) => typeof h?.command === "string" && h.command.includes(".solongate"));
|
|
3346
|
-
});
|
|
3347
|
-
if (kept.length) hooks.BeforeTool = kept;
|
|
3348
|
-
else delete hooks.BeforeTool;
|
|
3349
|
-
if (Object.keys(hooks).length === 0) delete s.hooks;
|
|
3350
|
-
writeFileSync5(p.geminiSettingsPath, JSON.stringify(s, null, 2) + "\n");
|
|
3339
|
+
const s = JSON.parse(readFileSync4(p.antigravityHooksPath, "utf-8"));
|
|
3340
|
+
if (!(ANTIGRAVITY_GROUP in s)) return;
|
|
3341
|
+
delete s[ANTIGRAVITY_GROUP];
|
|
3342
|
+
writeFileSync5(p.antigravityHooksPath, JSON.stringify(s, null, 2) + "\n");
|
|
3351
3343
|
} catch {
|
|
3352
3344
|
}
|
|
3353
3345
|
}
|
|
@@ -3394,7 +3386,7 @@ function installGlobalQuiet() {
|
|
|
3394
3386
|
};
|
|
3395
3387
|
writeFileSync5(p.settingsPath, JSON.stringify(merged, null, 2) + "\n");
|
|
3396
3388
|
try {
|
|
3397
|
-
|
|
3389
|
+
installAntigravityGuard(p, join6(p.hooksDir, "guard.mjs").replace(/\\/g, "/"));
|
|
3398
3390
|
} catch {
|
|
3399
3391
|
}
|
|
3400
3392
|
if (process.env["SOLONGATE_OS_LOCK"] === "1") lockProtected();
|
|
@@ -3437,7 +3429,7 @@ function uninstallGlobalQuiet() {
|
|
|
3437
3429
|
unlockProtected();
|
|
3438
3430
|
removeClaudeShim();
|
|
3439
3431
|
try {
|
|
3440
|
-
|
|
3432
|
+
removeAntigravityGuard(p);
|
|
3441
3433
|
} catch {
|
|
3442
3434
|
}
|
|
3443
3435
|
if (!existsSync2(p.settingsPath)) return { ok: true, message: "guard removed (open a new session)" };
|
package/hooks/guard.bundled.mjs
CHANGED
|
@@ -6536,7 +6536,7 @@ import { resolve, join, dirname, isAbsolute } from "node:path";
|
|
|
6536
6536
|
import { homedir } from "node:os";
|
|
6537
6537
|
import { gunzipSync } from "node:zlib";
|
|
6538
6538
|
import { createHash } from "node:crypto";
|
|
6539
|
-
var HOOK_VERSION =
|
|
6539
|
+
var HOOK_VERSION = 44;
|
|
6540
6540
|
function localLogsOnly(security) {
|
|
6541
6541
|
if (security && typeof security === "object") {
|
|
6542
6542
|
const l = security.localLogs;
|
|
@@ -6797,7 +6797,7 @@ function sgFinish(code) {
|
|
|
6797
6797
|
throw SG_DONE;
|
|
6798
6798
|
}
|
|
6799
6799
|
function blockTool(reason) {
|
|
6800
|
-
if (AGENT_TYPE === "
|
|
6800
|
+
if (AGENT_TYPE === "antigravity") {
|
|
6801
6801
|
process.stdout.write(JSON.stringify({
|
|
6802
6802
|
decision: "deny",
|
|
6803
6803
|
reason: `[SolonGate] ${reason}`
|
|
@@ -6817,7 +6817,7 @@ function blockTool(reason) {
|
|
|
6817
6817
|
}
|
|
6818
6818
|
}
|
|
6819
6819
|
function allowTool() {
|
|
6820
|
-
if (AGENT_TYPE === "
|
|
6820
|
+
if (AGENT_TYPE === "antigravity") {
|
|
6821
6821
|
process.stdout.write(JSON.stringify({ decision: "allow" }));
|
|
6822
6822
|
}
|
|
6823
6823
|
sgFinish(0);
|
|
@@ -7072,7 +7072,12 @@ var TAMPER_PATH_FIELDS = /* @__PURE__ */ new Set([
|
|
|
7072
7072
|
"to",
|
|
7073
7073
|
"directory",
|
|
7074
7074
|
"dir",
|
|
7075
|
-
"folder"
|
|
7075
|
+
"folder",
|
|
7076
|
+
// Antigravity CLI file-tool arg names (camelCase, lowercased here): its
|
|
7077
|
+
// write/read/list tools carry the path in these, so tamper protection sees it.
|
|
7078
|
+
"targetfile",
|
|
7079
|
+
"absolutepath",
|
|
7080
|
+
"filepath"
|
|
7076
7081
|
]);
|
|
7077
7082
|
function normTamperPath(p) {
|
|
7078
7083
|
return String(p || "").replace(/\\/g, "/").toLowerCase();
|
|
@@ -7763,13 +7768,30 @@ if (!REFRESH_MODE) {
|
|
|
7763
7768
|
}
|
|
7764
7769
|
let mappedToolName = raw.tool_name || raw.toolName || "";
|
|
7765
7770
|
let mappedToolInput = raw.tool_input || raw.toolInput || raw.params || {};
|
|
7771
|
+
let mappedSession = raw.session_id || raw.sessionId || raw.conversation_id || "";
|
|
7772
|
+
let mappedCwd = raw.cwd || "";
|
|
7773
|
+
if (raw.toolCall && typeof raw.toolCall === "object") {
|
|
7774
|
+
const tc = raw.toolCall;
|
|
7775
|
+
mappedToolName = mappedToolName || tc.name || "";
|
|
7776
|
+
const a = tc.args && typeof tc.args === "object" ? tc.args : {};
|
|
7777
|
+
mappedToolInput = { ...a };
|
|
7778
|
+
if (typeof a.CommandLine === "string" && mappedToolInput.command == null)
|
|
7779
|
+
mappedToolInput.command = a.CommandLine;
|
|
7780
|
+
mappedSession = mappedSession || raw.conversationId || "";
|
|
7781
|
+
if (!mappedCwd) {
|
|
7782
|
+
if (typeof a.Cwd === "string" && a.Cwd)
|
|
7783
|
+
mappedCwd = a.Cwd;
|
|
7784
|
+
else if (Array.isArray(raw.workspacePaths) && typeof raw.workspacePaths[0] === "string")
|
|
7785
|
+
mappedCwd = raw.workspacePaths[0];
|
|
7786
|
+
}
|
|
7787
|
+
}
|
|
7766
7788
|
const data = {
|
|
7767
7789
|
...raw,
|
|
7768
7790
|
tool_name: mappedToolName,
|
|
7769
7791
|
tool_input: mappedToolInput,
|
|
7770
7792
|
tool_response: raw.tool_response || raw.toolResponse || {},
|
|
7771
|
-
cwd:
|
|
7772
|
-
session_id:
|
|
7793
|
+
cwd: mappedCwd || process.cwd(),
|
|
7794
|
+
session_id: mappedSession
|
|
7773
7795
|
};
|
|
7774
7796
|
const args = data.tool_input;
|
|
7775
7797
|
const toolName = data.tool_name || "";
|
|
@@ -7943,7 +7965,7 @@ if (!REFRESH_MODE) {
|
|
|
7943
7965
|
} catch {
|
|
7944
7966
|
}
|
|
7945
7967
|
await maybeSelfUpdate();
|
|
7946
|
-
if (AGENT_TYPE === "
|
|
7968
|
+
if (AGENT_TYPE === "antigravity") {
|
|
7947
7969
|
process.stdout.write(JSON.stringify({ decision: "deny", reason: ghostHit }));
|
|
7948
7970
|
sgFinish(0);
|
|
7949
7971
|
}
|
|
@@ -7951,7 +7973,7 @@ if (!REFRESH_MODE) {
|
|
|
7951
7973
|
process.stderr.write(ghostHit + "\n");
|
|
7952
7974
|
sgFinish(2);
|
|
7953
7975
|
}
|
|
7954
|
-
if (AGENT_TYPE !== "
|
|
7976
|
+
if (AGENT_TYPE !== "antigravity" && toolName === "Bash") {
|
|
7955
7977
|
const rw = ghostListingRewrite(args, securityCfg.ghost);
|
|
7956
7978
|
if (rw) {
|
|
7957
7979
|
await maybeSelfUpdate();
|
package/hooks/guard.mjs
CHANGED
|
@@ -32,7 +32,7 @@ import { createHash } from 'node:crypto';
|
|
|
32
32
|
// the installed hook self-updates when the cloud version is higher (see
|
|
33
33
|
// maybeSelfUpdate). This is what makes guard fixes propagate without a manual
|
|
34
34
|
// reinstall — the same trust model as the OPA WASM this hook already runs.
|
|
35
|
-
const HOOK_VERSION =
|
|
35
|
+
const HOOK_VERSION = 44;
|
|
36
36
|
|
|
37
37
|
// True when local log storage is ON. In that mode logs are kept LOCAL ONLY and
|
|
38
38
|
// nothing is sent to the cloud audit log.
|
|
@@ -276,7 +276,7 @@ async function maybeSelfUpdate() {
|
|
|
276
276
|
// Two distinct identities, deliberately kept separate:
|
|
277
277
|
//
|
|
278
278
|
// AGENT_TYPE — the real AI client running this hook (claude-code /
|
|
279
|
-
//
|
|
279
|
+
// antigravity / openclaw). Baked into the hook registration by the installer
|
|
280
280
|
// as argv[2] (e.g. `node guard.mjs claude-code`). Decides the response
|
|
281
281
|
// format AND whether a selected policy actually applies to this client.
|
|
282
282
|
//
|
|
@@ -344,8 +344,8 @@ if (REFRESH_MODE) { try { setTimeout(() => { try { process.exit(process.exitCode
|
|
|
344
344
|
|
|
345
345
|
// ── Per-tool block/allow output ──
|
|
346
346
|
// Response format depends on the agent:
|
|
347
|
-
// Claude Code:
|
|
348
|
-
//
|
|
347
|
+
// Claude Code: exit 2 + stderr = BLOCK, exit 0 = ALLOW
|
|
348
|
+
// Antigravity CLI: {"decision": "deny/allow", "reason": "..."} on stdout (exit 0)
|
|
349
349
|
|
|
350
350
|
// Terminate the hook WITHOUT forcing process.exit(). On Windows + Node 24, calling
|
|
351
351
|
// process.exit() right after a fetch() (the cloud audit-log POST) aborts with
|
|
@@ -378,7 +378,7 @@ function sgFinish(code) {
|
|
|
378
378
|
}
|
|
379
379
|
|
|
380
380
|
function blockTool(reason) {
|
|
381
|
-
if (AGENT_TYPE === '
|
|
381
|
+
if (AGENT_TYPE === 'antigravity') {
|
|
382
382
|
process.stdout.write(JSON.stringify({
|
|
383
383
|
decision: 'deny',
|
|
384
384
|
reason: `[SolonGate] ${reason}`,
|
|
@@ -408,7 +408,7 @@ function blockTool(reason) {
|
|
|
408
408
|
}
|
|
409
409
|
|
|
410
410
|
function allowTool() {
|
|
411
|
-
if (AGENT_TYPE === '
|
|
411
|
+
if (AGENT_TYPE === 'antigravity') {
|
|
412
412
|
process.stdout.write(JSON.stringify({ decision: 'allow' }));
|
|
413
413
|
}
|
|
414
414
|
sgFinish(0);
|
|
@@ -784,6 +784,9 @@ const TAMPER_PATH_FIELDS = new Set([
|
|
|
784
784
|
'file_path', 'path', 'target_file', 'notebook_path',
|
|
785
785
|
'dest', 'destination', 'source', 'src', 'from', 'to',
|
|
786
786
|
'directory', 'dir', 'folder',
|
|
787
|
+
// Antigravity CLI file-tool arg names (camelCase, lowercased here): its
|
|
788
|
+
// write/read/list tools carry the path in these, so tamper protection sees it.
|
|
789
|
+
'targetfile', 'absolutepath', 'filepath',
|
|
787
790
|
]);
|
|
788
791
|
|
|
789
792
|
function normTamperPath(p) {
|
|
@@ -1581,6 +1584,30 @@ if (!REFRESH_MODE) { try { input += readFileSync(0, 'utf-8'); } catch {} }
|
|
|
1581
1584
|
|
|
1582
1585
|
let mappedToolName = raw.tool_name || raw.toolName || '';
|
|
1583
1586
|
let mappedToolInput = raw.tool_input || raw.toolInput || raw.params || {};
|
|
1587
|
+
let mappedSession = raw.session_id || raw.sessionId || raw.conversation_id || '';
|
|
1588
|
+
let mappedCwd = raw.cwd || '';
|
|
1589
|
+
|
|
1590
|
+
// Antigravity CLI (PreToolUse) nests the tool under a `toolCall` object
|
|
1591
|
+
// ({ name, args: { CommandLine, Cwd, ... } }) and carries metadata in
|
|
1592
|
+
// camelCase (conversationId, workspacePaths) — a different shape from the
|
|
1593
|
+
// flat Claude/Gemini payload. Flatten it into the fields the guard's
|
|
1594
|
+
// extractors read, and alias the shell command (args.CommandLine) to
|
|
1595
|
+
// `command` so extractCommands / tamperCheck / command policies see it. Tool
|
|
1596
|
+
// NAMES need no remapping: guessPermission/tamperCheck already classify
|
|
1597
|
+
// Antigravity's snake_case names (run_command → EXECUTE via "run",
|
|
1598
|
+
// write_to_file → WRITE, read_file → READ) by substring.
|
|
1599
|
+
if (raw.toolCall && typeof raw.toolCall === 'object') {
|
|
1600
|
+
const tc = raw.toolCall;
|
|
1601
|
+
mappedToolName = mappedToolName || tc.name || '';
|
|
1602
|
+
const a = (tc.args && typeof tc.args === 'object') ? tc.args : {};
|
|
1603
|
+
mappedToolInput = { ...a };
|
|
1604
|
+
if (typeof a.CommandLine === 'string' && mappedToolInput.command == null) mappedToolInput.command = a.CommandLine;
|
|
1605
|
+
mappedSession = mappedSession || raw.conversationId || '';
|
|
1606
|
+
if (!mappedCwd) {
|
|
1607
|
+
if (typeof a.Cwd === 'string' && a.Cwd) mappedCwd = a.Cwd;
|
|
1608
|
+
else if (Array.isArray(raw.workspacePaths) && typeof raw.workspacePaths[0] === 'string') mappedCwd = raw.workspacePaths[0];
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1584
1611
|
|
|
1585
1612
|
// Normalize field names across tools
|
|
1586
1613
|
const data = {
|
|
@@ -1588,8 +1615,8 @@ if (!REFRESH_MODE) { try { input += readFileSync(0, 'utf-8'); } catch {} }
|
|
|
1588
1615
|
tool_name: mappedToolName,
|
|
1589
1616
|
tool_input: mappedToolInput,
|
|
1590
1617
|
tool_response: raw.tool_response || raw.toolResponse || {},
|
|
1591
|
-
cwd:
|
|
1592
|
-
session_id:
|
|
1618
|
+
cwd: mappedCwd || process.cwd(),
|
|
1619
|
+
session_id: mappedSession,
|
|
1593
1620
|
};
|
|
1594
1621
|
const args = data.tool_input;
|
|
1595
1622
|
const toolName = data.tool_name || '';
|
|
@@ -1789,7 +1816,7 @@ if (!REFRESH_MODE) { try { input += readFileSync(0, 'utf-8'); } catch {} }
|
|
|
1789
1816
|
});
|
|
1790
1817
|
} catch {}
|
|
1791
1818
|
await maybeSelfUpdate();
|
|
1792
|
-
if (AGENT_TYPE === '
|
|
1819
|
+
if (AGENT_TYPE === 'antigravity') { process.stdout.write(JSON.stringify({ decision: 'deny', reason: ghostHit })); sgFinish(0); }
|
|
1793
1820
|
// Claude Code: JSON deny on stdout + exit 2 (reason on stderr). Exit 2 is
|
|
1794
1821
|
// the only block enforced in auto-accept mode (see blockTool); the JSON is
|
|
1795
1822
|
// the Windows fallback. ghostHit is a bare "No such file or directory", so
|
|
@@ -1800,7 +1827,7 @@ if (!REFRESH_MODE) { try { input += readFileSync(0, 'utf-8'); } catch {} }
|
|
|
1800
1827
|
}
|
|
1801
1828
|
// No direct hit: if this is a listing command, rewrite it so hidden
|
|
1802
1829
|
// entries are filtered out of its output (Claude Code only).
|
|
1803
|
-
if (AGENT_TYPE !== '
|
|
1830
|
+
if (AGENT_TYPE !== 'antigravity' && toolName === 'Bash') {
|
|
1804
1831
|
const rw = ghostListingRewrite(args, securityCfg.ghost);
|
|
1805
1832
|
if (rw) { await maybeSelfUpdate(); rewriteTool({ command: rw }); }
|
|
1806
1833
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.82.
|
|
3
|
+
"version": "0.82.12",
|
|
4
4
|
"description": "AI tool security proxy: protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. No code changes required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|