@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.
- package/LICENSE +57744 -0
- package/native-manifest.json +1414 -0
- package/package.json +254 -0
- package/plugins/abacus-ai/icon.svg +18 -0
- package/plugins/abacus-ai/plugin.js +121 -0
- package/plugins/abacus-ai/plugin.json +17 -0
- package/plugins/alibaba/icon-color.svg +1 -0
- package/plugins/alibaba/icon.svg +1 -0
- package/plugins/alibaba/plugin.js +322 -0
- package/plugins/alibaba/plugin.json +20 -0
- package/plugins/alibaba-token-plan/icon-color.svg +1 -0
- package/plugins/alibaba-token-plan/icon.svg +1 -0
- package/plugins/alibaba-token-plan/plugin.js +544 -0
- package/plugins/alibaba-token-plan/plugin.json +19 -0
- package/plugins/amp/icon-color.svg +1 -0
- package/plugins/amp/icon-conflict.svg +6 -0
- package/plugins/amp/icon.svg +1 -0
- package/plugins/amp/plugin.js +175 -0
- package/plugins/amp/plugin.json +16 -0
- package/plugins/antigravity/icon-color.svg +1 -0
- package/plugins/antigravity/icon-conflict.svg +3 -0
- package/plugins/antigravity/icon.svg +1 -0
- package/plugins/antigravity/plugin.js +739 -0
- package/plugins/antigravity/plugin.json +31 -0
- package/plugins/antigravity-cli/icon.svg +3 -0
- package/plugins/antigravity-cli/plugin.js +570 -0
- package/plugins/antigravity-cli/plugin.json +16 -0
- package/plugins/antigravity-ide/icon.svg +3 -0
- package/plugins/antigravity-ide/plugin.js +257 -0
- package/plugins/antigravity-ide/plugin.json +29 -0
- package/plugins/augment/icon.svg +14 -0
- package/plugins/augment/plugin.js +59 -0
- package/plugins/augment/plugin.json +18 -0
- package/plugins/aws-bedrock/icon-color.svg +1 -0
- package/plugins/aws-bedrock/icon.svg +1 -0
- package/plugins/aws-bedrock/plugin.js +206 -0
- package/plugins/aws-bedrock/plugin.json +18 -0
- package/plugins/azure-openai/icon-color.svg +1 -0
- package/plugins/azure-openai/icon.svg +1 -0
- package/plugins/azure-openai/plugin.js +145 -0
- package/plugins/azure-openai/plugin.json +17 -0
- package/plugins/chutes/icon.svg +7 -0
- package/plugins/chutes/plugin.js +236 -0
- package/plugins/chutes/plugin.json +19 -0
- package/plugins/claude/icon-color.svg +1 -0
- package/plugins/claude/icon.svg +1 -0
- package/plugins/claude/plugin.js +1723 -0
- package/plugins/claude/plugin.json +30 -0
- package/plugins/codebuff/icon.svg +92 -0
- package/plugins/codebuff/plugin.js +113 -0
- package/plugins/codebuff/plugin.json +17 -0
- package/plugins/codex/icon-color.svg +5 -0
- package/plugins/codex/icon.svg +1 -0
- package/plugins/codex/plugin.js +1009 -0
- package/plugins/codex/plugin.json +82 -0
- package/plugins/command-code/icon.svg +3 -0
- package/plugins/command-code/plugin.js +184 -0
- package/plugins/command-code/plugin.json +20 -0
- package/plugins/copilot/icon-color.svg +1 -0
- package/plugins/copilot/icon.svg +1 -0
- package/plugins/copilot/plugin.js +684 -0
- package/plugins/copilot/plugin.json +21 -0
- package/plugins/crof/icon.svg +3 -0
- package/plugins/crof/plugin.js +53 -0
- package/plugins/crof/plugin.json +17 -0
- package/plugins/crofai/icon.svg +16 -0
- package/plugins/crofai/plugin.js +81 -0
- package/plugins/crofai/plugin.json +18 -0
- package/plugins/cursor/icon-conflict.svg +3 -0
- package/plugins/cursor/icon.svg +1 -0
- package/plugins/cursor/plugin.js +1379 -0
- package/plugins/cursor/plugin.json +23 -0
- package/plugins/cursor-nightly/icon.png +0 -0
- package/plugins/cursor-nightly/plugin.js +1379 -0
- package/plugins/cursor-nightly/plugin.json +23 -0
- package/plugins/deepgram/icon.svg +1 -0
- package/plugins/deepgram/plugin.js +20 -0
- package/plugins/deepgram/plugin.json +17 -0
- package/plugins/deepseek/icon-color.svg +1 -0
- package/plugins/deepseek/icon.svg +1 -0
- package/plugins/deepseek/plugin.js +71 -0
- package/plugins/deepseek/plugin.json +17 -0
- package/plugins/devin/icon.svg +5 -0
- package/plugins/devin/plugin.js +341 -0
- package/plugins/devin/plugin.json +16 -0
- package/plugins/doubao/icon-color.svg +1 -0
- package/plugins/doubao/icon.svg +1 -0
- package/plugins/doubao/plugin.js +92 -0
- package/plugins/doubao/plugin.json +17 -0
- package/plugins/droid/icon.svg +1 -0
- package/plugins/droid/plugin.json +20 -0
- package/plugins/elevenlabs/icon.svg +4 -0
- package/plugins/elevenlabs/plugin.js +48 -0
- package/plugins/elevenlabs/plugin.json +18 -0
- package/plugins/factory/icon-conflict.svg +1 -0
- package/plugins/factory/icon.svg +1 -0
- package/plugins/factory/plugin.js +487 -0
- package/plugins/factory/plugin.json +15 -0
- package/plugins/fireworks-ai/icon.svg +6 -0
- package/plugins/fireworks-ai/plugin.js +370 -0
- package/plugins/fireworks-ai/plugin.json +19 -0
- package/plugins/gemini/icon-color.svg +1 -0
- package/plugins/gemini/icon.svg +1 -0
- package/plugins/gemini/plugin.js +460 -0
- package/plugins/gemini/plugin.json +16 -0
- package/plugins/grok/icon.svg +1 -0
- package/plugins/grok/plugin.js +297 -0
- package/plugins/grok/plugin.json +19 -0
- package/plugins/groqcloud/icon.svg +1 -0
- package/plugins/groqcloud/plugin.js +117 -0
- package/plugins/groqcloud/plugin.json +19 -0
- package/plugins/jetbrains-ai-assistant/icon-color.svg +14 -0
- package/plugins/jetbrains-ai-assistant/icon-conflict.svg +3 -0
- package/plugins/jetbrains-ai-assistant/icon.svg +14 -0
- package/plugins/jetbrains-ai-assistant/plugin.js +313 -0
- package/plugins/jetbrains-ai-assistant/plugin.json +16 -0
- package/plugins/kilo/icon.svg +1 -0
- package/plugins/kilo/plugin.js +111 -0
- package/plugins/kilo/plugin.json +19 -0
- package/plugins/kimi/icon-color.svg +1 -0
- package/plugins/kimi/icon-conflict.svg +3 -0
- package/plugins/kimi/icon.svg +1 -0
- package/plugins/kimi/plugin.js +358 -0
- package/plugins/kimi/plugin.json +15 -0
- package/plugins/kimi-k2/icon-color.svg +1 -0
- package/plugins/kimi-k2/icon.svg +1 -0
- package/plugins/kimi-k2/plugin.js +58 -0
- package/plugins/kimi-k2/plugin.json +18 -0
- package/plugins/kiro/icon-color.svg +5 -0
- package/plugins/kiro/icon-conflict.svg +1 -0
- package/plugins/kiro/icon.svg +4 -0
- package/plugins/kiro/plugin.js +390 -0
- package/plugins/kiro/plugin.json +16 -0
- package/plugins/litellm/icon.svg +16 -0
- package/plugins/litellm/plugin.js +199 -0
- package/plugins/litellm/plugin.json +16 -0
- package/plugins/llm-proxy/icon.svg +1 -0
- package/plugins/llm-proxy/plugin.js +40 -0
- package/plugins/llm-proxy/plugin.json +17 -0
- package/plugins/manus/icon.svg +6 -0
- package/plugins/manus/plugin.js +50 -0
- package/plugins/manus/plugin.json +17 -0
- package/plugins/mimo/icon.svg +1 -0
- package/plugins/mimo/plugin.js +177 -0
- package/plugins/mimo/plugin.json +19 -0
- package/plugins/minimax/icon-color.svg +1 -0
- package/plugins/minimax/icon-conflict.svg +4 -0
- package/plugins/minimax/icon.svg +1 -0
- package/plugins/minimax/plugin.js +453 -0
- package/plugins/minimax/plugin.json +14 -0
- package/plugins/mistral/icon-color.svg +1 -0
- package/plugins/mistral/icon.svg +1 -0
- package/plugins/mistral/plugin.js +152 -0
- package/plugins/mistral/plugin.json +18 -0
- package/plugins/moonshot/icon.svg +1 -0
- package/plugins/moonshot/plugin.js +43 -0
- package/plugins/moonshot/plugin.json +16 -0
- package/plugins/nanogpt/icon-color.svg +17 -0
- package/plugins/nanogpt/icon.svg +10 -0
- package/plugins/nanogpt/plugin.js +80 -0
- package/plugins/nanogpt/plugin.json +17 -0
- package/plugins/neuralwatt/icon.svg +3 -0
- package/plugins/neuralwatt/plugin.js +152 -0
- package/plugins/neuralwatt/plugin.json +17 -0
- package/plugins/ollama/icon.svg +1 -0
- package/plugins/ollama/plugin.js +92 -0
- package/plugins/ollama/plugin.json +20 -0
- package/plugins/openai-api/icon.svg +1 -0
- package/plugins/openai-api/plugin.js +533 -0
- package/plugins/openai-api/plugin.json +26 -0
- package/plugins/opencode/icon.svg +1 -0
- package/plugins/opencode/plugin.js +342 -0
- package/plugins/opencode/plugin.json +19 -0
- package/plugins/opencode-go/icon-conflict.svg +1 -0
- package/plugins/opencode-go/icon.svg +1 -0
- package/plugins/opencode-go/plugin.js +617 -0
- package/plugins/opencode-go/plugin.json +50 -0
- package/plugins/openrouter/icon.svg +1 -0
- package/plugins/openrouter/plugin.js +156 -0
- package/plugins/openrouter/plugin.json +8 -0
- package/plugins/perplexity/icon-color.svg +1 -0
- package/plugins/perplexity/icon-conflict.svg +1 -0
- package/plugins/perplexity/icon.svg +1 -0
- package/plugins/perplexity/plugin.js +425 -0
- package/plugins/perplexity/plugin.json +19 -0
- package/plugins/poe/icon.svg +1 -0
- package/plugins/poe/plugin.js +190 -0
- package/plugins/poe/plugin.json +19 -0
- package/plugins/stepfun/icon-color.svg +1 -0
- package/plugins/stepfun/icon.svg +1 -0
- package/plugins/stepfun/plugin.js +155 -0
- package/plugins/stepfun/plugin.json +18 -0
- package/plugins/synthetic/icon-conflict.svg +12 -0
- package/plugins/synthetic/icon.svg +14 -0
- package/plugins/synthetic/plugin.js +331 -0
- package/plugins/synthetic/plugin.json +23 -0
- package/plugins/t3chat/icon-color.svg +28 -0
- package/plugins/t3chat/icon.svg +4 -0
- package/plugins/t3chat/plugin.js +243 -0
- package/plugins/t3chat/plugin.json +20 -0
- package/plugins/venice/icon-color.svg +1 -0
- package/plugins/venice/icon.svg +1 -0
- package/plugins/venice/plugin.js +69 -0
- package/plugins/venice/plugin.json +16 -0
- package/plugins/vertex-ai/icon-color.svg +1 -0
- package/plugins/vertex-ai/icon.svg +1 -0
- package/plugins/vertex-ai/plugin.js +172 -0
- package/plugins/vertex-ai/plugin.json +18 -0
- package/plugins/warp/icon-color.svg +10 -0
- package/plugins/warp/icon.svg +6 -0
- package/plugins/warp/plugin.js +108 -0
- package/plugins/warp/plugin.json +18 -0
- package/plugins/windsurf/icon-conflict.svg +3 -0
- package/plugins/windsurf/icon.svg +1 -0
- package/plugins/windsurf/plugin.js +208 -0
- package/plugins/windsurf/plugin.json +16 -0
- package/plugins/zai/icon-conflict.svg +5 -0
- package/plugins/zai/icon.svg +1 -0
- package/plugins/zai/plugin.js +188 -0
- package/plugins/zai/plugin.json +16 -0
- package/plugins/zed/icon.svg +4 -0
- package/plugins/zed/plugin.js +270 -0
- package/plugins/zed/plugin.json +19 -0
- package/usagestat +0 -0
- package/usagestatd +0 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var QUOTA_FILENAME = "AIAssistantQuotaManager2.xml"
|
|
3
|
+
|
|
4
|
+
// JetBrains stores AI quota in 1e-5 credit units; divide by this to get credits.
|
|
5
|
+
var CREDIT_UNIT_SCALE = 100000
|
|
6
|
+
|
|
7
|
+
var PRODUCT_PREFIXES = [
|
|
8
|
+
"Aqua",
|
|
9
|
+
"AndroidStudio",
|
|
10
|
+
"CLion",
|
|
11
|
+
"DataGrip",
|
|
12
|
+
"DataSpell",
|
|
13
|
+
"GoLand",
|
|
14
|
+
"IdeaIC",
|
|
15
|
+
"IntelliJIdea",
|
|
16
|
+
"IntelliJIdeaCE",
|
|
17
|
+
"PhpStorm",
|
|
18
|
+
"PyCharm",
|
|
19
|
+
"PyCharmCE",
|
|
20
|
+
"Rider",
|
|
21
|
+
"RubyMine",
|
|
22
|
+
"RustRover",
|
|
23
|
+
"WebStorm",
|
|
24
|
+
"Writerside",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
function platformBaseDirs(ctx) {
|
|
28
|
+
var root = ctx.host.fs.appSupportPath("JetBrains")
|
|
29
|
+
if (!root) throw {code: "failed", message: "JetBrains configuration directory unavailable. Set settings.configDir to the IDE configuration directory."}
|
|
30
|
+
return [root]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isLikelyIdeDirName(name) {
|
|
34
|
+
if (typeof name !== "string") return false
|
|
35
|
+
var trimmed = name.trim()
|
|
36
|
+
if (!trimmed) return false
|
|
37
|
+
var hasPrefix = false
|
|
38
|
+
for (var i = 0; i < PRODUCT_PREFIXES.length; i += 1) {
|
|
39
|
+
if (trimmed.indexOf(PRODUCT_PREFIXES[i]) === 0) {
|
|
40
|
+
hasPrefix = true
|
|
41
|
+
break
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!hasPrefix) return false
|
|
45
|
+
return /\d{4}\.\d/.test(trimmed)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function safeListDir(ctx, path) {
|
|
49
|
+
if (
|
|
50
|
+
!ctx.host.fs ||
|
|
51
|
+
typeof ctx.host.fs.listDir !== "function" ||
|
|
52
|
+
!ctx.host.fs.exists(path)
|
|
53
|
+
) {
|
|
54
|
+
return []
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
var entries = ctx.host.fs.listDir(path)
|
|
59
|
+
return Array.isArray(entries) ? entries : []
|
|
60
|
+
} catch (e) {
|
|
61
|
+
ctx.host.log.warn("listDir failed for " + path + ": " + String(e))
|
|
62
|
+
return []
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function buildQuotaPaths(ctx) {
|
|
67
|
+
var settings = (ctx.provider && ctx.provider.settings) || {}
|
|
68
|
+
if (typeof settings.configDir === "string" && settings.configDir) {
|
|
69
|
+
var explicit = settings.configDir.replace(/[\\/]+$/, "") + "/options/" + QUOTA_FILENAME
|
|
70
|
+
return ctx.host.fs.exists(explicit) ? [explicit] : []
|
|
71
|
+
}
|
|
72
|
+
var bases = platformBaseDirs(ctx)
|
|
73
|
+
var paths = []
|
|
74
|
+
var seen = Object.create(null)
|
|
75
|
+
for (var b = 0; b < bases.length; b += 1) {
|
|
76
|
+
var base = bases[b]
|
|
77
|
+
var entries = safeListDir(ctx, base)
|
|
78
|
+
for (var i = 0; i < entries.length; i += 1) {
|
|
79
|
+
var dirName = entries[i]
|
|
80
|
+
if (!isLikelyIdeDirName(dirName)) continue
|
|
81
|
+
var quotaPath = base + "/" + dirName + "/options/" + QUOTA_FILENAME
|
|
82
|
+
if (!ctx.host.fs.exists(quotaPath)) continue
|
|
83
|
+
if (!seen[quotaPath]) {
|
|
84
|
+
seen[quotaPath] = true
|
|
85
|
+
paths.push(quotaPath)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return paths
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function decodeXmlEntities(text) {
|
|
93
|
+
if (!text) return ""
|
|
94
|
+
return String(text)
|
|
95
|
+
.replace(/ /g, "\n")
|
|
96
|
+
.replace(/ /g, "\r")
|
|
97
|
+
.replace(/"/g, '"')
|
|
98
|
+
.replace(/'/g, "'")
|
|
99
|
+
.replace(/</g, "<")
|
|
100
|
+
.replace(/>/g, ">")
|
|
101
|
+
.replace(/&/g, "&")
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function parseOptionJson(ctx, xml, optionName) {
|
|
105
|
+
var elemMatch = xml.match(new RegExp('<option\\b[^>]*\\bname="' + optionName + '"[^>]*/>'))
|
|
106
|
+
if (!elemMatch) return null
|
|
107
|
+
var valueMatch = elemMatch[0].match(/\bvalue="([^"]*)"/)
|
|
108
|
+
if (!valueMatch) return null
|
|
109
|
+
return ctx.util.tryParseJson(decodeXmlEntities(valueMatch[1]))
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function toNumber(value) {
|
|
113
|
+
var n = Number(value)
|
|
114
|
+
return Number.isFinite(n) ? n : null
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function clamp(value, min, max) {
|
|
118
|
+
if (value < min) return min
|
|
119
|
+
if (value > max) return max
|
|
120
|
+
return value
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function normalizeQuota(quotaInfo) {
|
|
124
|
+
if (!quotaInfo || typeof quotaInfo !== "object") return null
|
|
125
|
+
|
|
126
|
+
var maximum = toNumber(quotaInfo.maximum)
|
|
127
|
+
var used = toNumber(quotaInfo.current)
|
|
128
|
+
var remaining = toNumber(quotaInfo.available)
|
|
129
|
+
|
|
130
|
+
var tariff = quotaInfo.tariffQuota && typeof quotaInfo.tariffQuota === "object"
|
|
131
|
+
? quotaInfo.tariffQuota
|
|
132
|
+
: null
|
|
133
|
+
var topUp = quotaInfo.topUpQuota && typeof quotaInfo.topUpQuota === "object"
|
|
134
|
+
? quotaInfo.topUpQuota
|
|
135
|
+
: null
|
|
136
|
+
|
|
137
|
+
if (maximum === null) {
|
|
138
|
+
var tariffMaximum = tariff ? toNumber(tariff.maximum) : null
|
|
139
|
+
var topUpMaximum = topUp ? toNumber(topUp.maximum) : null
|
|
140
|
+
if (tariffMaximum !== null || topUpMaximum !== null) {
|
|
141
|
+
maximum = (tariffMaximum !== null ? tariffMaximum : 0) + (topUpMaximum !== null ? topUpMaximum : 0)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (used === null) {
|
|
146
|
+
var tariffUsed = tariff ? toNumber(tariff.current) : null
|
|
147
|
+
var topUpUsed = topUp ? toNumber(topUp.current) : null
|
|
148
|
+
if (tariffUsed !== null || topUpUsed !== null) {
|
|
149
|
+
used = (tariffUsed !== null ? tariffUsed : 0) + (topUpUsed !== null ? topUpUsed : 0)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (remaining === null) {
|
|
154
|
+
var tariffRemaining = tariff ? toNumber(tariff.available) : null
|
|
155
|
+
var topUpRemaining = topUp ? toNumber(topUp.available) : null
|
|
156
|
+
if (tariffRemaining !== null || topUpRemaining !== null) {
|
|
157
|
+
remaining = (tariffRemaining !== null ? tariffRemaining : 0) + (topUpRemaining !== null ? topUpRemaining : 0)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (remaining === null && maximum !== null && used !== null) {
|
|
162
|
+
remaining = maximum - used
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (maximum === null || maximum <= 0 || used === null) return null
|
|
166
|
+
|
|
167
|
+
used = clamp(used, 0, maximum)
|
|
168
|
+
if (remaining !== null) remaining = clamp(remaining, 0, maximum)
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
used: used,
|
|
172
|
+
maximum: maximum,
|
|
173
|
+
remaining: remaining,
|
|
174
|
+
until: quotaInfo.until || null,
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function readQuotaState(ctx, path) {
|
|
179
|
+
if (!ctx.host.fs.exists(path)) return null
|
|
180
|
+
try {
|
|
181
|
+
var xml = ctx.host.fs.readText(path)
|
|
182
|
+
var quotaInfo = parseOptionJson(ctx, xml, "quotaInfo")
|
|
183
|
+
var nextRefill = parseOptionJson(ctx, xml, "nextRefill")
|
|
184
|
+
var quota = normalizeQuota(quotaInfo)
|
|
185
|
+
if (!quota) return null
|
|
186
|
+
return { path: path, quota: quota, nextRefill: nextRefill }
|
|
187
|
+
} catch (e) {
|
|
188
|
+
ctx.host.log.warn("failed reading quota state " + path + ": " + String(e))
|
|
189
|
+
return null
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Handles only simple single-component durations (PTnH, PnD, PnW).
|
|
194
|
+
// JetBrains currently uses values like PT720H or P30D.
|
|
195
|
+
function parseIsoDurationMs(value) {
|
|
196
|
+
if (typeof value !== "string" || !value) return null
|
|
197
|
+
|
|
198
|
+
var h = value.match(/^PT(\d+)H$/)
|
|
199
|
+
if (h) return Number(h[1]) * 60 * 60 * 1000
|
|
200
|
+
|
|
201
|
+
var d = value.match(/^P(\d+)D$/)
|
|
202
|
+
if (d) return Number(d[1]) * 24 * 60 * 60 * 1000
|
|
203
|
+
|
|
204
|
+
var w = value.match(/^P(\d+)W$/)
|
|
205
|
+
if (w) return Number(w[1]) * 7 * 24 * 60 * 60 * 1000
|
|
206
|
+
|
|
207
|
+
return null
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function formatDecimal(value, places) {
|
|
211
|
+
if (!Number.isFinite(value)) return null
|
|
212
|
+
var factor = Math.pow(10, places)
|
|
213
|
+
var rounded = Math.round(value * factor) / factor
|
|
214
|
+
return rounded.toFixed(places).replace(/\.?0+$/, "")
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function detectDisplayScale(quota, nextRefill) {
|
|
218
|
+
var maxAbs = Math.max(
|
|
219
|
+
Math.abs(quota.maximum || 0),
|
|
220
|
+
Math.abs(quota.used || 0),
|
|
221
|
+
Math.abs(quota.remaining || 0)
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
if (nextRefill && nextRefill.tariff && typeof nextRefill.tariff === "object") {
|
|
225
|
+
var tariffAmount = toNumber(nextRefill.tariff.amount)
|
|
226
|
+
if (tariffAmount !== null) {
|
|
227
|
+
maxAbs = Math.max(maxAbs, Math.abs(tariffAmount))
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (maxAbs >= CREDIT_UNIT_SCALE) return CREDIT_UNIT_SCALE
|
|
232
|
+
return 1
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function probe(ctx) {
|
|
236
|
+
var paths = buildQuotaPaths(ctx)
|
|
237
|
+
var states = []
|
|
238
|
+
|
|
239
|
+
for (var i = 0; i < paths.length; i += 1) {
|
|
240
|
+
var state = readQuotaState(ctx, paths[i])
|
|
241
|
+
if (state) states.push(state)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (states.length === 0) {
|
|
245
|
+
throw paths.length > 0
|
|
246
|
+
? "JetBrains AI Assistant quota data unavailable. Open AI Assistant once and try again."
|
|
247
|
+
: "JetBrains AI Assistant not detected. Open a JetBrains IDE with AI Assistant enabled."
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (states.length > 1) {
|
|
251
|
+
throw {code: "failed", message: "Multiple JetBrains IDE quota profiles found. Select settings.configDir to choose one installation."}
|
|
252
|
+
}
|
|
253
|
+
var chosen = states[0]
|
|
254
|
+
var quota = chosen.quota
|
|
255
|
+
var scale = detectDisplayScale(quota, chosen.nextRefill)
|
|
256
|
+
var usedPercent = (quota.used / quota.maximum) * 100
|
|
257
|
+
if (!Number.isFinite(usedPercent)) usedPercent = 0
|
|
258
|
+
usedPercent = clamp(usedPercent, 0, 100)
|
|
259
|
+
var line = {
|
|
260
|
+
label: "Quota",
|
|
261
|
+
used: usedPercent,
|
|
262
|
+
limit: 100,
|
|
263
|
+
format: { kind: "percent" },
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
var resetSource = null
|
|
267
|
+
if (chosen.nextRefill && chosen.nextRefill.next) {
|
|
268
|
+
resetSource = chosen.nextRefill.next
|
|
269
|
+
} else if (quota.until) {
|
|
270
|
+
resetSource = quota.until
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
var resetsAt = ctx.util.toIso(resetSource)
|
|
274
|
+
if (resetsAt) line.resetsAt = resetsAt
|
|
275
|
+
|
|
276
|
+
var duration = null
|
|
277
|
+
if (
|
|
278
|
+
chosen.nextRefill &&
|
|
279
|
+
chosen.nextRefill.tariff &&
|
|
280
|
+
typeof chosen.nextRefill.tariff === "object"
|
|
281
|
+
) {
|
|
282
|
+
duration = parseIsoDurationMs(chosen.nextRefill.tariff.duration)
|
|
283
|
+
}
|
|
284
|
+
if (duration) line.periodDurationMs = duration
|
|
285
|
+
|
|
286
|
+
var lines = [ctx.line.progress(line)]
|
|
287
|
+
|
|
288
|
+
lines.push(
|
|
289
|
+
ctx.line.text({
|
|
290
|
+
label: "Used",
|
|
291
|
+
value:
|
|
292
|
+
scale > 1
|
|
293
|
+
? formatDecimal(quota.used / scale, 2) + " / " + formatDecimal(quota.maximum / scale, 2) + " credits"
|
|
294
|
+
: String(quota.used),
|
|
295
|
+
})
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
if (quota.remaining !== null) {
|
|
299
|
+
lines.push(
|
|
300
|
+
ctx.line.text({
|
|
301
|
+
label: "Remaining",
|
|
302
|
+
value: scale > 1 ? formatDecimal(quota.remaining / scale, 2) + " credits" : String(quota.remaining),
|
|
303
|
+
})
|
|
304
|
+
)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
ctx.host.log.info("quota loaded from " + chosen.path)
|
|
308
|
+
|
|
309
|
+
return { lines: lines }
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
globalThis.__openusage_plugin = { id: "jetbrains-ai-assistant", probe: probe }
|
|
313
|
+
})()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "jetbrains-ai-assistant",
|
|
4
|
+
"name": "JetBrains AI Assistant",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"icon": "icon.svg",
|
|
8
|
+
"brandColor": "#7d5fe6",
|
|
9
|
+
"supportedModes": ["local"],
|
|
10
|
+
"autoMode": "local",
|
|
11
|
+
"lines": [
|
|
12
|
+
{ "type": "progress", "label": "Quota", "scope": "overview", "primaryOrder": 1 },
|
|
13
|
+
{ "type": "text", "label": "Used", "scope": "detail" },
|
|
14
|
+
{ "type": "text", "label": "Remaining", "scope": "detail" }
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Kilo Code</title><path d="M0 0v24h24V0H0zm22.222 22.222H1.778V1.778h20.444v20.444zm-7.555-4.964h2.222v1.778h-2.794L12.89 17.83v-2.794h1.778v2.222zm4 0h-1.778v-2.222h-2.222v-1.778h2.793l1.207 1.207v2.793zm-7.556-2.591H9.333v-1.778h1.778v1.778zm-5.778-1.778h1.778v4h4v1.778H6.54L5.333 17.46V12.89zm13.334-3.556v1.778h-5.778V9.333h1.987V7.111h-1.987V5.333h2.558l1.206 1.207v2.793h2.014zm-11.556-2h2.222l1.778 1.778v2H9.333v-2H7.111v2H5.333V5.333h1.778v2zm4 0H9.333v-2h1.778v2z"></path></svg>
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var TRPC_BASE = "https://app.kilo.ai/api/trpc";
|
|
3
|
+
var PROCEDURES = "user.getCreditBlocks,kiloPass.getState,user.getAutoTopUpPaymentMethod";
|
|
4
|
+
var AUTH_PATH = "~/.local/share/kilo/auth.json";
|
|
5
|
+
|
|
6
|
+
function loadApiKey(ctx) {
|
|
7
|
+
var v = ctx.host.env.get("KILO_API_KEY");
|
|
8
|
+
if (typeof v === "string" && v.trim()) return v.trim();
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
if (ctx.host.fs.exists(AUTH_PATH)) {
|
|
12
|
+
var json = ctx.util.tryParseJson(ctx.host.fs.readText(AUTH_PATH));
|
|
13
|
+
if (json) {
|
|
14
|
+
var keys = ["apiKey", "api_key", "token"];
|
|
15
|
+
for (var i = 0; i < keys.length; i++) {
|
|
16
|
+
if (typeof json[keys[i]] === "string" && json[keys[i]].trim()) return json[keys[i]].trim();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
} catch (e) {
|
|
21
|
+
ctx.host.log.warn("kilo: failed to read auth.json: " + e);
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function buildUrl() {
|
|
27
|
+
var input = JSON.stringify({
|
|
28
|
+
"0": { json: null, meta: { values: ["undefined"] } },
|
|
29
|
+
"1": { json: null, meta: { values: ["undefined"] } },
|
|
30
|
+
"2": { json: null, meta: { values: ["undefined"] } },
|
|
31
|
+
});
|
|
32
|
+
return TRPC_BASE + "/" + PROCEDURES + "?batch=1&input=" + encodeURIComponent(input);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function extractData(batch, index) {
|
|
36
|
+
if (!Array.isArray(batch)) return null;
|
|
37
|
+
var item = batch[index];
|
|
38
|
+
return item && item.result && item.result.data && item.result.data.json;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function probe(ctx) {
|
|
42
|
+
var apiKey = loadApiKey(ctx);
|
|
43
|
+
if (!apiKey) {
|
|
44
|
+
throw "Kilo API key not found. Set KILO_API_KEY or sign in with Kilo CLI.";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
var result = ctx.util.requestJson({
|
|
48
|
+
method: "GET",
|
|
49
|
+
url: buildUrl(),
|
|
50
|
+
headers: { Authorization: "Bearer " + apiKey, Accept: "application/json" },
|
|
51
|
+
timeoutMs: 30000,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (ctx.util.isAuthStatus(result.resp.status)) {
|
|
55
|
+
throw "API key invalid or expired.";
|
|
56
|
+
}
|
|
57
|
+
if (result.resp.status < 200 || result.resp.status >= 300) {
|
|
58
|
+
throw "Kilo API error (HTTP " + result.resp.status + ").";
|
|
59
|
+
}
|
|
60
|
+
if (!result.json) throw "Could not parse Kilo response.";
|
|
61
|
+
|
|
62
|
+
var creditBlocks = extractData(result.json, 0);
|
|
63
|
+
var kiloPass = extractData(result.json, 1);
|
|
64
|
+
|
|
65
|
+
var totalMusd = 0, remainingMusd = 0;
|
|
66
|
+
if (Array.isArray(creditBlocks)) {
|
|
67
|
+
creditBlocks.forEach(function (block) {
|
|
68
|
+
totalMusd += (block.amount_mUsd || 0);
|
|
69
|
+
remainingMusd += (block.balance_mUsd || 0);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
var totalUsd = totalMusd / 1e6;
|
|
74
|
+
var remainingUsd = remainingMusd / 1e6;
|
|
75
|
+
var usedUsd = Math.max(0, totalUsd - remainingUsd);
|
|
76
|
+
var usedPct = totalUsd > 0 ? Math.min(100, (usedUsd / totalUsd) * 100) : 0;
|
|
77
|
+
|
|
78
|
+
var lines = [
|
|
79
|
+
ctx.line.progress({
|
|
80
|
+
label: "Credits",
|
|
81
|
+
used: usedPct,
|
|
82
|
+
limit: 100,
|
|
83
|
+
format: { kind: "percent" },
|
|
84
|
+
}),
|
|
85
|
+
ctx.line.text({ label: "Balance", value: "$" + usedUsd.toFixed(2) + " / $" + totalUsd.toFixed(2) }),
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
var plan = null;
|
|
89
|
+
if (kiloPass) {
|
|
90
|
+
var passUsage = kiloPass.currentPeriodUsageUsd || 0;
|
|
91
|
+
var passBase = kiloPass.currentPeriodBaseCreditsUsd || 0;
|
|
92
|
+
var passBonus = kiloPass.currentPeriodBonusCreditsUsd || 0;
|
|
93
|
+
var passTotal = passBase + passBonus;
|
|
94
|
+
if (passTotal > 0) {
|
|
95
|
+
var passPct = Math.min(100, (passUsage / passTotal) * 100);
|
|
96
|
+
lines.push(ctx.line.progress({
|
|
97
|
+
label: "Pass",
|
|
98
|
+
used: passPct,
|
|
99
|
+
limit: 100,
|
|
100
|
+
format: { kind: "percent" },
|
|
101
|
+
}));
|
|
102
|
+
lines.push(ctx.line.text({ label: "Pass Balance", value: "$" + passUsage.toFixed(2) + " / $" + passTotal.toFixed(2) }));
|
|
103
|
+
}
|
|
104
|
+
plan = kiloPass.planName || kiloPass.tier || kiloPass.status || null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return { plan: plan, lines: lines };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
globalThis.__openusage_plugin = { id: "kilo", probe: probe };
|
|
111
|
+
})();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "kilo",
|
|
4
|
+
"name": "Kilo",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"brandColor": "#F59E0B",
|
|
8
|
+
"links": [
|
|
9
|
+
{ "label": "Usage", "url": "https://app.kilo.ai/usage" }
|
|
10
|
+
],
|
|
11
|
+
"supportedModes": ["api", "local"],
|
|
12
|
+
"autoMode": "local",
|
|
13
|
+
"lines": [
|
|
14
|
+
{ "type": "progress", "label": "Credits", "scope": "overview", "primaryOrder": 1 },
|
|
15
|
+
{ "type": "text", "label": "Balance", "scope": "detail" },
|
|
16
|
+
{ "type": "progress", "label": "Pass", "scope": "overview", "primaryOrder": 2 },
|
|
17
|
+
{ "type": "text", "label": "Pass Balance", "scope": "detail" }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Kimi</title><path d="M21.846 0a1.923 1.923 0 110 3.846H20.15a.226.226 0 01-.227-.226V1.923C19.923.861 20.784 0 21.846 0z" fill="#1783FF"></path><path d="M11.065 11.199l7.257-7.2c.137-.136.06-.41-.116-.41H14.3a.164.164 0 00-.117.051l-7.82 7.756c-.122.12-.302.013-.302-.179V3.82c0-.127-.083-.23-.185-.23H3.186c-.103 0-.186.103-.186.23V19.77c0 .128.083.23.186.23h2.69c.103 0 .186-.102.186-.23v-3.25c0-.069.025-.135.069-.178l2.424-2.406a.158.158 0 01.205-.023l6.484 4.772a7.677 7.677 0 003.453 1.283c.108.012.2-.095.2-.23v-3.06c0-.117-.07-.212-.164-.227a5.028 5.028 0 01-2.027-.807l-5.613-4.064c-.117-.078-.132-.279-.028-.381z" fill="#fff"></path></svg>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
|
|
2
|
+
<path d="M11.065 11.199l7.257-7.2c.137-.136.06-.41-.116-.41H14.3a.164.164 0 0 0-.117.051l-7.82 7.756c-.122.12-.302.013-.302-.179V3.82c0-.127-.083-.23-.185-.23H3.186c-.103 0-.186.103-.186.23V19.77c0 .128.083.23.186.23h2.69c.103 0 .186-.102.186-.23v-3.25c0-.069.025-.135.069-.178l2.424-2.406a.158.158 0 0 1 .205-.023l6.484 4.772a7.677 7.677 0 0 0 3.453 1.283c.108.012.2-.095.2-.23v-3.06c0-.117-.07-.212-.164-.227a5.028 5.028 0 0 1-2.027-.807l-5.613-4.064c-.117-.078-.132-.279-.028-.381z" />
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Kimi</title><path d="M21.846 0a1.923 1.923 0 110 3.846H20.15a.226.226 0 01-.227-.226V1.923C19.923.861 20.784 0 21.846 0z"></path><path d="M11.065 11.199l7.257-7.2c.137-.136.06-.41-.116-.41H14.3a.164.164 0 00-.117.051l-7.82 7.756c-.122.12-.302.013-.302-.179V3.82c0-.127-.083-.23-.185-.23H3.186c-.103 0-.186.103-.186.23V19.77c0 .128.083.23.186.23h2.69c.103 0 .186-.102.186-.23v-3.25c0-.069.025-.135.069-.178l2.424-2.406a.158.158 0 01.205-.023l6.484 4.772a7.677 7.677 0 003.453 1.283c.108.012.2-.095.2-.23v-3.06c0-.117-.07-.212-.164-.227a5.028 5.028 0 01-2.027-.807l-5.613-4.064c-.117-.078-.132-.279-.028-.381z"></path></svg>
|