@solongate/proxy 0.82.11 → 0.82.13

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/README.md CHANGED
@@ -61,7 +61,7 @@ Manage everything from the **Policies**, **Audit**, and **Settings** pages in th
61
61
  <table cellspacing="0" cellpadding="0" border="0" align="center">
62
62
  <tr>
63
63
  <td><a href="https://claude.com/claude-code"><img src="https://solongate.com/cells/claude.png" width="200" alt="Claude Code" /></a></td>
64
- <td><a href="https://github.com/google-gemini/gemini-cli"><img src="https://solongate.com/cells/gemini.png" width="200" alt="Gemini CLI" /></a></td>
64
+ <td><a href="https://antigravity.google"><img src="https://solongate.com/cells/antigravity.png" width="200" alt="Antigravity CLI" /></a></td>
65
65
  <td><a href="https://openclaw.ai"><img src="https://solongate.com/cells/openclaw.png" width="200" alt="OpenClaw (soon)" /></a></td>
66
66
  <td><a href="https://openai.com/codex"><img src="https://solongate.com/cells/codex.png" width="200" alt="Codex (soon)" /></a></td>
67
67
  </tr>
@@ -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(` Gemini CLI \u2192 ${resolve(home, ".gemini", "tmp")}`);
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: "Gemini CLI", path: resolve(home, ".gemini", "tmp") },
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: `Gemini CLI (${user})`, path: resolve(userHome, ".gemini", "tmp") },
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: `Gemini CLI (${user})`, path: resolve(userHome, ".gemini", "tmp") },
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 collectGemini() {
264
+ function collectAntigravity() {
265
265
  const sessions = [];
266
- const geminiDir = resolve2(homedir2(), ".gemini", "tmp");
267
- if (!existsSync2(geminiDir)) return sessions;
268
- for (const projectDir of readdirSync(geminiDir)) {
269
- const chatsDir = join2(geminiDir, projectDir, "chats");
270
- if (!existsSync2(chatsDir) || !statSync(chatsDir).isDirectory()) continue;
271
- for (const file of readdirSync(chatsDir)) {
272
- if (!file.startsWith("session-") || !file.endsWith(".json")) continue;
273
- const filePath = join2(chatsDir, file);
274
- try {
275
- const data = JSON.parse(readFileSync2(filePath, "utf-8"));
276
- const toolCalls = [];
277
- const userMessages = [];
278
- const sessionId = data.sessionId || file.replace(".json", "");
279
- for (const msg of data.messages || []) {
280
- if (msg.role === "user" && (msg.text || msg.content)) {
281
- const text = String(msg.text || msg.content).slice(0, 500);
282
- if (text.length > 0) {
283
- userMessages.push({ timestamp: msg.timestamp || data.startTime || "", text });
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 (!msg.toolCalls || !Array.isArray(msg.toolCalls)) continue;
287
- for (const tc of msg.toolCalls) {
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: tc.result ? JSON.stringify(tc.result).slice(0, 2e3) : void 0,
293
- isError: tc.status === "error",
294
- timestamp: tc.timestamp || msg.timestamp || data.startTime || "",
295
- source: "gemini",
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: "gemini", sessionId });
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: "gemini", startTime: data.startTime || "", endTime: data.lastUpdated || "", model: data.messages?.[0]?.model || "", toolCalls, filePath });
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 geminiSessions = collectGemini();
518
+ const antigravitySessions = collectAntigravity();
506
519
  const openclawSessions = collectOpenClaw();
507
520
  const customSessions = collectCustomDirs();
508
- const sessions = [...claudeSessions, ...geminiSessions, ...openclawSessions, ...customSessions].sort((a, b) => (a.startTime || "").localeCompare(b.startTime || ""));
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 (geminiSessions.length > 0) sources.push("Gemini CLI");
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
- gemini: source_default.blue,
2615
+ antigravity: source_default.blue,
2603
2616
  openclaw: source_default.green
2604
2617
  };
2605
2618
  var SOURCE_LABEL = {
2606
2619
  claude: "Claude",
2607
- gemini: "Gemini",
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
- gemini: "Gemini",
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-gemini { background: rgba(96,165,250,0.12); color: #60a5fa; }
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="gemini">Gemini</option><option value="openclaw">OpenClaw</option></select>
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>
@@ -19,7 +19,7 @@ export interface ToolCall {
19
19
  result?: string;
20
20
  isError?: boolean;
21
21
  timestamp: string;
22
- source: 'claude' | 'gemini' | 'openclaw';
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' | 'gemini' | 'openclaw';
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' | 'gemini' | 'openclaw' | 'all';
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(' Gemini CLI Open this folder, .mcp.json is auto-detected');
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.');
@@ -5,12 +5,12 @@ export declare function globalPaths(): {
5
5
  sgDir: string;
6
6
  hooksDir: string;
7
7
  claudeDir: string;
8
- geminiDir: string;
8
+ antigravityDir: string;
9
9
  settingsPath: string;
10
10
  backupPath: string;
11
11
  configPath: string;
12
- geminiSettingsPath: string;
13
- geminiBackupPath: string;
12
+ antigravityHooksPath: string;
13
+ antigravityBackupPath: string;
14
14
  };
15
15
  export declare function clearGuardUpdateCheck(): boolean;
16
16
  export declare function runGlobalRestore(): void;
@@ -72,7 +72,7 @@ function protectedTargets() {
72
72
  join(p.hooksDir, "shield.mjs"),
73
73
  p.configPath,
74
74
  p.settingsPath,
75
- p.geminiSettingsPath
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 geminiDir = join(home, ".gemini");
89
+ const antigravityDir = join(home, ".gemini", "config");
90
90
  return {
91
91
  home,
92
92
  sgDir,
93
93
  hooksDir,
94
94
  claudeDir,
95
- geminiDir,
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
- // Gemini CLI reads hooks from ~/.gemini/settings.json (user-level). Only the
100
- // guard is registered there (BeforeTool); Gemini's ALLOW-path audit is
101
- // covered by the passive session-log collector (~/.gemini/tmp), not a hook.
102
- geminiSettingsPath: join(geminiDir, "settings.json"),
103
- geminiBackupPath: join(geminiDir, "settings.solongate.bak")
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
- function geminiHookCommand(guardAbs) {
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, "/")}" gemini-cli "Gemini CLI"`;
125
+ return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}" antigravity "Antigravity"`;
125
126
  }
126
- function installGeminiGuard(p, guardAbs) {
127
- mkdirSync(p.geminiDir, { recursive: true });
127
+ function installAntigravityGuard(p, guardAbs) {
128
+ mkdirSync(p.antigravityDir, { recursive: true });
128
129
  let existing = {};
129
- if (existsSync(p.geminiSettingsPath)) {
130
- const raw = readFileSync(p.geminiSettingsPath, "utf-8");
131
- if (!existsSync(p.geminiBackupPath)) writeFileSync(p.geminiBackupPath, raw);
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
- hooks: {
142
- ...existingHooks,
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.geminiSettingsPath, JSON.stringify(merged, null, 2) + "\n");
145
+ writeFileSync(p.antigravityHooksPath, JSON.stringify(merged, null, 2) + "\n");
147
146
  }
148
- function removeGeminiGuard(p) {
149
- if (!existsSync(p.geminiSettingsPath)) return;
147
+ function removeAntigravityGuard(p) {
148
+ if (!existsSync(p.antigravityHooksPath)) return;
150
149
  try {
151
- const s = JSON.parse(readFileSync(p.geminiSettingsPath, "utf-8"));
152
- const hooks = s.hooks && typeof s.hooks === "object" ? s.hooks : null;
153
- if (!hooks || !Array.isArray(hooks.BeforeTool)) return;
154
- const kept = hooks.BeforeTool.filter((entry) => {
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
- removeGeminiGuard(p);
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
- installGeminiGuard(p, join(p.hooksDir, "guard.mjs").replace(/\\/g, "/"));
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
- removeGeminiGuard(p);
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
- installGeminiGuard(p, guardAbs);
422
- console.log(` Registered Gemini CLI guard \u2192 ${p.geminiSettingsPath}`);
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.geminiSettingsPath
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 geminiDir = join11(home, ".gemini");
10228
+ const antigravityDir = join11(home, ".gemini", "config");
10229
10229
  return {
10230
10230
  home,
10231
10231
  sgDir,
10232
10232
  hooksDir,
10233
10233
  claudeDir,
10234
- geminiDir,
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
- // Gemini CLI reads hooks from ~/.gemini/settings.json (user-level). Only the
10239
- // guard is registered there (BeforeTool); Gemini's ALLOW-path audit is
10240
- // covered by the passive session-log collector (~/.gemini/tmp), not a hook.
10241
- geminiSettingsPath: join11(geminiDir, "settings.json"),
10242
- geminiBackupPath: join11(geminiDir, "settings.solongate.bak")
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 geminiHookCommand(guardAbs) {
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, "/")}" gemini-cli "Gemini CLI"`;
10255
+ return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}" antigravity "Antigravity"`;
10256
10256
  }
10257
- function installGeminiGuard(p, guardAbs) {
10258
- mkdirSync8(p.geminiDir, { recursive: true });
10257
+ function installAntigravityGuard(p, guardAbs) {
10258
+ mkdirSync8(p.antigravityDir, { recursive: true });
10259
10259
  let existing = {};
10260
- if (existsSync4(p.geminiSettingsPath)) {
10261
- const raw = readFileSync9(p.geminiSettingsPath, "utf-8");
10262
- if (!existsSync4(p.geminiBackupPath)) writeFileSync9(p.geminiBackupPath, raw);
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
- hooks: {
10273
- ...existingHooks,
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.geminiSettingsPath, JSON.stringify(merged, null, 2) + "\n");
10275
+ writeFileSync9(p.antigravityHooksPath, JSON.stringify(merged, null, 2) + "\n");
10278
10276
  }
10279
- function removeGeminiGuard(p) {
10280
- if (!existsSync4(p.geminiSettingsPath)) return;
10277
+ function removeAntigravityGuard(p) {
10278
+ if (!existsSync4(p.antigravityHooksPath)) return;
10281
10279
  try {
10282
- const s = JSON.parse(readFileSync9(p.geminiSettingsPath, "utf-8"));
10283
- const hooks = s.hooks && typeof s.hooks === "object" ? s.hooks : null;
10284
- if (!hooks || !Array.isArray(hooks.BeforeTool)) return;
10285
- const kept = hooks.BeforeTool.filter((entry) => {
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
- installGeminiGuard(p, join11(p.hooksDir, "guard.mjs").replace(/\\/g, "/"));
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
- removeGeminiGuard(p);
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(' Gemini CLI Open this folder, .mcp.json is auto-detected');
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("gemini")) return { id: "gemini-cli", name: "Gemini CLI" };
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("gemini")) return { id: "gemini-cli", name: "Gemini CLI" };
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.geminiSettingsPath
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 geminiDir = join(home, ".gemini");
116
+ const antigravityDir = join(home, ".gemini", "config");
117
117
  return {
118
118
  home,
119
119
  sgDir,
120
120
  hooksDir,
121
121
  claudeDir,
122
- geminiDir,
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
- // Gemini CLI reads hooks from ~/.gemini/settings.json (user-level). Only the
127
- // guard is registered there (BeforeTool); Gemini's ALLOW-path audit is
128
- // covered by the passive session-log collector (~/.gemini/tmp), not a hook.
129
- geminiSettingsPath: join(geminiDir, "settings.json"),
130
- geminiBackupPath: join(geminiDir, "settings.solongate.bak")
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
- function geminiHookCommand(guardAbs) {
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, "/")}" gemini-cli "Gemini CLI"`;
144
+ return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}" antigravity "Antigravity"`;
144
145
  }
145
- function installGeminiGuard(p, guardAbs) {
146
- mkdirSync(p.geminiDir, { recursive: true });
146
+ function installAntigravityGuard(p, guardAbs) {
147
+ mkdirSync(p.antigravityDir, { recursive: true });
147
148
  let existing = {};
148
- if (existsSync(p.geminiSettingsPath)) {
149
- const raw = readFileSync(p.geminiSettingsPath, "utf-8");
150
- if (!existsSync(p.geminiBackupPath)) writeFileSync(p.geminiBackupPath, raw);
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
- hooks: {
161
- ...existingHooks,
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.geminiSettingsPath, JSON.stringify(merged, null, 2) + "\n");
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
- installGeminiGuard(p, guardAbs);
297
- console.log(` Registered Gemini CLI guard \u2192 ${p.geminiSettingsPath}`);
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.geminiSettingsPath
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 geminiDir = join6(home, ".gemini");
3286
+ const antigravityDir = join6(home, ".gemini", "config");
3287
3287
  return {
3288
3288
  home,
3289
3289
  sgDir,
3290
3290
  hooksDir,
3291
3291
  claudeDir,
3292
- geminiDir,
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
- // Gemini CLI reads hooks from ~/.gemini/settings.json (user-level). Only the
3297
- // guard is registered there (BeforeTool); Gemini's ALLOW-path audit is
3298
- // covered by the passive session-log collector (~/.gemini/tmp), not a hook.
3299
- geminiSettingsPath: join6(geminiDir, "settings.json"),
3300
- geminiBackupPath: join6(geminiDir, "settings.solongate.bak")
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
- function geminiHookCommand(guardAbs) {
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, "/")}" gemini-cli "Gemini CLI"`;
3314
+ return `${call}"${nodeBin}" "${guardAbs.replace(/\\/g, "/")}" antigravity "Antigravity"`;
3314
3315
  }
3315
- function installGeminiGuard(p, guardAbs) {
3316
- mkdirSync4(p.geminiDir, { recursive: true });
3316
+ function installAntigravityGuard(p, guardAbs) {
3317
+ mkdirSync4(p.antigravityDir, { recursive: true });
3317
3318
  let existing = {};
3318
- if (existsSync2(p.geminiSettingsPath)) {
3319
- const raw = readFileSync4(p.geminiSettingsPath, "utf-8");
3320
- if (!existsSync2(p.geminiBackupPath)) writeFileSync5(p.geminiBackupPath, raw);
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
- hooks: {
3331
- ...existingHooks,
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.geminiSettingsPath, JSON.stringify(merged, null, 2) + "\n");
3334
+ writeFileSync5(p.antigravityHooksPath, JSON.stringify(merged, null, 2) + "\n");
3336
3335
  }
3337
- function removeGeminiGuard(p) {
3338
- if (!existsSync2(p.geminiSettingsPath)) return;
3336
+ function removeAntigravityGuard(p) {
3337
+ if (!existsSync2(p.antigravityHooksPath)) return;
3339
3338
  try {
3340
- const s = JSON.parse(readFileSync4(p.geminiSettingsPath, "utf-8"));
3341
- const hooks = s.hooks && typeof s.hooks === "object" ? s.hooks : null;
3342
- if (!hooks || !Array.isArray(hooks.BeforeTool)) return;
3343
- const kept = hooks.BeforeTool.filter((entry) => {
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
- installGeminiGuard(p, join6(p.hooksDir, "guard.mjs").replace(/\\/g, "/"));
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
- removeGeminiGuard(p);
3432
+ removeAntigravityGuard(p);
3441
3433
  } catch {
3442
3434
  }
3443
3435
  if (!existsSync2(p.settingsPath)) return { ok: true, message: "guard removed (open a new session)" };
@@ -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 = 43;
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 === "gemini-cli") {
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 === "gemini-cli") {
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: raw.cwd || process.cwd(),
7772
- session_id: raw.session_id || raw.sessionId || raw.conversation_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 === "gemini-cli") {
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 !== "gemini-cli" && toolName === "Bash") {
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 = 43;
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
- // gemini-cli / openclaw). Baked into the hook registration by the installer
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: exit 2 + stderr = BLOCK, exit 0 = ALLOW
348
- // Gemini CLI: {"decision": "deny/allow", "reason": "..."}
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 === 'gemini-cli') {
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 === 'gemini-cli') {
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: raw.cwd || process.cwd(),
1592
- session_id: raw.session_id || raw.sessionId || raw.conversation_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 === 'gemini-cli') { process.stdout.write(JSON.stringify({ decision: 'deny', reason: ghostHit })); sgFinish(0); }
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 !== 'gemini-cli' && toolName === 'Bash') {
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.11",
3
+ "version": "0.82.13",
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": {