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 +18 -1
- package/dist/index.js +152 -57
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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
|
|
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 (
|
|
1687
|
+
if (responseData.usageMetadata) {
|
|
1687
1688
|
tokensUsed = {
|
|
1688
|
-
prompt:
|
|
1689
|
-
completion:
|
|
1690
|
-
total:
|
|
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
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
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
|
-
|
|
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:
|
|
1909
|
-
extensionServerPort:
|
|
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
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1951
|
+
if (!commandLine.toLowerCase().includes("antigravity")) {
|
|
1952
|
+
continue;
|
|
1953
|
+
}
|
|
1954
|
+
candidates.push({
|
|
1940
1955
|
pid: proc.Id,
|
|
1941
|
-
csrfToken:
|
|
1942
|
-
extensionServerPort:
|
|
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:
|
|
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
|
|
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: "
|
|
2210
|
+
hostname: "127.0.0.1",
|
|
2151
2211
|
port,
|
|
2152
|
-
path:
|
|
2153
|
-
method: "
|
|
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
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
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
|
-
|
|
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
|
|
4115
|
-
if (
|
|
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
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
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", [], {}));
|