@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,16 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "windsurf",
4
+ "name": "Windsurf",
5
+ "version": "0.0.1",
6
+ "entry": "plugin.js",
7
+ "icon": "icon.svg",
8
+ "brandColor": "#111111",
9
+ "supportedModes": ["oauth", "local"],
10
+ "autoMode": "local",
11
+ "lines": [
12
+ { "type": "progress", "label": "Daily quota", "scope": "overview", "primaryOrder": 1 },
13
+ { "type": "progress", "label": "Weekly quota", "scope": "overview" },
14
+ { "type": "text", "label": "Extra usage balance", "scope": "detail" }
15
+ ]
16
+ }
@@ -0,0 +1,5 @@
1
+ <svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M51.57 23.67l-4.33 6.17c-0.67 0.97-1.80 1.57-3.00 1.57H20.57V23.63C20.53 23.67 51.57 23.67 51.57 23.67z" fill="currentColor"/>
3
+ <polygon points="81.00,23.67 43.80,76.37 19.00,76.37 56.20,23.67" fill="currentColor"/>
4
+ <path d="M48.43 76.37l4.37-6.20c0.67-0.97 1.80-1.57 3.00-1.57h23.63v7.77H48.43z" fill="currentColor"/>
5
+ </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>Z.ai</title><path d="M12.105 2L9.927 4.953H.653L2.83 2h9.276zM23.254 19.048L21.078 22h-9.242l2.174-2.952h9.244zM24 2L9.264 22H0L14.736 2H24z"></path></svg>
@@ -0,0 +1,188 @@
1
+ (function () {
2
+ const BASE_URL = "https://api.z.ai"
3
+ const SUBSCRIPTION_URL = BASE_URL + "/api/biz/subscription/list"
4
+ const QUOTA_URL = BASE_URL + "/api/monitor/usage/quota/limit"
5
+ const PERIOD_MS = 5 * 60 * 60 * 1000
6
+ const WEEK_MS = 7 * 24 * 60 * 60 * 1000
7
+ const MONTH_MS = 30 * 24 * 60 * 60 * 1000
8
+
9
+ function loadApiKey(ctx) {
10
+ const zai = ctx.host.env.get("ZAI_API_KEY")
11
+ if (typeof zai === "string" && zai.trim()) return zai.trim()
12
+
13
+ const glm = ctx.host.env.get("GLM_API_KEY")
14
+ if (typeof glm === "string" && glm.trim()) return glm.trim()
15
+
16
+ return null
17
+ }
18
+
19
+ function fetchSubscription(ctx, apiKey) {
20
+ try {
21
+ const resp = ctx.util.request({
22
+ method: "GET",
23
+ url: SUBSCRIPTION_URL,
24
+ headers: {
25
+ Authorization: "Bearer " + apiKey,
26
+ Accept: "application/json",
27
+ },
28
+ timeoutMs: 10000,
29
+ })
30
+ if (resp.status < 200 || resp.status >= 300) {
31
+ ctx.host.log.warn("subscription request failed: HTTP " + resp.status)
32
+ return null
33
+ }
34
+ const data = ctx.util.tryParseJson(resp.bodyText)
35
+ if (!data) return null
36
+ const list = data.data
37
+ if (!Array.isArray(list) || list.length === 0) return null
38
+ return {
39
+ productName: list[0].productName || null,
40
+ nextRenewTime: list[0].nextRenewTime || null,
41
+ }
42
+ } catch (e) {
43
+ ctx.host.log.warn("subscription request exception: " + String(e))
44
+ return null
45
+ }
46
+ }
47
+
48
+ function fetchQuota(ctx, apiKey) {
49
+ let resp
50
+ try {
51
+ resp = ctx.util.request({
52
+ method: "GET",
53
+ url: QUOTA_URL,
54
+ headers: {
55
+ Authorization: "Bearer " + apiKey,
56
+ Accept: "application/json",
57
+ },
58
+ timeoutMs: 10000,
59
+ })
60
+ } catch (e) {
61
+ ctx.host.log.error("usage request exception: " + String(e))
62
+ throw "Usage request failed. Check your connection."
63
+ }
64
+
65
+ if (ctx.util.isAuthStatus(resp.status)) {
66
+ throw "API key invalid. Check your Z.ai API key."
67
+ }
68
+
69
+ if (resp.status < 200 || resp.status >= 300) {
70
+ throw "Usage request failed (HTTP " + String(resp.status) + "). Try again later."
71
+ }
72
+
73
+ const data = ctx.util.tryParseJson(resp.bodyText)
74
+ if (!data) {
75
+ throw "Usage response invalid. Try again later."
76
+ }
77
+
78
+ return data
79
+ }
80
+
81
+ function findLimit(limits, type, unit) {
82
+ let fallback = null
83
+ for (let i = 0; i < limits.length; i++) {
84
+ const item = limits[i]
85
+ if (item.type === type || item.name === type) {
86
+ if (unit === undefined) {
87
+ return item
88
+ }
89
+ if (item.unit === unit) {
90
+ return item
91
+ }
92
+ // Store first entry without unit as fallback
93
+ if (fallback === null && item.unit === undefined) {
94
+ fallback = item
95
+ }
96
+ }
97
+ }
98
+ return fallback
99
+ }
100
+
101
+ function probe(ctx) {
102
+ const apiKey = loadApiKey(ctx)
103
+ if (!apiKey) {
104
+ throw "No ZAI_API_KEY found. Set up environment variable first."
105
+ }
106
+
107
+ const sub = fetchSubscription(ctx, apiKey)
108
+ const plan = sub && sub.productName ? ctx.fmt.planLabel(sub.productName) : null
109
+
110
+ const quota = fetchQuota(ctx, apiKey)
111
+ const lines = []
112
+
113
+ const container = quota.data || quota
114
+ const limits = container.limits || container
115
+ if (!Array.isArray(limits) || limits.length === 0) {
116
+ lines.push(ctx.line.badge({ label: "Session", text: "No usage data", color: "#a3a3a3" }))
117
+ return { plan, lines }
118
+ }
119
+
120
+ const tokenLimit = findLimit(limits, "TOKENS_LIMIT", 3)
121
+
122
+ if (!tokenLimit) {
123
+ lines.push(ctx.line.badge({ label: "Session", text: "No usage data", color: "#a3a3a3" }))
124
+ return { plan, lines }
125
+ }
126
+
127
+ const used = typeof tokenLimit.percentage === "number" ? tokenLimit.percentage : 0
128
+ const resetsAt = tokenLimit.nextResetTime ? ctx.util.toIso(tokenLimit.nextResetTime) : undefined
129
+
130
+ const progressOpts = {
131
+ label: "Session",
132
+ used,
133
+ limit: 100,
134
+ format: { kind: "percent" },
135
+ periodDurationMs: PERIOD_MS,
136
+ }
137
+ if (resetsAt) {
138
+ progressOpts.resetsAt = resetsAt
139
+ }
140
+ lines.push(ctx.line.progress(progressOpts))
141
+
142
+ const weeklyTokenLimit = findLimit(limits, "TOKENS_LIMIT", 6)
143
+ if (weeklyTokenLimit) {
144
+ const weeklyUsed = Number.isFinite(weeklyTokenLimit.percentage) ? weeklyTokenLimit.percentage : 0
145
+ const weeklyResetsAt = weeklyTokenLimit.nextResetTime ? ctx.util.toIso(weeklyTokenLimit.nextResetTime) : undefined
146
+
147
+ const weeklyOpts = {
148
+ label: "Weekly",
149
+ used: weeklyUsed,
150
+ limit: 100,
151
+ format: { kind: "percent" },
152
+ periodDurationMs: WEEK_MS,
153
+ }
154
+ if (weeklyResetsAt) {
155
+ weeklyOpts.resetsAt = weeklyResetsAt
156
+ }
157
+ lines.push(ctx.line.progress(weeklyOpts))
158
+ }
159
+
160
+ const timeLimit = findLimit(limits, "TIME_LIMIT")
161
+
162
+ if (timeLimit) {
163
+ const webUsed = typeof timeLimit.currentValue === "number" ? timeLimit.currentValue : 0
164
+ const webTotal = typeof timeLimit.usage === "number" ? timeLimit.usage : 0
165
+ const now = new Date()
166
+ const nextMonth = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1))
167
+ const webResetsAt = timeLimit.nextResetTime
168
+ ? ctx.util.toIso(timeLimit.nextResetTime)
169
+ : nextMonth.toISOString()
170
+
171
+ const webOpts = {
172
+ label: "Web Searches",
173
+ used: webUsed,
174
+ limit: webTotal,
175
+ format: { kind: "count", suffix: "/ " + webTotal },
176
+ periodDurationMs: MONTH_MS,
177
+ }
178
+ if (webResetsAt) {
179
+ webOpts.resetsAt = webResetsAt
180
+ }
181
+ lines.push(ctx.line.progress(webOpts))
182
+ }
183
+
184
+ return { plan, lines }
185
+ }
186
+
187
+ globalThis.__openusage_plugin = { id: "zai", probe }
188
+ })()
@@ -0,0 +1,16 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "zai",
4
+ "name": "Z.ai",
5
+ "version": "0.0.1",
6
+ "entry": "plugin.js",
7
+ "icon": "icon.svg",
8
+ "brandColor": "#2D2D2D",
9
+ "supportedModes": ["api"],
10
+ "autoMode": "api",
11
+ "lines": [
12
+ { "type": "progress", "label": "Session", "scope": "overview", "primaryOrder": 1 },
13
+ { "type": "progress", "label": "Weekly", "scope": "overview" },
14
+ { "type": "progress", "label": "Web Searches", "scope": "overview" }
15
+ ]
16
+ }
@@ -0,0 +1,4 @@
1
+ <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <title>Zed</title>
3
+ <path fill="#084EFF" d="M2.25 1.5a.75.75 0 0 0-.75.75v16.5H0V2.25A2.25 2.25 0 0 1 2.25 0h20.095c1.002 0 1.504 1.212.795 1.92L10.764 14.298h3.486V12.75h1.5v1.922a1.125 1.125 0 0 1-1.125 1.125H9.264l-2.578 2.578h11.689V9h1.5v9.375a1.5 1.5 0 0 1-1.5 1.5H5.185L2.562 22.5H21.75a.75.75 0 0 0 .75-.75V5.25H24v16.5A2.25 2.25 0 0 1 21.75 24H1.655C.653 24 .151 22.788.86 22.08L13.19 9.75H9.75v1.5h-1.5V9.375A1.125 1.125 0 0 1 9.375 8.25h5.314l2.625-2.625H5.625V15h-1.5V5.625a1.5 1.5 0 0 1 1.5-1.5h13.19L21.438 1.5z"/>
4
+ </svg>
@@ -0,0 +1,270 @@
1
+ (function () {
2
+ var DEFAULT_SERVICE_URL = "https://zed.dev";
3
+ var DEFAULT_SERVER = "https://cloud.zed.dev";
4
+
5
+ function env(ctx, name) {
6
+ try {
7
+ var value = ctx.host.env.get(name);
8
+ return typeof value === "string" && value.trim() ? value.trim() : null;
9
+ } catch (_) {
10
+ return null;
11
+ }
12
+ }
13
+
14
+ function setting(ctx, names) {
15
+ var settings = ctx.provider && ctx.provider.settings ? ctx.provider.settings : {};
16
+ for (var i = 0; i < names.length; i++) {
17
+ var value = settings[names[i]];
18
+ if (typeof value === "string" && value.trim()) return value.trim();
19
+ }
20
+ return null;
21
+ }
22
+
23
+ function settingsValue(settings, names) {
24
+ if (!settings || typeof settings !== "object") return null;
25
+ for (var i = 0; i < names.length; i++) {
26
+ var value = settings[names[i]];
27
+ if (typeof value === "string" && value.trim()) return value.trim();
28
+ }
29
+ return null;
30
+ }
31
+
32
+ function normalizeUrl(value) {
33
+ if (typeof value !== "string" || !value.trim()) return null;
34
+ return value.trim().replace(/\/+$/, "");
35
+ }
36
+
37
+ function pathValue(ctx, name, fromEnv) {
38
+ var value = fromEnv ? ctx.host.env.get(name) : (ctx.provider.settings || {})[name];
39
+ if (value === undefined || value === null || value === "") return null;
40
+ var absolute = typeof value === "string" && (ctx.app.platform === "windows"
41
+ ? /^(?:[A-Za-z]:[\\/]|[\\/]{2}[^\\/]+[\\/][^\\/]+)/.test(value) : value[0] === "/");
42
+ if (!absolute || value.indexOf("\u0000") >= 0) throw {code: "failed", message: "Zed " + name + " must be an absolute path."};
43
+ return value;
44
+ }
45
+
46
+ function settingsPath(ctx) {
47
+ var file = pathValue(ctx, "settingsPath", false);
48
+ if (file) return file;
49
+ var custom = pathValue(ctx, "userDataDir", false);
50
+ if (custom) return custom.replace(/[\\/]+$/, "") + "/config/settings.json";
51
+ if (ctx.app.platform === "macos") return ctx.host.fs.homeDir + "/.config/zed/settings.json";
52
+ var flatpak = ctx.app.platform === "linux" ? pathValue(ctx, "FLATPAK_XDG_CONFIG_HOME", true) : null;
53
+ if (flatpak) return flatpak.replace(/\/+$/, "") + "/zed/settings.json";
54
+ var path = ctx.host.fs.appSupportPath((ctx.app.platform === "windows" ? "Zed" : "zed") + "/settings.json");
55
+ if (!path) throw {code: "failed", message: "Zed config directory unavailable. Set settingsPath or userDataDir."};
56
+ return path;
57
+ }
58
+
59
+ // Zed settings are JSON with comments and trailing commas. Keep comment-like
60
+ // text inside strings intact, including escaped quotes and URL slashes.
61
+ function parseSettings(text) {
62
+ var clean = "", quoted = false, escaped = false;
63
+ text = text.replace(/^\uFEFF/, "");
64
+ for (var i = 0; i < text.length; i++) {
65
+ var c = text[i], next = text[i + 1];
66
+ if (quoted) {
67
+ clean += c;
68
+ if (escaped) escaped = false;
69
+ else if (c === "\\") escaped = true;
70
+ else if (c === '"') quoted = false;
71
+ } else if (c === '"') { quoted = true; clean += c; }
72
+ else if (c === "/" && next === "/") {
73
+ while (i + 1 < text.length && text[i + 1] !== "\n") i++;
74
+ clean += " ";
75
+ } else if (c === "/" && next === "*") {
76
+ var end = text.indexOf("*/", i + 2);
77
+ if (end < 0) throw new Error("Unterminated settings comment");
78
+ i = end + 1; clean += " ";
79
+ } else clean += c;
80
+ }
81
+ var result = ""; quoted = false; escaped = false;
82
+ for (var j = 0; j < clean.length; j++) {
83
+ var ch = clean[j];
84
+ if (quoted) {
85
+ result += ch;
86
+ if (escaped) escaped = false;
87
+ else if (ch === "\\") escaped = true;
88
+ else if (ch === '"') quoted = false;
89
+ } else if (ch === '"') { quoted = true; result += ch; }
90
+ else if (ch === "," && /^\s*[}\]]/.test(clean.slice(j + 1))) continue;
91
+ else result += ch;
92
+ }
93
+ var parsed = JSON.parse(result);
94
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("Settings must be an object");
95
+ return parsed;
96
+ }
97
+
98
+ function readSettings(ctx) {
99
+ var path = settingsPath(ctx);
100
+ if (!ctx.host.fs.exists(path)) {
101
+ if ((ctx.provider.settings || {}).settingsPath || (ctx.provider.settings || {}).userDataDir)
102
+ throw {code: "credential-unavailable", message: "Selected Zed settings file is missing. Check settingsPath/userDataDir."};
103
+ return {};
104
+ }
105
+ try {
106
+ return parseSettings(ctx.host.fs.readText(path));
107
+ } catch (_) {
108
+ throw {code: "credential-unavailable", message: "Cannot read valid JSONC from the selected Zed settings file."};
109
+ }
110
+ }
111
+
112
+ function isTrustedServer(url) {
113
+ return url === "https://zed.dev" || url === "https://staging.zed.dev";
114
+ }
115
+
116
+ function authConfig(ctx, zedSettings) {
117
+ var serverUrl = normalizeUrl(
118
+ setting(ctx, ["serverUrl", "serverURL"]) ||
119
+ env(ctx, "ZED_SERVER_URL") ||
120
+ settingsValue(zedSettings, ["server_url", "serverUrl", "serverURL"]) ||
121
+ DEFAULT_SERVICE_URL
122
+ );
123
+ var credentialsUrl = normalizeUrl(
124
+ setting(ctx, ["credentialsUrl", "credentialsURL"]) ||
125
+ settingsValue(zedSettings, ["credentials_url", "credentialsUrl", "credentialsURL"]) ||
126
+ serverUrl ||
127
+ DEFAULT_SERVICE_URL
128
+ );
129
+
130
+ if (!serverUrl || !/^https:\/\//i.test(serverUrl)) throw "Zed server URL must be HTTPS.";
131
+ if (!credentialsUrl || !/^https:\/\//i.test(credentialsUrl)) throw "Zed credentials URL must be HTTPS.";
132
+ if (!isTrustedServer(serverUrl) && credentialsUrl !== serverUrl) {
133
+ throw "Zed custom server credentials URL must match the server URL.";
134
+ }
135
+
136
+ return {
137
+ serverBase: isTrustedServer(serverUrl) ? DEFAULT_SERVER : serverUrl,
138
+ credentialsUrl: credentialsUrl,
139
+ };
140
+ }
141
+
142
+ function explicitCredentials(ctx) {
143
+ var userID = setting(ctx, ["userId", "userID"]) ||
144
+ (ctx.provider && typeof ctx.provider.workspaceId === "string" ? ctx.provider.workspaceId.trim() : "") ||
145
+ env(ctx, "ZED_USER_ID");
146
+ var accessToken = (ctx.provider && typeof ctx.provider.apiKey === "string" ? ctx.provider.apiKey.trim() : "") ||
147
+ setting(ctx, ["accessToken"]) ||
148
+ env(ctx, "ZED_ACCESS_TOKEN");
149
+ return userID && accessToken ? { userID: userID, accessToken: accessToken, source: "explicit" } : null;
150
+ }
151
+
152
+ function keychainCredentialFromRaw(ctx, raw) {
153
+ var parsed = typeof raw === "string" ? ctx.util.tryParseJson(raw) : raw;
154
+ if (!parsed || typeof parsed !== "object") return null;
155
+ var account = typeof parsed.account === "string" && parsed.account.trim() ? parsed.account.trim() : null;
156
+ var password = typeof parsed.password === "string" && parsed.password.trim() ? parsed.password.trim() : null;
157
+ if (!account || !password) return null;
158
+ return { userID: account, accessToken: password, source: "keychain" };
159
+ }
160
+
161
+ function readKeychainCredentials(ctx, credentialsUrl) {
162
+ var keychain = ctx.host.keychain;
163
+ if (!keychain) return null;
164
+
165
+ if (typeof keychain.readInternetPassword === "function") {
166
+ try {
167
+ var internet = keychainCredentialFromRaw(ctx, keychain.readInternetPassword(credentialsUrl));
168
+ if (internet) return internet;
169
+ } catch (e) {
170
+ ctx.host.log.info("Zed internet keychain read failed: " + String(e));
171
+ }
172
+ }
173
+
174
+ if (typeof keychain.readGenericPasswordItem === "function") {
175
+ try {
176
+ var generic = keychainCredentialFromRaw(ctx, keychain.readGenericPasswordItem(credentialsUrl));
177
+ if (generic) return generic;
178
+ } catch (e) {
179
+ ctx.host.log.info("Zed generic keychain read failed: " + String(e));
180
+ }
181
+ }
182
+
183
+ return null;
184
+ }
185
+
186
+ function credentials(ctx, credentialsUrl) {
187
+ var explicit = explicitCredentials(ctx);
188
+ if (explicit) return explicit;
189
+
190
+ var keychainCredentials = readKeychainCredentials(ctx, credentialsUrl);
191
+ if (keychainCredentials) {
192
+ ctx.host.log.info("Zed credentials loaded from keychain");
193
+ return keychainCredentials;
194
+ }
195
+
196
+ throw "Not signed in to Zed. Sign in from the Zed editor app with GitHub, or set ZED_USER_ID and ZED_ACCESS_TOKEN.";
197
+ }
198
+
199
+ function requestUser(ctx, creds, base) {
200
+ var resp = ctx.util.request({
201
+ method: "GET",
202
+ url: base + "/client/users/me",
203
+ headers: {
204
+ Authorization: creds.userID + " " + creds.accessToken,
205
+ Accept: "application/json",
206
+ },
207
+ timeoutMs: 15000,
208
+ });
209
+ if (ctx.util.isAuthStatus(resp.status)) throw "Zed credentials are invalid or expired. Sign in to Zed again.";
210
+ if (resp.status < 200 || resp.status >= 300) throw "Zed cloud API returned HTTP " + resp.status + ".";
211
+ var json = ctx.util.tryParseJson(resp.bodyText);
212
+ if (!json) throw "Could not parse Zed account response.";
213
+ return json;
214
+ }
215
+
216
+ function planLabel(plan) {
217
+ var raw = String(plan && (plan.plan_v3 || plan.planV3 || plan.name || "") || "").trim();
218
+ if (!raw) return null;
219
+ return raw.split(/[_-]+/).map(function (part) {
220
+ return part ? part.charAt(0).toUpperCase() + part.slice(1) : part;
221
+ }).join(" ");
222
+ }
223
+
224
+ function parseDate(value) {
225
+ if (typeof value !== "string" || !value.trim()) return null;
226
+ var ms = Date.parse(value);
227
+ return Number.isFinite(ms) ? new Date(ms) : null;
228
+ }
229
+
230
+ function usageLine(plan) {
231
+ var usage = plan && plan.usage && plan.usage.edit_predictions;
232
+ if (!usage) return { type: "badge", label: "Edit predictions", text: "Unavailable", color: "yellow" };
233
+ var used = Number(usage.used) || 0;
234
+ var limit = usage.limit;
235
+ if (limit === "unlimited" || (limit && limit.unlimited)) {
236
+ return { type: "text", label: "Edit predictions", value: String(Math.round(used)) + " used · unlimited" };
237
+ }
238
+ var numericLimit = typeof limit === "number" ? limit : Number(limit && limit.limited);
239
+ if (!Number.isFinite(numericLimit) || numericLimit <= 0) {
240
+ return { type: "text", label: "Edit predictions", value: String(Math.round(used)) + " used" };
241
+ }
242
+ var line = {
243
+ type: "progress",
244
+ label: "Edit predictions",
245
+ used: used,
246
+ limit: numericLimit,
247
+ format: { kind: "count", suffix: "predictions" },
248
+ };
249
+ var ended = parseDate(plan.subscription_period && (plan.subscription_period.ended_at || plan.subscription_period.endedAt));
250
+ if (ended) line.resetsAt = ended.toISOString();
251
+ return line;
252
+ }
253
+
254
+ function probe(ctx) {
255
+ var zedSettings = readSettings(ctx);
256
+ var config = authConfig(ctx, zedSettings);
257
+ var creds = credentials(ctx, config.credentialsUrl);
258
+ var json = requestUser(ctx, creds, config.serverBase);
259
+ var user = json.user || {};
260
+ var plan = json.plan || {};
261
+ var displayName = user.github_login || user.name ? "Zed (" + (user.github_login || user.name) + ")" : "Zed";
262
+ var lines = [usageLine(plan)];
263
+ if (plan.has_overdue_invoices || plan.hasOverdueInvoices) {
264
+ lines.push({ type: "badge", label: "Invoices", text: "Overdue", color: "red" });
265
+ }
266
+ return { displayName: displayName, source: "api", plan: planLabel(plan), lines: lines };
267
+ }
268
+
269
+ globalThis.__openusage_plugin = { id: "zed", probe: probe };
270
+ })();
@@ -0,0 +1,19 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "zed",
4
+ "name": "Zed",
5
+ "version": "0.0.1",
6
+ "entry": "plugin.js",
7
+ "icon": "icon.svg",
8
+ "brandColor": "#6D5EF8",
9
+ "links": [
10
+ { "label": "Account", "url": "https://zed.dev/account" },
11
+ { "label": "Status", "url": "https://status.zed.dev" }
12
+ ],
13
+ "supportedModes": ["api", "local"],
14
+ "autoMode": "api",
15
+ "lines": [
16
+ { "type": "progress", "label": "Edit predictions", "scope": "overview", "primaryOrder": 1 },
17
+ { "type": "badge", "label": "Invoices", "scope": "detail" }
18
+ ]
19
+ }
package/usagestat ADDED
Binary file
package/usagestatd ADDED
Binary file