@hashimkarim/usagestat-linux-x64-gnu 2.0.0-alpha.1

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.
Files changed (225) hide show
  1. package/LICENSE +57744 -0
  2. package/native-manifest.json +1414 -0
  3. package/package.json +254 -0
  4. package/plugins/abacus-ai/icon.svg +18 -0
  5. package/plugins/abacus-ai/plugin.js +121 -0
  6. package/plugins/abacus-ai/plugin.json +17 -0
  7. package/plugins/alibaba/icon-color.svg +1 -0
  8. package/plugins/alibaba/icon.svg +1 -0
  9. package/plugins/alibaba/plugin.js +322 -0
  10. package/plugins/alibaba/plugin.json +20 -0
  11. package/plugins/alibaba-token-plan/icon-color.svg +1 -0
  12. package/plugins/alibaba-token-plan/icon.svg +1 -0
  13. package/plugins/alibaba-token-plan/plugin.js +544 -0
  14. package/plugins/alibaba-token-plan/plugin.json +19 -0
  15. package/plugins/amp/icon-color.svg +1 -0
  16. package/plugins/amp/icon-conflict.svg +6 -0
  17. package/plugins/amp/icon.svg +1 -0
  18. package/plugins/amp/plugin.js +175 -0
  19. package/plugins/amp/plugin.json +16 -0
  20. package/plugins/antigravity/icon-color.svg +1 -0
  21. package/plugins/antigravity/icon-conflict.svg +3 -0
  22. package/plugins/antigravity/icon.svg +1 -0
  23. package/plugins/antigravity/plugin.js +739 -0
  24. package/plugins/antigravity/plugin.json +31 -0
  25. package/plugins/antigravity-cli/icon.svg +3 -0
  26. package/plugins/antigravity-cli/plugin.js +570 -0
  27. package/plugins/antigravity-cli/plugin.json +16 -0
  28. package/plugins/antigravity-ide/icon.svg +3 -0
  29. package/plugins/antigravity-ide/plugin.js +257 -0
  30. package/plugins/antigravity-ide/plugin.json +29 -0
  31. package/plugins/augment/icon.svg +14 -0
  32. package/plugins/augment/plugin.js +59 -0
  33. package/plugins/augment/plugin.json +18 -0
  34. package/plugins/aws-bedrock/icon-color.svg +1 -0
  35. package/plugins/aws-bedrock/icon.svg +1 -0
  36. package/plugins/aws-bedrock/plugin.js +206 -0
  37. package/plugins/aws-bedrock/plugin.json +18 -0
  38. package/plugins/azure-openai/icon-color.svg +1 -0
  39. package/plugins/azure-openai/icon.svg +1 -0
  40. package/plugins/azure-openai/plugin.js +145 -0
  41. package/plugins/azure-openai/plugin.json +17 -0
  42. package/plugins/chutes/icon.svg +7 -0
  43. package/plugins/chutes/plugin.js +236 -0
  44. package/plugins/chutes/plugin.json +19 -0
  45. package/plugins/claude/icon-color.svg +1 -0
  46. package/plugins/claude/icon.svg +1 -0
  47. package/plugins/claude/plugin.js +1723 -0
  48. package/plugins/claude/plugin.json +30 -0
  49. package/plugins/codebuff/icon.svg +92 -0
  50. package/plugins/codebuff/plugin.js +113 -0
  51. package/plugins/codebuff/plugin.json +17 -0
  52. package/plugins/codex/icon-color.svg +5 -0
  53. package/plugins/codex/icon.svg +1 -0
  54. package/plugins/codex/plugin.js +1009 -0
  55. package/plugins/codex/plugin.json +82 -0
  56. package/plugins/command-code/icon.svg +3 -0
  57. package/plugins/command-code/plugin.js +184 -0
  58. package/plugins/command-code/plugin.json +20 -0
  59. package/plugins/copilot/icon-color.svg +1 -0
  60. package/plugins/copilot/icon.svg +1 -0
  61. package/plugins/copilot/plugin.js +684 -0
  62. package/plugins/copilot/plugin.json +21 -0
  63. package/plugins/crof/icon.svg +3 -0
  64. package/plugins/crof/plugin.js +53 -0
  65. package/plugins/crof/plugin.json +17 -0
  66. package/plugins/crofai/icon.svg +16 -0
  67. package/plugins/crofai/plugin.js +81 -0
  68. package/plugins/crofai/plugin.json +18 -0
  69. package/plugins/cursor/icon-conflict.svg +3 -0
  70. package/plugins/cursor/icon.svg +1 -0
  71. package/plugins/cursor/plugin.js +1379 -0
  72. package/plugins/cursor/plugin.json +23 -0
  73. package/plugins/cursor-nightly/icon.png +0 -0
  74. package/plugins/cursor-nightly/plugin.js +1379 -0
  75. package/plugins/cursor-nightly/plugin.json +23 -0
  76. package/plugins/deepgram/icon.svg +1 -0
  77. package/plugins/deepgram/plugin.js +20 -0
  78. package/plugins/deepgram/plugin.json +17 -0
  79. package/plugins/deepseek/icon-color.svg +1 -0
  80. package/plugins/deepseek/icon.svg +1 -0
  81. package/plugins/deepseek/plugin.js +71 -0
  82. package/plugins/deepseek/plugin.json +17 -0
  83. package/plugins/devin/icon.svg +5 -0
  84. package/plugins/devin/plugin.js +341 -0
  85. package/plugins/devin/plugin.json +16 -0
  86. package/plugins/doubao/icon-color.svg +1 -0
  87. package/plugins/doubao/icon.svg +1 -0
  88. package/plugins/doubao/plugin.js +92 -0
  89. package/plugins/doubao/plugin.json +17 -0
  90. package/plugins/droid/icon.svg +1 -0
  91. package/plugins/droid/plugin.json +20 -0
  92. package/plugins/elevenlabs/icon.svg +4 -0
  93. package/plugins/elevenlabs/plugin.js +48 -0
  94. package/plugins/elevenlabs/plugin.json +18 -0
  95. package/plugins/factory/icon-conflict.svg +1 -0
  96. package/plugins/factory/icon.svg +1 -0
  97. package/plugins/factory/plugin.js +487 -0
  98. package/plugins/factory/plugin.json +15 -0
  99. package/plugins/fireworks-ai/icon.svg +6 -0
  100. package/plugins/fireworks-ai/plugin.js +370 -0
  101. package/plugins/fireworks-ai/plugin.json +19 -0
  102. package/plugins/gemini/icon-color.svg +1 -0
  103. package/plugins/gemini/icon.svg +1 -0
  104. package/plugins/gemini/plugin.js +460 -0
  105. package/plugins/gemini/plugin.json +16 -0
  106. package/plugins/grok/icon.svg +1 -0
  107. package/plugins/grok/plugin.js +297 -0
  108. package/plugins/grok/plugin.json +19 -0
  109. package/plugins/groqcloud/icon.svg +1 -0
  110. package/plugins/groqcloud/plugin.js +117 -0
  111. package/plugins/groqcloud/plugin.json +19 -0
  112. package/plugins/jetbrains-ai-assistant/icon-color.svg +14 -0
  113. package/plugins/jetbrains-ai-assistant/icon-conflict.svg +3 -0
  114. package/plugins/jetbrains-ai-assistant/icon.svg +14 -0
  115. package/plugins/jetbrains-ai-assistant/plugin.js +313 -0
  116. package/plugins/jetbrains-ai-assistant/plugin.json +16 -0
  117. package/plugins/kilo/icon.svg +1 -0
  118. package/plugins/kilo/plugin.js +111 -0
  119. package/plugins/kilo/plugin.json +19 -0
  120. package/plugins/kimi/icon-color.svg +1 -0
  121. package/plugins/kimi/icon-conflict.svg +3 -0
  122. package/plugins/kimi/icon.svg +1 -0
  123. package/plugins/kimi/plugin.js +358 -0
  124. package/plugins/kimi/plugin.json +15 -0
  125. package/plugins/kimi-k2/icon-color.svg +1 -0
  126. package/plugins/kimi-k2/icon.svg +1 -0
  127. package/plugins/kimi-k2/plugin.js +58 -0
  128. package/plugins/kimi-k2/plugin.json +18 -0
  129. package/plugins/kiro/icon-color.svg +5 -0
  130. package/plugins/kiro/icon-conflict.svg +1 -0
  131. package/plugins/kiro/icon.svg +4 -0
  132. package/plugins/kiro/plugin.js +390 -0
  133. package/plugins/kiro/plugin.json +16 -0
  134. package/plugins/litellm/icon.svg +16 -0
  135. package/plugins/litellm/plugin.js +199 -0
  136. package/plugins/litellm/plugin.json +16 -0
  137. package/plugins/llm-proxy/icon.svg +1 -0
  138. package/plugins/llm-proxy/plugin.js +40 -0
  139. package/plugins/llm-proxy/plugin.json +17 -0
  140. package/plugins/manus/icon.svg +6 -0
  141. package/plugins/manus/plugin.js +50 -0
  142. package/plugins/manus/plugin.json +17 -0
  143. package/plugins/mimo/icon.svg +1 -0
  144. package/plugins/mimo/plugin.js +177 -0
  145. package/plugins/mimo/plugin.json +19 -0
  146. package/plugins/minimax/icon-color.svg +1 -0
  147. package/plugins/minimax/icon-conflict.svg +4 -0
  148. package/plugins/minimax/icon.svg +1 -0
  149. package/plugins/minimax/plugin.js +453 -0
  150. package/plugins/minimax/plugin.json +14 -0
  151. package/plugins/mistral/icon-color.svg +1 -0
  152. package/plugins/mistral/icon.svg +1 -0
  153. package/plugins/mistral/plugin.js +152 -0
  154. package/plugins/mistral/plugin.json +18 -0
  155. package/plugins/moonshot/icon.svg +1 -0
  156. package/plugins/moonshot/plugin.js +43 -0
  157. package/plugins/moonshot/plugin.json +16 -0
  158. package/plugins/nanogpt/icon-color.svg +17 -0
  159. package/plugins/nanogpt/icon.svg +10 -0
  160. package/plugins/nanogpt/plugin.js +80 -0
  161. package/plugins/nanogpt/plugin.json +17 -0
  162. package/plugins/neuralwatt/icon.svg +3 -0
  163. package/plugins/neuralwatt/plugin.js +152 -0
  164. package/plugins/neuralwatt/plugin.json +17 -0
  165. package/plugins/ollama/icon.svg +1 -0
  166. package/plugins/ollama/plugin.js +92 -0
  167. package/plugins/ollama/plugin.json +20 -0
  168. package/plugins/openai-api/icon.svg +1 -0
  169. package/plugins/openai-api/plugin.js +533 -0
  170. package/plugins/openai-api/plugin.json +26 -0
  171. package/plugins/opencode/icon.svg +1 -0
  172. package/plugins/opencode/plugin.js +342 -0
  173. package/plugins/opencode/plugin.json +19 -0
  174. package/plugins/opencode-go/icon-conflict.svg +1 -0
  175. package/plugins/opencode-go/icon.svg +1 -0
  176. package/plugins/opencode-go/plugin.js +617 -0
  177. package/plugins/opencode-go/plugin.json +50 -0
  178. package/plugins/openrouter/icon.svg +1 -0
  179. package/plugins/openrouter/plugin.js +156 -0
  180. package/plugins/openrouter/plugin.json +8 -0
  181. package/plugins/perplexity/icon-color.svg +1 -0
  182. package/plugins/perplexity/icon-conflict.svg +1 -0
  183. package/plugins/perplexity/icon.svg +1 -0
  184. package/plugins/perplexity/plugin.js +425 -0
  185. package/plugins/perplexity/plugin.json +19 -0
  186. package/plugins/poe/icon.svg +1 -0
  187. package/plugins/poe/plugin.js +190 -0
  188. package/plugins/poe/plugin.json +19 -0
  189. package/plugins/stepfun/icon-color.svg +1 -0
  190. package/plugins/stepfun/icon.svg +1 -0
  191. package/plugins/stepfun/plugin.js +155 -0
  192. package/plugins/stepfun/plugin.json +18 -0
  193. package/plugins/synthetic/icon-conflict.svg +12 -0
  194. package/plugins/synthetic/icon.svg +14 -0
  195. package/plugins/synthetic/plugin.js +331 -0
  196. package/plugins/synthetic/plugin.json +23 -0
  197. package/plugins/t3chat/icon-color.svg +28 -0
  198. package/plugins/t3chat/icon.svg +4 -0
  199. package/plugins/t3chat/plugin.js +243 -0
  200. package/plugins/t3chat/plugin.json +20 -0
  201. package/plugins/venice/icon-color.svg +1 -0
  202. package/plugins/venice/icon.svg +1 -0
  203. package/plugins/venice/plugin.js +69 -0
  204. package/plugins/venice/plugin.json +16 -0
  205. package/plugins/vertex-ai/icon-color.svg +1 -0
  206. package/plugins/vertex-ai/icon.svg +1 -0
  207. package/plugins/vertex-ai/plugin.js +172 -0
  208. package/plugins/vertex-ai/plugin.json +18 -0
  209. package/plugins/warp/icon-color.svg +10 -0
  210. package/plugins/warp/icon.svg +6 -0
  211. package/plugins/warp/plugin.js +108 -0
  212. package/plugins/warp/plugin.json +18 -0
  213. package/plugins/windsurf/icon-conflict.svg +3 -0
  214. package/plugins/windsurf/icon.svg +1 -0
  215. package/plugins/windsurf/plugin.js +208 -0
  216. package/plugins/windsurf/plugin.json +16 -0
  217. package/plugins/zai/icon-conflict.svg +5 -0
  218. package/plugins/zai/icon.svg +1 -0
  219. package/plugins/zai/plugin.js +188 -0
  220. package/plugins/zai/plugin.json +16 -0
  221. package/plugins/zed/icon.svg +4 -0
  222. package/plugins/zed/plugin.js +270 -0
  223. package/plugins/zed/plugin.json +19 -0
  224. package/usagestat +0 -0
  225. package/usagestatd +0 -0
@@ -0,0 +1,739 @@
1
+ (function () {
2
+ var LS_SERVICE = "exa.language_server_pb.LanguageServerService"
3
+ var AGY_KEYCHAIN_SERVICE = "gemini"
4
+ var AGY_KEYCHAIN_ACCOUNT = "antigravity"
5
+ var CLOUD_CODE_URLS = [
6
+ "https://daily-cloudcode-pa.googleapis.com",
7
+ "https://cloudcode-pa.googleapis.com",
8
+ ]
9
+ var LOAD_CODE_ASSIST_PATH = "/v1internal:loadCodeAssist"
10
+ var FETCH_MODELS_PATH = "/v1internal:fetchAvailableModels"
11
+ var RETRIEVE_QUOTA_PATH = "/v1internal:retrieveUserQuota"
12
+ var LOGIN_MESSAGE = "Start Antigravity or run `agy` and try again."
13
+ var GOOGLE_OAUTH_URL = "https://oauth2.googleapis.com/token"
14
+ var GOOGLE_CLIENT_ID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com"
15
+ var GOOGLE_CLIENT_SECRET = "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"
16
+ var OAUTH_TOKEN_KEY = "antigravityUnifiedStateSync.oauthToken"
17
+ var OAUTH_TOKEN_SENTINEL = "oauthTokenInfoSentinelKey"
18
+ var CC_MODEL_BLACKLIST = {
19
+ "MODEL_CHAT_20706": true,
20
+ "MODEL_CHAT_23310": true,
21
+ "MODEL_GOOGLE_GEMINI_2_5_FLASH": true,
22
+ "MODEL_GOOGLE_GEMINI_2_5_FLASH_THINKING": true,
23
+ "MODEL_GOOGLE_GEMINI_2_5_FLASH_LITE": true,
24
+ "MODEL_GOOGLE_GEMINI_2_5_PRO": true,
25
+ "MODEL_PLACEHOLDER_M19": true,
26
+ "MODEL_PLACEHOLDER_M9": true,
27
+ "MODEL_PLACEHOLDER_M12": true,
28
+ }
29
+ // --- Protobuf wire-format decoder ---
30
+
31
+ function readVarint(s, pos) {
32
+ var v = 0
33
+ var shift = 0
34
+ while (pos < s.length) {
35
+ var b = s.charCodeAt(pos++)
36
+ v += (b & 0x7f) * Math.pow(2, shift)
37
+ if ((b & 0x80) === 0) return { v: v, p: pos }
38
+ shift += 7
39
+ }
40
+ return null
41
+ }
42
+
43
+ function readFields(s) {
44
+ var fields = {}
45
+ var pos = 0
46
+ while (pos < s.length) {
47
+ var tag = readVarint(s, pos)
48
+ if (!tag) break
49
+ pos = tag.p
50
+ var fieldNum = Math.floor(tag.v / 8)
51
+ var wireType = tag.v % 8
52
+ if (wireType === 0) {
53
+ var val = readVarint(s, pos)
54
+ if (!val) break
55
+ fields[fieldNum] = { type: 0, value: val.v }
56
+ pos = val.p
57
+ } else if (wireType === 1) {
58
+ if (pos + 8 > s.length) break
59
+ pos += 8
60
+ } else if (wireType === 2) {
61
+ var len = readVarint(s, pos)
62
+ if (!len) break
63
+ pos = len.p
64
+ if (pos + len.v > s.length) break
65
+ fields[fieldNum] = { type: 2, data: s.substring(pos, pos + len.v) }
66
+ pos += len.v
67
+ } else if (wireType === 5) {
68
+ if (pos + 4 > s.length) break
69
+ pos += 4
70
+ } else {
71
+ break
72
+ }
73
+ }
74
+ return fields
75
+ }
76
+
77
+ // --- SQLite credential reading ---
78
+
79
+ function providerSettings(ctx) { return (ctx.provider && ctx.provider.settings) || {} }
80
+
81
+ function antigravityStateDbPaths(ctx) {
82
+ var opts = providerSettings(ctx)
83
+ if (opts.userDataDir) return [opts.userDataDir.replace(/[\\/]+$/, "") + "/User/globalStorage/state.vscdb"]
84
+ var variants = {"antigravity": "Antigravity", "antigravity-ide": "Antigravity IDE"}
85
+ if (opts.ideVariant && !variants[opts.ideVariant]) throw {code: "failed", message: "Unknown Antigravity ideVariant; use antigravity or antigravity-ide."}
86
+ return (opts.ideVariant ? [opts.ideVariant] : Object.keys(variants)).map(function(id) {
87
+ return ctx.host.fs.appSupportPath(variants[id] + "/User/globalStorage/state.vscdb")
88
+ }).filter(function(path) { return !!path && ctx.host.fs.exists(path) })
89
+ }
90
+
91
+ // Antigravity wraps OAuth state in a double-base64 envelope:
92
+ // b64(outer.f1 = wrapper{ f1=sentinel, f2=payload{ f1=b64(inner proto) } }).
93
+ // The inner base64 layer is the unusual part - it's a UTF-8 string field, not raw bytes.
94
+ function unwrapOAuthSentinel(ctx, base64Text) {
95
+ var trimmed = String(base64Text || "").replace(/^\s+|\s+$/g, "")
96
+ if (!trimmed) return null
97
+ var outer = ctx.base64.decode(trimmed)
98
+ var outerFields = readFields(outer)
99
+ if (!outerFields[1] || outerFields[1].type !== 2) return null
100
+ var wrapper = readFields(outerFields[1].data)
101
+ var sentinel = (wrapper[1] && wrapper[1].type === 2) ? wrapper[1].data : null
102
+ var payload = (wrapper[2] && wrapper[2].type === 2) ? wrapper[2].data : null
103
+ if (sentinel !== OAUTH_TOKEN_SENTINEL || !payload) return null
104
+ var payloadFields = readFields(payload)
105
+ if (!payloadFields[1] || payloadFields[1].type !== 2) return null
106
+ var innerText = payloadFields[1].data.replace(/^\s+|\s+$/g, "")
107
+ if (!innerText) return null
108
+ return ctx.base64.decode(innerText)
109
+ }
110
+
111
+ function loadOAuthTokensFromDb(ctx, dbPath) {
112
+ try {
113
+ var rows = ctx.host.sqlite.query(
114
+ dbPath,
115
+ "SELECT value FROM ItemTable WHERE key = '" + OAUTH_TOKEN_KEY + "' LIMIT 1"
116
+ )
117
+ var parsed = ctx.util.tryParseJson(rows)
118
+ if (!parsed || !parsed.length || !parsed[0].value) return null
119
+ var inner = unwrapOAuthSentinel(ctx, parsed[0].value)
120
+ if (!inner) return null
121
+ var fields = readFields(inner)
122
+ var accessToken = (fields[1] && fields[1].type === 2) ? fields[1].data : null
123
+ var refreshToken = (fields[3] && fields[3].type === 2) ? fields[3].data : null
124
+ var expirySeconds = null
125
+ if (fields[4] && fields[4].type === 2) {
126
+ var ts = readFields(fields[4].data)
127
+ if (ts[1] && ts[1].type === 0) expirySeconds = ts[1].value
128
+ }
129
+ if (!accessToken && !refreshToken) return null
130
+ return { accessToken: accessToken, refreshToken: refreshToken, expirySeconds: expirySeconds }
131
+ } catch (e) {
132
+ ctx.host.log.warn("failed to read unified oauth token from " + dbPath + ": " + String(e))
133
+ return null
134
+ }
135
+ }
136
+
137
+ function loadOAuthTokenCandidates(ctx) {
138
+ var candidates = []
139
+ var paths = antigravityStateDbPaths(ctx)
140
+ for (var i = 0; i < paths.length; i++) {
141
+ var tokens = loadOAuthTokensFromDb(ctx, paths[i])
142
+ if (tokens) {
143
+ tokens.profileKey = ctx.host.crypto.sha256Hex(paths[i] + "\n" + (tokens.refreshToken || tokens.accessToken))
144
+ candidates.push(tokens)
145
+ }
146
+ }
147
+ if (candidates.length > 1) throw {code: "failed", message: "Multiple Antigravity credential profiles found; set settings.ideVariant or userDataDir."}
148
+ return candidates
149
+ }
150
+
151
+ // --- Google OAuth token refresh ---
152
+
153
+ function refreshAccessToken(ctx, refreshTokenValue, profileKey) {
154
+ if (!refreshTokenValue) {
155
+ ctx.host.log.warn("refresh skipped: no refresh token")
156
+ return null
157
+ }
158
+ ctx.host.log.info("attempting Google OAuth token refresh")
159
+ try {
160
+ var resp = ctx.host.http.request({
161
+ method: "POST",
162
+ url: GOOGLE_OAUTH_URL,
163
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
164
+ bodyText:
165
+ "client_id=" + encodeURIComponent(GOOGLE_CLIENT_ID) +
166
+ "&client_secret=" + encodeURIComponent(GOOGLE_CLIENT_SECRET) +
167
+ "&refresh_token=" + encodeURIComponent(refreshTokenValue) +
168
+ "&grant_type=refresh_token",
169
+ timeoutMs: 15000,
170
+ })
171
+ if (resp.status < 200 || resp.status >= 300) {
172
+ ctx.host.log.warn("Google OAuth refresh returned status: " + resp.status)
173
+ return null
174
+ }
175
+ var body = ctx.util.tryParseJson(resp.bodyText)
176
+ if (!body || !body.access_token) {
177
+ ctx.host.log.warn("Google OAuth refresh response missing access_token")
178
+ return null
179
+ }
180
+ var expiresIn = (typeof body.expires_in === "number") ? body.expires_in : 3600
181
+ cacheToken(ctx, body.access_token, expiresIn, profileKey)
182
+ return body.access_token
183
+ } catch (e) {
184
+ ctx.host.log.warn("Google OAuth refresh failed: " + String(e))
185
+ return null
186
+ }
187
+ }
188
+
189
+ // --- Token cache ---
190
+
191
+ function loadCachedToken(ctx, profileKey) {
192
+ var path = ctx.app.pluginDataDir + "/auth.json"
193
+ try {
194
+ if (!ctx.host.fs.exists(path)) return null
195
+ var data = ctx.util.tryParseJson(ctx.host.fs.readText(path))
196
+ if (!data || !profileKey || data.profileKey !== profileKey || !data.accessToken || !data.expiresAtMs) return null
197
+ if (data.expiresAtMs <= Date.now()) return null
198
+ return data.accessToken
199
+ } catch (e) {
200
+ ctx.host.log.warn("failed to read cached token: " + String(e))
201
+ return null
202
+ }
203
+ }
204
+
205
+ function cacheToken(ctx, accessToken, expiresInSeconds, profileKey) {
206
+ var path = ctx.app.pluginDataDir + "/auth.json"
207
+ try {
208
+ ctx.host.fs.writeText(path, JSON.stringify({
209
+ accessToken: accessToken,
210
+ profileKey: profileKey,
211
+ expiresAtMs: Date.now() + (expiresInSeconds || 3600) * 1000,
212
+ }))
213
+ } catch (e) {
214
+ ctx.host.log.warn("failed to cache refreshed token: " + String(e))
215
+ }
216
+ }
217
+
218
+ // --- agy keychain token ---
219
+
220
+ function trimString(value) {
221
+ return typeof value === "string" ? value.trim() : ""
222
+ }
223
+
224
+ function decodeBase64(ctx, text) {
225
+ try {
226
+ return ctx.base64.decode(text)
227
+ } catch (e) {
228
+ return null
229
+ }
230
+ }
231
+
232
+ function unwrapAgyKeychainText(ctx, raw) {
233
+ var text = trimString(raw)
234
+ if (!text) return null
235
+ if (text.indexOf("go-keyring-base64:") === 0) {
236
+ text = trimString(decodeBase64(ctx, text.slice("go-keyring-base64:".length)))
237
+ }
238
+ return text || null
239
+ }
240
+
241
+ function extractTokenFromObject(obj) {
242
+ if (!obj || typeof obj !== "object") return null
243
+
244
+ var directKeys = [
245
+ "access_token",
246
+ "accessToken",
247
+ "token",
248
+ "id_token",
249
+ "idToken",
250
+ "bearerToken",
251
+ "auth_token",
252
+ "authToken",
253
+ ]
254
+ for (var i = 0; i < directKeys.length; i++) {
255
+ var value = obj[directKeys[i]]
256
+ if (typeof value === "string" && value.trim()) return value.trim()
257
+ }
258
+
259
+ var nestedKeys = ["token", "tokens", "oauth", "oauth2", "credentials", "auth"]
260
+ for (var j = 0; j < nestedKeys.length; j++) {
261
+ var nested = extractTokenFromObject(obj[nestedKeys[j]])
262
+ if (nested) return nested
263
+ }
264
+
265
+ return null
266
+ }
267
+
268
+ function extractAgyAccessToken(ctx, raw) {
269
+ var text = unwrapAgyKeychainText(ctx, raw)
270
+ if (!text) return null
271
+
272
+ var parsed = ctx.util.tryParseJson(text)
273
+ if (typeof parsed === "string" && parsed.trim()) return parsed.trim()
274
+ if (parsed) return extractTokenFromObject(parsed)
275
+
276
+ if (text.indexOf("Bearer ") === 0) return text.slice("Bearer ".length).trim() || null
277
+ return text
278
+ }
279
+
280
+ function loadAgyKeychainToken(ctx) {
281
+ if (!ctx.host.keychain || typeof ctx.host.keychain.readGenericPassword !== "function") {
282
+ return null
283
+ }
284
+ try {
285
+ var raw = ctx.host.keychain.readGenericPassword(AGY_KEYCHAIN_SERVICE, AGY_KEYCHAIN_ACCOUNT)
286
+ return extractAgyAccessToken(ctx, raw)
287
+ } catch (e) {
288
+ ctx.host.log.info("agy keychain read failed: " + String(e))
289
+ return null
290
+ }
291
+ }
292
+
293
+ // --- LS discovery ---
294
+
295
+ function discoverNative(ctx, options) {
296
+ if (typeof ctx.host.ls.discoverStatus !== "function") return ctx.host.ls.discover(options)
297
+ var report = ctx.host.ls.discoverStatus(options)
298
+ if (report.status === "ready") return report.result
299
+ if (report.status === "missing") return null
300
+ if (report.status === "ambiguous") throw {code: "failed", message: "Multiple Antigravity processes found; select settings.ideProcessId or use the separate CLI provider."}
301
+ throw {code: report.status === "unsupported" ? "unsupported" : report.reasonCode === "ide-discovery-timed-out" ? "timed-out" : "failed", message: "Antigravity process discovery is unavailable; run the backend and app as the same signed-in user."}
302
+ }
303
+
304
+ function discoverLs(ctx) {
305
+ var options = {processName: "language_server", markers: ["antigravity", "antigravity-ide"], csrfFlag: "--csrf_token", portFlag: "--extension_server_port"}
306
+ var pid = providerSettings(ctx).ideProcessId
307
+ if (pid != null) {
308
+ if (!Number.isInteger(Number(pid)) || Number(pid) <= 0 || Number(pid) > 4294967295) throw {code: "failed", message: "Invalid Antigravity ideProcessId."}
309
+ options.pid = Number(pid)
310
+ }
311
+ return discoverNative(ctx, options)
312
+ }
313
+
314
+ function discoverAgyLs(ctx) {
315
+ return discoverNative(ctx, {processName: "agy", markers: [], csrfFlag: "", portFlag: null})
316
+ }
317
+
318
+ function probePort(ctx, scheme, port, csrf) {
319
+ ctx.host.http.request({
320
+ method: "POST",
321
+ url: scheme + "://127.0.0.1:" + port + "/" + LS_SERVICE + "/GetUnleashData",
322
+ headers: {
323
+ "Content-Type": "application/json",
324
+ "Connect-Protocol-Version": "1",
325
+ "x-codeium-csrf-token": csrf,
326
+ },
327
+ bodyText: JSON.stringify({
328
+ context: {
329
+ properties: {
330
+ devMode: "false",
331
+ extensionVersion: "unknown",
332
+ ide: "antigravity",
333
+ ideVersion: "unknown",
334
+ os: "macos",
335
+ },
336
+ },
337
+ }),
338
+ timeoutMs: 5000,
339
+ dangerouslyIgnoreTls: scheme === "https",
340
+ })
341
+ // Any HTTP response means this port is alive (even 400 validation errors).
342
+ return true
343
+ }
344
+
345
+ function findWorkingPort(ctx, discovery) {
346
+ var ports = discovery.ports || []
347
+ for (var i = 0; i < ports.length; i++) {
348
+ var port = ports[i]
349
+ // Try HTTPS first (LS may use self-signed cert), then HTTP
350
+ try { if (probePort(ctx, "https", port, discovery.csrf)) return { port: port, scheme: "https" } } catch (e) { /* ignore */ }
351
+ try { if (probePort(ctx, "http", port, discovery.csrf)) return { port: port, scheme: "http" } } catch (e) { /* ignore */ }
352
+ ctx.host.log.info("port " + port + " probe failed on both schemes")
353
+ }
354
+ if (discovery.extensionPort) return { port: discovery.extensionPort, scheme: "http" }
355
+ return null
356
+ }
357
+
358
+ function callLs(ctx, port, scheme, csrf, method, body) {
359
+ var resp = ctx.host.http.request({
360
+ method: "POST",
361
+ url: scheme + "://127.0.0.1:" + port + "/" + LS_SERVICE + "/" + method,
362
+ headers: {
363
+ "Content-Type": "application/json",
364
+ "Connect-Protocol-Version": "1",
365
+ "x-codeium-csrf-token": csrf,
366
+ },
367
+ bodyText: JSON.stringify(body || {}),
368
+ timeoutMs: 10000,
369
+ dangerouslyIgnoreTls: scheme === "https",
370
+ })
371
+ if (resp.status < 200 || resp.status >= 300) {
372
+ ctx.host.log.warn("callLs " + method + " returned " + resp.status)
373
+ return null
374
+ }
375
+ return ctx.util.tryParseJson(resp.bodyText)
376
+ }
377
+
378
+ // --- Line builders ---
379
+
380
+ function normalizeLabel(label) {
381
+ // "Gemini 3 Pro (High)" -> "Gemini 3 Pro"
382
+ return label.replace(/\s*\([^)]*\)\s*$/, "").trim()
383
+ }
384
+
385
+ function poolLabel(normalizedLabel) {
386
+ var lower = normalizedLabel.toLowerCase()
387
+ if (lower.indexOf("gemini") !== -1 && lower.indexOf("pro") !== -1) return "Gemini Pro"
388
+ if (lower.indexOf("gemini") !== -1 && lower.indexOf("flash") !== -1) return "Gemini Flash"
389
+ // All non-Gemini models (Claude, GPT-OSS, etc.) share a single quota pool
390
+ return "Claude"
391
+ }
392
+
393
+ function modelSortKey(label) {
394
+ var lower = label.toLowerCase()
395
+ // Gemini Pro variants first, then other Gemini, then Claude Opus, then other Claude, then rest
396
+ if (lower.indexOf("gemini") !== -1 && lower.indexOf("pro") !== -1) return "0a_" + label
397
+ if (lower.indexOf("gemini") !== -1) return "0b_" + label
398
+ if (lower.indexOf("claude") !== -1 && lower.indexOf("opus") !== -1) return "1a_" + label
399
+ if (lower.indexOf("claude") !== -1) return "1b_" + label
400
+ return "2_" + label
401
+ }
402
+
403
+ var QUOTA_PERIOD_MS = 5 * 60 * 60 * 1000 // 5 hours
404
+
405
+ function modelLine(ctx, label, remainingFraction, resetTime) {
406
+ var clamped = Math.max(0, Math.min(1, remainingFraction))
407
+ var used = Math.round((1 - clamped) * 100)
408
+ return ctx.line.progress({
409
+ label: label,
410
+ used: used,
411
+ limit: 100,
412
+ format: { kind: "percent" },
413
+ resetsAt: resetTime || undefined,
414
+ periodDurationMs: QUOTA_PERIOD_MS,
415
+ })
416
+ }
417
+
418
+ function buildModelLines(ctx, configs) {
419
+ var deduped = {}
420
+ for (var i = 0; i < configs.length; i++) {
421
+ var c = configs[i]
422
+ var label = (typeof c.label === "string") ? c.label.trim() : ""
423
+ if (!label) continue
424
+ var qi = c.quotaInfo
425
+ var frac = (qi && typeof qi.remainingFraction === "number") ? qi.remainingFraction : 0
426
+ var rtime = (qi && qi.resetTime) || undefined
427
+ var pool = poolLabel(normalizeLabel(label))
428
+ if (!deduped[pool] || frac < deduped[pool].remainingFraction) {
429
+ deduped[pool] = {
430
+ label: pool,
431
+ remainingFraction: frac,
432
+ resetTime: rtime,
433
+ }
434
+ }
435
+ }
436
+
437
+ var models = []
438
+ var keys = Object.keys(deduped)
439
+ for (var i = 0; i < keys.length; i++) {
440
+ var m = deduped[keys[i]]
441
+ m.sortKey = modelSortKey(m.label)
442
+ models.push(m)
443
+ }
444
+
445
+ models.sort(function (a, b) {
446
+ return a.sortKey < b.sortKey ? -1 : a.sortKey > b.sortKey ? 1 : 0
447
+ })
448
+
449
+ var lines = []
450
+ for (var i = 0; i < models.length; i++) {
451
+ lines.push(modelLine(ctx, models[i].label, models[i].remainingFraction, models[i].resetTime))
452
+ }
453
+ return lines
454
+ }
455
+
456
+ // --- Cloud Code API ---
457
+
458
+ function requestCloudCodeJson(ctx, path, token, userAgent, body) {
459
+ for (var i = 0; i < CLOUD_CODE_URLS.length; i++) {
460
+ try {
461
+ var resp = ctx.host.http.request({
462
+ method: "POST",
463
+ url: CLOUD_CODE_URLS[i] + path,
464
+ headers: {
465
+ Accept: "application/json",
466
+ "Content-Type": "application/json",
467
+ Authorization: "Bearer " + token,
468
+ "User-Agent": userAgent || "antigravity",
469
+ },
470
+ bodyText: JSON.stringify(body || {}),
471
+ timeoutMs: 15000,
472
+ })
473
+ if (!resp || typeof resp.status !== "number" || !Number.isFinite(resp.status)) {
474
+ ctx.host.log.warn("Cloud Code returned invalid response shape (" + CLOUD_CODE_URLS[i] + ")")
475
+ continue
476
+ }
477
+ if (ctx.util.isAuthStatus(resp.status)) return { _authFailed: true }
478
+ if (resp.status >= 200 && resp.status < 300) {
479
+ var json = ctx.util.tryParseJson(resp.bodyText)
480
+ if (!json || typeof json !== "object") {
481
+ ctx.host.log.warn("Cloud Code returned invalid JSON (" + CLOUD_CODE_URLS[i] + ")")
482
+ continue
483
+ }
484
+ return json
485
+ }
486
+ } catch (e) {
487
+ ctx.host.log.warn("Cloud Code request failed (" + CLOUD_CODE_URLS[i] + "): " + String(e))
488
+ }
489
+ }
490
+ return null
491
+ }
492
+
493
+ function probeCloudCode(ctx, token, userAgent) {
494
+ return requestCloudCodeJson(ctx, FETCH_MODELS_PATH, token, userAgent, {})
495
+ }
496
+
497
+ function parseCloudCodeModels(data) {
498
+ var modelsObj = data && data.models
499
+ if (!modelsObj || typeof modelsObj !== "object") return []
500
+ var keys = Object.keys(modelsObj)
501
+ var configs = []
502
+ for (var i = 0; i < keys.length; i++) {
503
+ var m = modelsObj[keys[i]]
504
+ if (!m || typeof m !== "object") continue
505
+ if (m.isInternal) continue
506
+ var modelId = m.model || keys[i]
507
+ if (CC_MODEL_BLACKLIST[modelId]) continue
508
+ var displayName =
509
+ (typeof m.displayName === "string" && m.displayName.trim()) ||
510
+ (typeof m.label === "string" && m.label.trim()) ||
511
+ ""
512
+ if (!displayName) continue
513
+ var qi = m.quotaInfo
514
+ var frac = (qi && typeof qi.remainingFraction === "number") ? qi.remainingFraction : 0
515
+ var rtime = (qi && qi.resetTime) || undefined
516
+ configs.push({
517
+ label: displayName,
518
+ quotaInfo: { remainingFraction: frac, resetTime: rtime },
519
+ })
520
+ }
521
+ return configs
522
+ }
523
+
524
+ function readAgyPlan(loadData) {
525
+ var paidTier = loadData && loadData.paidTier
526
+ if (paidTier && typeof paidTier.name === "string" && paidTier.name.trim()) {
527
+ return paidTier.name.trim()
528
+ }
529
+ var currentTier = loadData && loadData.currentTier
530
+ if (currentTier && typeof currentTier.name === "string" && currentTier.name.trim()) {
531
+ return currentTier.name.trim()
532
+ }
533
+ return null
534
+ }
535
+
536
+ function parseAgyQuotaBuckets(data) {
537
+ var buckets = data && data.buckets
538
+ if (!Array.isArray(buckets)) return []
539
+ var configs = []
540
+ for (var i = 0; i < buckets.length; i++) {
541
+ var bucket = buckets[i]
542
+ if (!bucket || typeof bucket !== "object") continue
543
+ var modelId = (typeof bucket.modelId === "string" && bucket.modelId.trim()) || ""
544
+ if (!modelId) continue
545
+ var frac = (typeof bucket.remainingFraction === "number") ? bucket.remainingFraction : 0
546
+ configs.push({
547
+ label: modelId,
548
+ quotaInfo: { remainingFraction: frac, resetTime: bucket.resetTime || undefined },
549
+ })
550
+ }
551
+ return configs
552
+ }
553
+
554
+ function probeAgyCloudCode(ctx, token) {
555
+ var loadData = requestCloudCodeJson(ctx, LOAD_CODE_ASSIST_PATH, token, "agy", {})
556
+ if (!loadData || loadData._authFailed) return loadData
557
+
558
+ var project =
559
+ typeof loadData.cloudaicompanionProject === "string" && loadData.cloudaicompanionProject.trim()
560
+ ? loadData.cloudaicompanionProject.trim()
561
+ : null
562
+ var quotaData = null
563
+ if (project) {
564
+ quotaData = requestCloudCodeJson(ctx, RETRIEVE_QUOTA_PATH, token, "agy", { project: project })
565
+ }
566
+ if (!quotaData || quotaData._authFailed) {
567
+ quotaData = requestCloudCodeJson(ctx, RETRIEVE_QUOTA_PATH, token, "agy", {})
568
+ }
569
+ if (!quotaData || quotaData._authFailed) return quotaData
570
+
571
+ var lines = buildModelLines(ctx, parseAgyQuotaBuckets(quotaData))
572
+ if (lines.length === 0) return null
573
+ return { plan: readAgyPlan(loadData), lines: lines }
574
+ }
575
+
576
+ // --- LS probe ---
577
+
578
+ function probeDiscovery(ctx, discovery) {
579
+ if (!discovery) return null
580
+
581
+ var found = findWorkingPort(ctx, discovery)
582
+ if (!found) return null
583
+
584
+ ctx.host.log.info("using LS at " + found.scheme + "://127.0.0.1:" + found.port)
585
+
586
+ var metadata = {
587
+ ideName: "antigravity",
588
+ extensionName: "antigravity",
589
+ ideVersion: "unknown",
590
+ locale: "en",
591
+ }
592
+
593
+ // Try GetUserStatus first, fall back to GetCommandModelConfigs
594
+ var data = null
595
+ try {
596
+ data = callLs(ctx, found.port, found.scheme, discovery.csrf, "GetUserStatus", { metadata: metadata })
597
+ } catch (e) {
598
+ ctx.host.log.warn("GetUserStatus threw: " + String(e))
599
+ }
600
+ var hasUserStatus = data && data.userStatus
601
+
602
+ if (!hasUserStatus) {
603
+ ctx.host.log.warn("GetUserStatus failed, trying GetCommandModelConfigs")
604
+ data = callLs(ctx, found.port, found.scheme, discovery.csrf, "GetCommandModelConfigs", { metadata: metadata })
605
+ }
606
+
607
+ // Parse model configs
608
+ var configs
609
+ if (hasUserStatus) {
610
+ configs = (data.userStatus.cascadeModelConfigData || {}).clientModelConfigs || []
611
+ } else if (data && data.clientModelConfigs) {
612
+ configs = data.clientModelConfigs
613
+ } else {
614
+ return null
615
+ }
616
+
617
+ var filtered = []
618
+ for (var j = 0; j < configs.length; j++) {
619
+ var mid = configs[j].modelOrAlias && configs[j].modelOrAlias.model
620
+ if (mid && CC_MODEL_BLACKLIST[mid]) continue
621
+ filtered.push(configs[j])
622
+ }
623
+
624
+ var lines = buildModelLines(ctx, filtered)
625
+ if (lines.length === 0) return null
626
+
627
+ var plan = null
628
+ if (hasUserStatus) {
629
+ // Prefer userTier.name (Google's own subscription system) over the legacy
630
+ // planInfo.planName field inherited from Windsurf/Codeium, which always
631
+ // returns "Pro" for all paid tiers including Google AI Ultra.
632
+ var ut = data.userStatus.userTier
633
+ var userTierName =
634
+ ut && typeof ut.name === "string" && ut.name.trim() ? ut.name.trim() : null
635
+ if (userTierName) {
636
+ plan = userTierName
637
+ } else {
638
+ var ps = data.userStatus.planStatus || {}
639
+ var pi = ps.planInfo || {}
640
+ plan =
641
+ typeof pi.planName === "string" && pi.planName.trim() ? pi.planName.trim() : null
642
+ }
643
+ }
644
+
645
+ return { plan: plan, lines: lines }
646
+ }
647
+
648
+ function probeLs(ctx) {
649
+ return probeDiscovery(ctx, discoverLs(ctx))
650
+ }
651
+
652
+ function probeAgyLs(ctx) {
653
+ return probeDiscovery(ctx, discoverAgyLs(ctx))
654
+ }
655
+
656
+ // --- Probe ---
657
+
658
+ function probe(ctx) {
659
+ var opts = providerSettings(ctx)
660
+ var explicitDb = !!(opts.userDataDir || opts.ideVariant)
661
+ if (explicitDb && opts.ideProcessId != null) throw {code: "failed", message: "Select an Antigravity database profile or a process ID, not both."}
662
+ if (!explicitDb) {
663
+ var lsResult = probeLs(ctx)
664
+ if (lsResult) return lsResult
665
+ if (opts.ideProcessId != null) throw LOGIN_MESSAGE
666
+ }
667
+ var dbTokenCandidates = loadOAuthTokenCandidates(ctx)
668
+ if (explicitDb && !dbTokenCandidates.length) throw LOGIN_MESSAGE
669
+ if (!dbTokenCandidates.length) {
670
+ var agyLsResult = probeAgyLs(ctx)
671
+ if (agyLsResult) return agyLsResult
672
+ }
673
+
674
+ var tokens = []
675
+ var nowSec = Math.floor(Date.now() / 1000)
676
+ for (var i = 0; i < dbTokenCandidates.length; i++) {
677
+ var dbTokens = dbTokenCandidates[i]
678
+ if (dbTokens.accessToken && (!dbTokens.expirySeconds || dbTokens.expirySeconds > nowSec)) {
679
+ if (tokens.indexOf(dbTokens.accessToken) === -1) tokens.push(dbTokens.accessToken)
680
+ }
681
+ }
682
+
683
+ var profileKey = dbTokenCandidates.length ? dbTokenCandidates[0].profileKey : null
684
+ var cached = loadCachedToken(ctx, profileKey)
685
+ if (cached && tokens.indexOf(cached) === -1) tokens.push(cached)
686
+
687
+ var ccData = null
688
+ var sawAuthFailure = false
689
+ for (var i = 0; i < tokens.length; i++) {
690
+ var nextData = probeCloudCode(ctx, tokens[i])
691
+ if (nextData && !nextData._authFailed) {
692
+ ccData = nextData
693
+ break
694
+ }
695
+ if (nextData && nextData._authFailed) sawAuthFailure = true
696
+ }
697
+
698
+ // Only refresh on evidence of an auth failure, or when there were no tokens to try.
699
+ // probeCloudCode returns null for transient failures (5xx/timeouts); without this
700
+ // guard a Cloud Code incident would trigger a Google OAuth refresh every probe cycle
701
+ // instead of ~once per token lifetime - risking refresh-token throttling or rotation.
702
+ if (!ccData && (sawAuthFailure || tokens.length === 0)) {
703
+ var refreshTokens = []
704
+ for (var j = 0; j < dbTokenCandidates.length; j++) {
705
+ var refreshToken = dbTokenCandidates[j].refreshToken
706
+ if (refreshToken && refreshTokens.indexOf(refreshToken) === -1) refreshTokens.push(refreshToken)
707
+ }
708
+ for (var k = 0; k < refreshTokens.length; k++) {
709
+ var refreshed = refreshAccessToken(ctx, refreshTokens[k], profileKey)
710
+ if (!refreshed) continue
711
+ var refreshedData = probeCloudCode(ctx, refreshed)
712
+ if (refreshedData && !refreshedData._authFailed) {
713
+ ccData = refreshedData
714
+ break
715
+ }
716
+ if (refreshedData && refreshedData._authFailed) ccData = refreshedData
717
+ }
718
+ }
719
+
720
+ if (!dbTokenCandidates.length && (!ccData || ccData._authFailed)) {
721
+ var agyToken = loadAgyKeychainToken(ctx)
722
+ if (agyToken) {
723
+ var agyResult = probeAgyCloudCode(ctx, agyToken)
724
+ if (agyResult && !agyResult._authFailed) return agyResult
725
+ if (agyResult && agyResult._authFailed) ccData = agyResult
726
+ }
727
+ }
728
+
729
+ if (ccData && !ccData._authFailed) {
730
+ var configs = parseCloudCodeModels(ccData)
731
+ var lines = buildModelLines(ctx, configs)
732
+ if (lines.length > 0) return { plan: null, lines: lines }
733
+ }
734
+
735
+ throw LOGIN_MESSAGE
736
+ }
737
+
738
+ globalThis.__openusage_plugin = { id: "antigravity", probe: probe }
739
+ })()