antigravity-usage 0.2.7 → 0.2.9

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
@@ -174,10 +174,27 @@ Quickly check if your auth tokens are valid or expired.
174
174
  antigravity-usage wakeup config # Interactive setup (takes 30 seconds)
175
175
  antigravity-usage wakeup install # Install to native system cron
176
176
  antigravity-usage wakeup status # Check configuration & next run
177
- antigravity-usage wakeup test # Test trigger manually
177
+ antigravity-usage wakeup test # Test trigger manually (interactive)
178
178
  antigravity-usage wakeup history # View trigger history
179
179
  ```
180
180
 
181
+ **Quick Test with Flags:**
182
+ ```bash
183
+ # Test with specific email and model
184
+ antigravity-usage wakeup test -e your@gmail.com -m claude-sonnet-4-5
185
+
186
+ # Full command with custom prompt
187
+ antigravity-usage wakeup test --email your@gmail.com --model gemini-3-flash --prompt "hello"
188
+
189
+ # Mix flags (missing ones will be prompted)
190
+ antigravity-usage wakeup test -e your@gmail.com
191
+ ```
192
+
193
+ **Available Options:**
194
+ - `-e, --email <email>` - Account email to use for testing
195
+ - `-m, --model <model>` - Model ID to test (e.g., claude-sonnet-4-5, gemini-3-flash)
196
+ - `-p, --prompt <prompt>` - Test prompt to send (default: "hi")
197
+
181
198
  **Why This Matters:**
182
199
  Your Antigravity quota resets every ~5 hours, but if you don't use it, you lose it. The wakeup feature ensures you **automatically trigger** both Claude and Gemini models to keep your quota flowing.
183
200
 
package/dist/index.js CHANGED
@@ -1679,15 +1679,16 @@ var CloudCodeClient = class {
1679
1679
  if (jsonStr.trim() === "[DONE]") continue;
1680
1680
  try {
1681
1681
  const data = JSON.parse(jsonStr);
1682
- const candidateText = data.candidates?.[0]?.content?.parts?.[0]?.text;
1682
+ const responseData = data.response || data;
1683
+ const candidateText = responseData.candidates?.[0]?.content?.parts?.[0]?.text;
1683
1684
  if (candidateText) {
1684
1685
  fullText += candidateText;
1685
1686
  }
1686
- if (data.usageMetadata) {
1687
+ if (responseData.usageMetadata) {
1687
1688
  tokensUsed = {
1688
- prompt: data.usageMetadata.promptTokenCount || 0,
1689
- completion: data.usageMetadata.candidatesTokenCount || 0,
1690
- total: data.usageMetadata.totalTokenCount || 0
1689
+ prompt: responseData.usageMetadata.promptTokenCount || 0,
1690
+ completion: responseData.usageMetadata.candidatesTokenCount || 0,
1691
+ total: responseData.usageMetadata.totalTokenCount || 0
1691
1692
  };
1692
1693
  }
1693
1694
  } catch {
@@ -1852,12 +1853,21 @@ async function detectOnUnix() {
1852
1853
  const { stdout } = await execAsync("ps aux");
1853
1854
  const lines = stdout.split("\n");
1854
1855
  for (const line of lines) {
1855
- if (line.toLowerCase().includes("antigravity") && (line.includes("language-server") || line.includes("lsp") || line.includes("server"))) {
1856
- debug("process-detector", `Found potential Antigravity process: ${line}`);
1857
- const processInfo = parseUnixProcessLine(line);
1858
- if (processInfo) {
1859
- return processInfo;
1860
- }
1856
+ const lower = line.toLowerCase();
1857
+ if (!lower.includes("antigravity")) {
1858
+ continue;
1859
+ }
1860
+ if (lower.includes("server installation script")) {
1861
+ continue;
1862
+ }
1863
+ const hasServerSignal = line.includes("language-server") || line.includes("lsp") || line.includes("--csrf_token") || line.includes("--extension_server_port") || line.includes("exa.language_server_pb");
1864
+ if (!hasServerSignal) {
1865
+ continue;
1866
+ }
1867
+ debug("process-detector", `Found potential Antigravity process: ${line}`);
1868
+ const processInfo = parseUnixProcessLine(line);
1869
+ if (processInfo) {
1870
+ return processInfo;
1861
1871
  }
1862
1872
  }
1863
1873
  debug("process-detector", "No Antigravity process found");
@@ -1894,24 +1904,27 @@ async function detectOnWindows() {
1894
1904
  // 10MB buffer for long command lines
1895
1905
  );
1896
1906
  const lines = stdout.split("\n").filter((line) => line.trim() && !line.includes("Node,CommandLine,ProcessId"));
1907
+ const candidates = [];
1897
1908
  for (const line of lines) {
1898
1909
  const parts = line.split(",");
1899
1910
  if (parts.length >= 3) {
1900
1911
  const commandLine = parts.slice(1, -1).join(",");
1901
1912
  const pid = parseInt(parts[parts.length - 1].trim(), 10);
1902
1913
  if (!isNaN(pid) && commandLine.toLowerCase().includes("antigravity")) {
1903
- debug("process-detector", `Found Antigravity process on Windows: PID ${pid}`);
1904
- const csrfToken = extractArgument(commandLine, "--csrf_token");
1905
- const extensionServerPort = extractArgument(commandLine, "--extension_server_port");
1906
- return {
1914
+ candidates.push({
1907
1915
  pid,
1908
- csrfToken: csrfToken || void 0,
1909
- extensionServerPort: extensionServerPort ? parseInt(extensionServerPort, 10) : void 0,
1916
+ csrfToken: extractArgument(commandLine, "--csrf_token") || void 0,
1917
+ extensionServerPort: parsePortValue(extractArgument(commandLine, "--extension_server_port")),
1910
1918
  commandLine
1911
- };
1919
+ });
1912
1920
  }
1913
1921
  }
1914
1922
  }
1923
+ const selected = selectBestWindowsCandidate(candidates);
1924
+ if (selected) {
1925
+ debug("process-detector", `Selected Antigravity process on Windows: PID ${selected.pid}`);
1926
+ return selected;
1927
+ }
1915
1928
  return await detectOnWindowsPowerShell();
1916
1929
  } catch (err) {
1917
1930
  debug("process-detector", "Error detecting process on Windows with WMIC, trying PowerShell", err);
@@ -1928,28 +1941,73 @@ async function detectOnWindowsPowerShell() {
1928
1941
  }
1929
1942
  const processes = JSON.parse(stdout);
1930
1943
  const processList = Array.isArray(processes) ? processes : [processes];
1944
+ const candidates = [];
1931
1945
  for (const proc of processList) {
1932
1946
  if (proc.Id) {
1933
1947
  const { stdout: cmdLine } = await execAsync(
1934
1948
  `powershell -Command "(Get-CimInstance Win32_Process -Filter 'ProcessId = ${proc.Id}').CommandLine"`
1935
1949
  );
1936
1950
  const commandLine = cmdLine.trim();
1937
- const csrfToken = extractArgument(commandLine, "--csrf_token");
1938
- const extensionServerPort = extractArgument(commandLine, "--extension_server_port");
1939
- return {
1951
+ if (!commandLine.toLowerCase().includes("antigravity")) {
1952
+ continue;
1953
+ }
1954
+ candidates.push({
1940
1955
  pid: proc.Id,
1941
- csrfToken: csrfToken || void 0,
1942
- extensionServerPort: extensionServerPort ? parseInt(extensionServerPort, 10) : void 0,
1956
+ csrfToken: extractArgument(commandLine, "--csrf_token") || void 0,
1957
+ extensionServerPort: parsePortValue(extractArgument(commandLine, "--extension_server_port")),
1943
1958
  commandLine
1944
- };
1959
+ });
1945
1960
  }
1946
1961
  }
1962
+ const selected = selectBestWindowsCandidate(candidates);
1963
+ if (selected) {
1964
+ debug("process-detector", `Selected Antigravity process on Windows (PowerShell): PID ${selected.pid}`);
1965
+ return selected;
1966
+ }
1947
1967
  return null;
1948
1968
  } catch (err) {
1949
1969
  debug("process-detector", "Error detecting process on Windows with PowerShell", err);
1950
1970
  return null;
1951
1971
  }
1952
1972
  }
1973
+ function parsePortValue(rawPort) {
1974
+ if (!rawPort) {
1975
+ return void 0;
1976
+ }
1977
+ const parsed = parseInt(rawPort, 10);
1978
+ return isNaN(parsed) ? void 0 : parsed;
1979
+ }
1980
+ function scoreWindowsCandidate(candidate) {
1981
+ const lower = candidate.commandLine.toLowerCase();
1982
+ let score = 0;
1983
+ if (lower.includes("antigravity")) score += 1;
1984
+ if (lower.includes("lsp")) score += 5;
1985
+ if (candidate.extensionServerPort) score += 10;
1986
+ if (candidate.csrfToken) score += 20;
1987
+ if (lower.includes("language_server") || lower.includes("language-server") || lower.includes("exa.language_server_pb")) {
1988
+ score += 50;
1989
+ }
1990
+ return score;
1991
+ }
1992
+ function selectBestWindowsCandidate(candidates) {
1993
+ if (candidates.length === 0) {
1994
+ return null;
1995
+ }
1996
+ debug("process-detector", `Found ${candidates.length} Antigravity candidate process(es) on Windows`);
1997
+ let best = null;
1998
+ let bestScore = -1;
1999
+ for (const candidate of candidates) {
2000
+ const score = scoreWindowsCandidate(candidate);
2001
+ if (score > bestScore) {
2002
+ best = candidate;
2003
+ bestScore = score;
2004
+ }
2005
+ }
2006
+ if (best) {
2007
+ debug("process-detector", `Selected PID ${best.pid} with score ${bestScore}`);
2008
+ }
2009
+ return best;
2010
+ }
1953
2011
  function extractArgument(commandLine, argName) {
1954
2012
  const eqRegex = new RegExp(`${argName}=([^\\s"']+|"[^"]*"|'[^']*')`, "i");
1955
2013
  const eqMatch = commandLine.match(eqRegex);
@@ -2076,6 +2134,8 @@ async function discoverPortsOnWindows(pid) {
2076
2134
  // src/local/port-prober.ts
2077
2135
  import https from "https";
2078
2136
  import http from "http";
2137
+ var CONNECT_RPC_PATH = "/exa.language_server_pb.LanguageServerService/GetUnleashData";
2138
+ var VALID_CONNECT_STATUSES = /* @__PURE__ */ new Set([200, 401]);
2079
2139
  async function probeForConnectAPI(ports, csrfToken, timeout = 500) {
2080
2140
  debug("port-prober", `Probing ${ports.length} ports: ${ports.join(", ")}`);
2081
2141
  const probePromises = ports.map((port) => probePort(port, csrfToken, timeout));
@@ -2095,7 +2155,7 @@ async function probePort(port, csrfToken, timeout = 500) {
2095
2155
  if (httpsResult) {
2096
2156
  return httpsResult;
2097
2157
  }
2098
- const httpResult = await probeHttp(port, timeout);
2158
+ const httpResult = await probeHttp(port, timeout, csrfToken);
2099
2159
  if (httpResult) {
2100
2160
  return httpResult;
2101
2161
  }
@@ -2106,7 +2166,7 @@ function probeHttps(port, timeout, csrfToken) {
2106
2166
  const options = {
2107
2167
  hostname: "127.0.0.1",
2108
2168
  port,
2109
- path: "/exa.language_server_pb.LanguageServerService/GetUnleashData",
2169
+ path: CONNECT_RPC_PATH,
2110
2170
  method: "POST",
2111
2171
  timeout,
2112
2172
  rejectUnauthorized: false,
@@ -2118,7 +2178,7 @@ function probeHttps(port, timeout, csrfToken) {
2118
2178
  }
2119
2179
  };
2120
2180
  const req = https.request(options, (res) => {
2121
- if (res.statusCode === 200) {
2181
+ if (res.statusCode && VALID_CONNECT_STATUSES.has(res.statusCode)) {
2122
2182
  debug("port-prober", `HTTPS Connect RPC probe on port ${port}: status ${res.statusCode} - valid connect port`);
2123
2183
  resolve({
2124
2184
  baseUrl: `https://127.0.0.1:${port}`,
@@ -2144,23 +2204,43 @@ function probeHttps(port, timeout, csrfToken) {
2144
2204
  req.end();
2145
2205
  });
2146
2206
  }
2147
- function probeHttp(port, timeout) {
2207
+ function probeHttp(port, timeout, csrfToken) {
2148
2208
  return new Promise((resolve) => {
2149
2209
  const options = {
2150
- hostname: "localhost",
2210
+ hostname: "127.0.0.1",
2151
2211
  port,
2152
- path: "/",
2153
- method: "GET",
2154
- timeout
2212
+ path: CONNECT_RPC_PATH,
2213
+ method: "POST",
2214
+ timeout,
2215
+ headers: {
2216
+ "Content-Type": "application/json",
2217
+ "Connect-Protocol-Version": "1",
2218
+ ...csrfToken ? { "X-Codeium-Csrf-Token": csrfToken } : {}
2219
+ }
2155
2220
  };
2156
2221
  const req = http.request(options, (res) => {
2157
- debug("port-prober", `HTTP probe on port ${port}: status ${res.statusCode}`);
2158
- resolve({
2159
- baseUrl: `http://localhost:${port}`,
2160
- protocol: "http",
2161
- port
2222
+ let data = "";
2223
+ res.on("data", (chunk) => {
2224
+ data += chunk.toString();
2225
+ });
2226
+ res.on("end", () => {
2227
+ if (data.toLowerCase().includes("client sent an http request to an https server")) {
2228
+ debug("port-prober", `HTTP probe on port ${port}: protocol mismatch response, rejecting`);
2229
+ resolve(null);
2230
+ return;
2231
+ }
2232
+ if (res.statusCode && VALID_CONNECT_STATUSES.has(res.statusCode)) {
2233
+ debug("port-prober", `HTTP Connect RPC probe on port ${port}: status ${res.statusCode} - valid connect port`);
2234
+ resolve({
2235
+ baseUrl: `http://127.0.0.1:${port}`,
2236
+ protocol: "http",
2237
+ port
2238
+ });
2239
+ return;
2240
+ }
2241
+ debug("port-prober", `HTTP probe on port ${port}: status ${res.statusCode} - not connect port`);
2242
+ resolve(null);
2162
2243
  });
2163
- res.resume();
2164
2244
  });
2165
2245
  req.on("error", (err) => {
2166
2246
  debug("port-prober", `HTTP probe on port ${port} failed: ${err.message}`);
@@ -2171,6 +2251,7 @@ function probeHttp(port, timeout) {
2171
2251
  req.destroy();
2172
2252
  resolve(null);
2173
2253
  });
2254
+ req.write(JSON.stringify({ wrapper_data: {} }));
2174
2255
  req.end();
2175
2256
  });
2176
2257
  }
@@ -2468,7 +2549,11 @@ async function fetchQuotaLocal() {
2468
2549
  throw new AntigravityNotRunningError();
2469
2550
  }
2470
2551
  debug("service", `Found Antigravity process: PID ${processInfo.pid}`);
2471
- const ports = await discoverPorts(processInfo.pid);
2552
+ let ports = await discoverPorts(processInfo.pid);
2553
+ if (ports.length === 0 && processInfo.extensionServerPort) {
2554
+ debug("service", `Falling back to extension_server_port: ${processInfo.extensionServerPort}`);
2555
+ ports = [processInfo.extensionServerPort];
2556
+ }
2472
2557
  if (ports.length === 0) {
2473
2558
  throw new PortDetectionError();
2474
2559
  }
@@ -3868,7 +3953,7 @@ async function wakeupCommand(subcommand, args, options) {
3868
3953
  await uninstallSchedule();
3869
3954
  break;
3870
3955
  case "test":
3871
- await runTestTrigger();
3956
+ await runTestTrigger(options);
3872
3957
  break;
3873
3958
  case "history":
3874
3959
  await showHistory(options);
@@ -4103,7 +4188,7 @@ async function uninstallSchedule() {
4103
4188
  }
4104
4189
  console.log("");
4105
4190
  }
4106
- async function runTestTrigger() {
4191
+ async function runTestTrigger(options = {}) {
4107
4192
  console.log("\n\u{1F9EA} Test Trigger\n");
4108
4193
  const accountManager = getAccountManager();
4109
4194
  const accounts = accountManager.getAccountEmails();
@@ -4111,8 +4196,17 @@ async function runTestTrigger() {
4111
4196
  console.log("\u274C No accounts available. Please login first.");
4112
4197
  return;
4113
4198
  }
4114
- let accountEmail = accounts[0];
4115
- if (accounts.length > 1) {
4199
+ let accountEmail;
4200
+ if (options.email) {
4201
+ if (!accounts.includes(options.email)) {
4202
+ console.log(`\u274C Account "${options.email}" not found.`);
4203
+ console.log(` Available accounts: ${accounts.join(", ")}`);
4204
+ return;
4205
+ }
4206
+ accountEmail = options.email;
4207
+ } else if (accounts.length === 1) {
4208
+ accountEmail = accounts[0];
4209
+ } else {
4116
4210
  const { selectedAccount } = await inquirer2.prompt([{
4117
4211
  type: "list",
4118
4212
  name: "selectedAccount",
@@ -4121,19 +4215,20 @@ async function runTestTrigger() {
4121
4215
  }]);
4122
4216
  accountEmail = selectedAccount;
4123
4217
  }
4124
- const config = loadWakeupConfig();
4125
- const { modelId } = await inquirer2.prompt([{
4126
- type: "input",
4127
- name: "modelId",
4128
- message: "Model ID to test:",
4129
- default: config?.selectedModels[0] || "claude-sonnet-4-5"
4130
- }]);
4131
- const { prompt } = await inquirer2.prompt([{
4132
- type: "input",
4133
- name: "prompt",
4134
- message: "Test prompt:",
4135
- default: "hi"
4136
- }]);
4218
+ let modelId;
4219
+ if (options.model) {
4220
+ modelId = options.model;
4221
+ } else {
4222
+ const config = loadWakeupConfig();
4223
+ const { selectedModel } = await inquirer2.prompt([{
4224
+ type: "input",
4225
+ name: "selectedModel",
4226
+ message: "Model ID to test:",
4227
+ default: config?.selectedModels[0] || "claude-sonnet-4-5"
4228
+ }]);
4229
+ modelId = selectedModel;
4230
+ }
4231
+ const prompt = options.prompt || "hi";
4137
4232
  console.log("\n\u23F3 Triggering...");
4138
4233
  try {
4139
4234
  const result = await testTrigger(modelId, accountEmail, prompt);
@@ -4267,7 +4362,7 @@ wakeupCmd.command("config").description("Configure auto wake-up schedule").actio
4267
4362
  wakeupCmd.command("trigger").description("Execute one trigger cycle (called by cron)").option("--scheduled", "Mark as scheduled trigger").action((options) => wakeupCommand("trigger", [], options));
4268
4363
  wakeupCmd.command("install").description("Install wake-up schedule to system cron").action(() => wakeupCommand("install", [], {}));
4269
4364
  wakeupCmd.command("uninstall").description("Remove wake-up schedule from system cron").action(() => wakeupCommand("uninstall", [], {}));
4270
- wakeupCmd.command("test").description("Test trigger manually").action(() => wakeupCommand("test", [], {}));
4365
+ wakeupCmd.command("test").description("Test trigger manually").option("-e, --email <email>", "Account email to use for testing").option("-m, --model <model>", "Model ID to test").option("-p, --prompt <prompt>", "Test prompt to send", "hi").action((options) => wakeupCommand("test", [], options));
4271
4366
  wakeupCmd.command("history").description("View trigger history").option("--limit <n>", "Number of records to show", "10").option("--json", "Output as JSON").action((options) => wakeupCommand("history", [], options));
4272
4367
  wakeupCmd.command("status").description("Show wake-up status and configuration").action(() => wakeupCommand("status", [], {}));
4273
4368
  wakeupCmd.action(() => wakeupCommand("status", [], {}));