oc-go-usage-display 1.0.2 → 2.0.0

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 (41) hide show
  1. package/README.md +249 -68
  2. package/bin/lib.js +433 -29
  3. package/bin/oc-go-usage-display-init.js +42 -13
  4. package/bin/oc-go-usage-display-remove.js +38 -0
  5. package/bin/oc-go-usage-display-show.js +47 -39
  6. package/bin/oc-go-usage-display-status.js +33 -42
  7. package/bin/oc-go-usage-display-update.js +27 -14
  8. package/dist/helpers.d.ts +116 -0
  9. package/dist/helpers.d.ts.map +1 -0
  10. package/dist/helpers.js +568 -0
  11. package/dist/helpers.js.map +1 -0
  12. package/dist/index.d.ts +5 -9
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +258 -278
  15. package/dist/index.js.map +1 -1
  16. package/dist/plugins/oc-go-usage-display.kilo.ts +678 -0
  17. package/dist/plugins/oc-go-usage-display.kilo.tsx +1272 -0
  18. package/dist/plugins/oc-go-usage-display.ts +678 -0
  19. package/dist/plugins/oc-go-usage-display.tsx +1018 -0
  20. package/dist/shared.d.ts +96 -0
  21. package/dist/shared.d.ts.map +1 -0
  22. package/dist/shared.js +575 -0
  23. package/dist/shared.js.map +1 -0
  24. package/dist/tui-shared.d.ts +109 -0
  25. package/dist/tui-shared.d.ts.map +1 -0
  26. package/dist/tui-shared.js +372 -0
  27. package/dist/tui-shared.js.map +1 -0
  28. package/dist/tui.d.ts.map +1 -1
  29. package/dist/tui.js +226 -377
  30. package/dist/tui.js.map +1 -1
  31. package/dist/tui.kilo.d.ts +8 -0
  32. package/dist/tui.kilo.d.ts.map +1 -0
  33. package/dist/tui.kilo.js +502 -0
  34. package/dist/tui.kilo.js.map +1 -0
  35. package/package.json +47 -13
  36. package/src/helpers.ts +733 -0
  37. package/src/index.ts +331 -304
  38. package/src/shared.ts +696 -0
  39. package/src/tui-shared.tsx +705 -0
  40. package/src/tui.kilo.tsx +816 -0
  41. package/src/tui.tsx +356 -465
@@ -0,0 +1,568 @@
1
+ // Pure helpers shared by the plugin entry modules.
2
+ //
3
+ // IMPORTANT: these live OUTSIDE `src/index.ts` / `src/tui.tsx`. OpenCode's
4
+ // loader enumerates every export of a plugin entry module and (when the
5
+ // default is not a `{ id, server }` module) invokes each one as a plugin
6
+ // factory. An entry module must therefore export ONLY its default module;
7
+ // keeping the helper surface here makes that contract structural instead of
8
+ // accidental (a stray `export function` returning null used to crash
9
+ // `Provider.list`).
10
+ //
11
+ // Unit-tested via `dist/helpers.js` (see test/unit/server.test.js and
12
+ // test/unit/tui.test.js).
13
+ import * as fs from "node:fs";
14
+ import { resolveHostRoots, formatResetDuration, hostEnv, isRecord, resolveUsageHost, safeJoinPath, toNonEmptyString, toUsageCount, CACHE_RATE_DECIMALS, CACHE_RATE_EMPTY, GO_MODEL_MIX_BUDGET, GO_MODEL_MIX_NAME_MAX_CHARS, GO_MODEL_MIX_SEPARATOR, GO_PROVIDER_ID, PERCENT_CELL_WIDTH, KILO_MODEL_NAME_MAX_CHARS, KILO_TOKEN_USAGE_ROWS, TOP_GO_MODELS_LIMIT, } from "./shared.js";
15
+ // ---------------------------------------------------------------------------
16
+ // Server: compact one-line snapshot summary (keeps the rolling reset suffix)
17
+ // ---------------------------------------------------------------------------
18
+ function formatWindow(window) {
19
+ if (!window)
20
+ return "n/a";
21
+ return `${window.percent}%`;
22
+ }
23
+ export function formatServerLine(snapshot) {
24
+ if (snapshot.apiUnavailable || (!snapshot.rolling && !snapshot.weekly && !snapshot.monthly)) {
25
+ const reason = snapshot.apiError ?? "unknown error";
26
+ return `Go n/a (${reason})`;
27
+ }
28
+ const rollingReset = formatResetDuration(snapshot.rolling?.resetInSec ?? null) ??
29
+ snapshot.rolling?.resetText ??
30
+ null;
31
+ const rollingText = snapshot.rolling === null
32
+ ? "5h n/a"
33
+ : `5h ${snapshot.rolling.percent}%${rollingReset ? ` (reset ${rollingReset})` : ""}`;
34
+ return `Go ${rollingText} | 7d ${formatWindow(snapshot.weekly)} | 30d ${formatWindow(snapshot.monthly)}`;
35
+ }
36
+ export function fileConfigPath(host = "opencode") {
37
+ return safeJoinPath(resolveHostRoots(host).configDir, "oc-go-usage-display.json");
38
+ }
39
+ export function readFileConfig(host = "opencode") {
40
+ let raw;
41
+ try {
42
+ raw = fs.readFileSync(fileConfigPath(host), "utf8");
43
+ }
44
+ catch {
45
+ return { workspaceId: null, authCookie: null };
46
+ }
47
+ let parsed;
48
+ try {
49
+ parsed = JSON.parse(raw);
50
+ }
51
+ catch {
52
+ return { workspaceId: null, authCookie: null };
53
+ }
54
+ if (!isRecord(parsed))
55
+ return { workspaceId: null, authCookie: null };
56
+ return {
57
+ workspaceId: toNonEmptyString(parsed.workspaceId),
58
+ authCookie: toNonEmptyString(parsed.authCookie),
59
+ };
60
+ }
61
+ export function isMalformedAuthCookie(cookie) {
62
+ // Reject CR/LF (header injection), separators that confuse cookie jars,
63
+ // plus tab, NUL, and double-quote (never valid in a cookie value).
64
+ return /[\r\n;,\t\0"]/.test(cookie);
65
+ }
66
+ export function hasMalformedAuthCookie(fileConfig = readFileConfig(), host = resolveUsageHost()) {
67
+ const raw = toNonEmptyString(hostEnv(host, "AUTH_COOKIE")) ?? fileConfig.authCookie;
68
+ if (!raw)
69
+ return false;
70
+ return isMalformedAuthCookie(raw);
71
+ }
72
+ // ---------------------------------------------------------------------------
73
+ // Server: cookie-fetch redirect policy
74
+ // ---------------------------------------------------------------------------
75
+ //
76
+ // The workspace scrape carries the user's `auth` cookie. Automatic redirect
77
+ // following may re-send caller headers (including the cookie) to a cross-origin
78
+ // Location, and runtime header stripping cannot be relied on to prevent that.
79
+ // The cookie path therefore requests `redirect: "manual"` and re-sends only
80
+ // after these helpers approve a Location on the allowlisted canonical HTTPS
81
+ // hosts. `fetchViaApiKey` is untouched (anonymous API path).
82
+ const ALLOWED_REDIRECT_HOSTS = new Set(["opencode.ai", "auth.opencode.ai"]);
83
+ // Follow at most this many redirects before giving up (a redirect loop or an
84
+ // endless login bounce becomes a clear unavailable snapshot instead of a hang).
85
+ export const MAX_REDIRECT_HOPS = 3;
86
+ // Only the canonical HTTPS origins may receive the auth cookie: no explicit
87
+ // ports, no userinfo, and an exact allowlisted hostname (so `opencode.ai.evil`
88
+ // never matches).
89
+ function isAllowedHttpsUrl(url) {
90
+ return (url.protocol === "https:" &&
91
+ url.username === "" &&
92
+ url.password === "" &&
93
+ url.port === "" &&
94
+ ALLOWED_REDIRECT_HOSTS.has(url.hostname));
95
+ }
96
+ // Resolve `location` against `fromUrl`; null unless BOTH the current URL and
97
+ // the resolved target are allowed HTTPS origins.
98
+ function resolveRedirectUrl(fromUrl, location) {
99
+ let base;
100
+ try {
101
+ base = new URL(fromUrl);
102
+ }
103
+ catch {
104
+ return null;
105
+ }
106
+ if (!isAllowedHttpsUrl(base))
107
+ return null;
108
+ let next;
109
+ try {
110
+ next = new URL(location, base);
111
+ }
112
+ catch {
113
+ return null;
114
+ }
115
+ return isAllowedHttpsUrl(next) ? next : null;
116
+ }
117
+ function redirectTargetHost(fromUrl, location) {
118
+ try {
119
+ const host = new URL(location, fromUrl).host;
120
+ return host.length > 0 ? host : null;
121
+ }
122
+ catch {
123
+ return null;
124
+ }
125
+ }
126
+ // True when `location` resolves to an allowed canonical HTTPS host relative to
127
+ // an allowed `fromUrl`. Relative locations inherit the current host.
128
+ export function isAllowedRedirect(fromUrl, location) {
129
+ return resolveRedirectUrl(fromUrl, location) !== null;
130
+ }
131
+ // Pure redirect decision: follow (with the resolved absolute URL) or stop with
132
+ // a user-facing reason. Never throws.
133
+ export function resolveAllowedRedirect(fromUrl, location, hopsFollowed) {
134
+ if (hopsFollowed >= MAX_REDIRECT_HOPS) {
135
+ return { follow: false, reason: `too many redirects (limit ${MAX_REDIRECT_HOPS})` };
136
+ }
137
+ if (location === null || location.trim().length === 0) {
138
+ return { follow: false, reason: "redirect without a Location header" };
139
+ }
140
+ const next = resolveRedirectUrl(fromUrl, location);
141
+ if (next === null) {
142
+ const host = redirectTargetHost(fromUrl, location);
143
+ return {
144
+ follow: false,
145
+ reason: `redirect blocked (target not allowed${host ? `: ${host}` : ""})`,
146
+ };
147
+ }
148
+ return { follow: true, url: next.toString() };
149
+ }
150
+ export function isDisplayMode(value) {
151
+ return value === "sidebar" || value === "statusline" || value === "both";
152
+ }
153
+ export const DEFAULT_SIDEBAR_MODE = "integrated";
154
+ // Tolerant like `parseBooleanFlag`, because the same value reaches us from a
155
+ // hand-written env var and from typed JSON: null means "unset or unrecognized",
156
+ // and the caller keeps falling through to the next source.
157
+ export function parseSidebarMode(value) {
158
+ if (typeof value !== "string")
159
+ return null;
160
+ const normalized = value.trim().toLowerCase();
161
+ return normalized === "integrated" || normalized === "standalone" ? normalized : null;
162
+ }
163
+ export function providerIdFromModel(model) {
164
+ if (typeof model !== "string" || model.length === 0)
165
+ return undefined;
166
+ const provider = model.split("/")[0];
167
+ return provider !== undefined && provider.length > 0 ? provider : undefined;
168
+ }
169
+ export function resolveProviderId(state, sessionId, fallback) {
170
+ // The session's own model is the one in use, so it outranks the config default.
171
+ try {
172
+ const fromSession = state?.session?.get?.(sessionId)?.model?.providerID;
173
+ if (typeof fromSession === "string" && fromSession.length > 0)
174
+ return fromSession;
175
+ }
176
+ catch {
177
+ // Fall through: a throwing store is not a reason to hide the panel.
178
+ }
179
+ try {
180
+ const fromConfig = providerIdFromModel(state?.config?.model);
181
+ if (fromConfig !== undefined)
182
+ return fromConfig;
183
+ }
184
+ catch {
185
+ // Fall through to the event-signal fallback.
186
+ }
187
+ return fallback;
188
+ }
189
+ export function surfaceSelectionFromDisplayMode(mode) {
190
+ return { sidebar: mode !== "statusline", statusline: mode !== "sidebar" };
191
+ }
192
+ export function parseBooleanFlag(value) {
193
+ if (typeof value === "boolean")
194
+ return value;
195
+ if (typeof value === "number") {
196
+ if (value === 1)
197
+ return true;
198
+ if (value === 0)
199
+ return false;
200
+ return null;
201
+ }
202
+ if (typeof value !== "string")
203
+ return null;
204
+ const normalized = value.trim().toLowerCase();
205
+ if (normalized === "1" || normalized === "true")
206
+ return true;
207
+ if (normalized === "0" || normalized === "false")
208
+ return false;
209
+ return null;
210
+ }
211
+ export function isSnapshotEmpty(snapshot) {
212
+ return snapshot.rolling === null && snapshot.weekly === null && snapshot.monthly === null;
213
+ }
214
+ // Which window's countdown the plan is waiting on. One decision, read by the
215
+ // sidebar's reset line, by the per-row suffixes under a capped meter and by the
216
+ // statusline, so no two of them can name different windows.
217
+ //
218
+ // A capped window outranks a nearer one, and the longest cap outranks the
219
+ // shorter ones: an exhausted `30d` is what actually stops work, so a `5h` that
220
+ // rolls over in two hours is not the fact worth the cells. With nothing capped
221
+ // the soonest reset is the answer, because that is the first moment the
222
+ // percentages printed beside it will move.
223
+ //
224
+ // The capped case is read back out of `buildPlanRows` instead of re-deriving
225
+ // what "capped" means, so the statusline cannot drift from the sidebar. Only
226
+ // `resetInSec` is ever compared; a window that carries nothing but the host's
227
+ // free text can be printed once it has been chosen, never compared as a string.
228
+ export function relevantReset(snapshot) {
229
+ const rows = buildPlanRows(snapshot);
230
+ for (let i = rows.length - 1; i >= 0; i -= 1) {
231
+ const row = rows[i];
232
+ if (row?.reset != null)
233
+ return { label: row.label, text: row.reset };
234
+ }
235
+ return soonestReset(snapshot);
236
+ }
237
+ // The soonest reset across the windows, capped or not. A stale payload, clock
238
+ // skew or a reset that fired mid-flight can all send a negative span, and an
239
+ // elapsed countdown is as unusable as an unreadable one.
240
+ function soonestReset(snapshot) {
241
+ const windows = [
242
+ ["5h", snapshot.rolling],
243
+ ["7d", snapshot.weekly],
244
+ ["30d", snapshot.monthly],
245
+ ];
246
+ let soonest = null;
247
+ for (const [name, window] of windows) {
248
+ if (window === null)
249
+ continue;
250
+ const seconds = window.resetInSec;
251
+ if (typeof seconds !== "number" || !Number.isFinite(seconds) || seconds < 0)
252
+ continue;
253
+ if (soonest !== null && seconds >= soonest.seconds)
254
+ continue;
255
+ soonest = { label: name, seconds };
256
+ }
257
+ if (soonest === null)
258
+ return null;
259
+ const text = formatResetDuration(soonest.seconds);
260
+ return text === null ? null : { label: soonest.label, text };
261
+ }
262
+ export function formatStatusline(snapshot) {
263
+ const rolling = snapshot.rolling === null ? "5h n/a" : `5h ${snapshot.rolling.percent}%`;
264
+ const weekly = snapshot.weekly === null ? "7d n/a" : `7d ${snapshot.weekly.percent}%`;
265
+ const monthly = snapshot.monthly === null ? "30d n/a" : `30d ${snapshot.monthly.percent}%`;
266
+ const windows = `Go ${rolling} | ${weekly} | ${monthly}`;
267
+ // The same countdown the sidebar shows, without its window label: the
268
+ // percentages are right there in the same order, so naming the window again
269
+ // would spend cells restating what the line already says.
270
+ const reset = relevantReset(snapshot);
271
+ return reset === null ? windows : `${windows} · resets in ${reset.text}`;
272
+ }
273
+ const WARNING_PERCENT = 75;
274
+ const ERROR_PERCENT = 90;
275
+ // A capped window is a hard stop rather than a percentage: `limited` wins over
276
+ // whatever the gauge says, so a window that is capped at 3% still reads as error
277
+ // instead of reassuring the eye.
278
+ export function usageMeterSeverity(window) {
279
+ if (window.limited)
280
+ return "error";
281
+ return meterSeverityForPercent(window.percent);
282
+ }
283
+ // The threshold ladder on its own, so a gauge that is not backed by a plan
284
+ // window (the per-model Go share) colors by the same rules.
285
+ export function meterSeverityForPercent(percent) {
286
+ if (!Number.isFinite(percent))
287
+ return "muted";
288
+ if (percent >= ERROR_PERCENT)
289
+ return "error";
290
+ if (percent >= WARNING_PERCENT)
291
+ return "warning";
292
+ return "muted";
293
+ }
294
+ // The meter's filled fraction, clamped to 0-100: the API can report a percent
295
+ // outside the range and a NaN would be a layout error rather than a drawing one.
296
+ //
297
+ // The meter itself is TWO BOXES -- a filled one at this percentage and a track
298
+ // for the rest -- not a string of block glyphs. A glyph string has a fixed cell
299
+ // count, and a plugin cannot measure the sidebar it is rendering into (opentui
300
+ // resolves a text node's `width` as a wrapping bound, and no layout callback
301
+ // reaches a plugin), so a glyph meter is either too short for a wide sidebar or
302
+ // clipped by a narrow one. Boxes fill whatever the row gives them, which is why
303
+ // the meter now reaches the sidebar's right edge on any host and any width.
304
+ export function meterFillPercent(percent) {
305
+ if (!Number.isFinite(percent))
306
+ return 0;
307
+ return Math.min(Math.max(percent, 0), 100);
308
+ }
309
+ // `meterWidth` is the sidebar's budget, not the bar's design: 16 cells fit next
310
+ // to Kilo's model table, 10 fit opencode's ~30-cell sidebar. The glyphs and the
311
+ // saturating fill are identical, so two widths are the same bar at two sizes.
312
+ export function buildPlanRows(snapshot) {
313
+ const windows = [
314
+ ["5h", snapshot.rolling],
315
+ ["7d", snapshot.weekly],
316
+ ["30d", snapshot.monthly],
317
+ ];
318
+ const rows = [];
319
+ for (const [label, window] of windows) {
320
+ if (window === null)
321
+ continue;
322
+ rows.push({
323
+ label,
324
+ percent: window.percent,
325
+ severity: usageMeterSeverity(window),
326
+ // A countdown only tells the user something once the window is capped;
327
+ // before that the schedule is noise, and the header rows already show it.
328
+ reset: window.limited ? formatResetDuration(window.resetInSec) ?? window.resetText : null,
329
+ });
330
+ }
331
+ return rows;
332
+ }
333
+ // ---------------------------------------------------------------------------
334
+ // TUI: session model usage (the integrated panel's replacement for Kilo's own
335
+ // token-usage band)
336
+ // ---------------------------------------------------------------------------
337
+ //
338
+ // The host hands over raw counts and a USD cost with no display metadata, so
339
+ // every number crosses a formatter. The formatters below guard first: a bare
340
+ // `Intl.NumberFormat` prints NaN as "NaN" and Infinity as "∞", and either one
341
+ // silently stretches a sidebar column that is width-budgeted by the host.
342
+ const COUNT_FORMAT = new Intl.NumberFormat("en-US");
343
+ const CURRENCY_FORMAT = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" });
344
+ export function formatUsageCount(value) {
345
+ return COUNT_FORMAT.format(toUsageCount(value));
346
+ }
347
+ export function formatUsageCost(value) {
348
+ return CURRENCY_FORMAT.format(toUsageCount(value));
349
+ }
350
+ // Every bucket a token can land in. Cache is included because cached reads and
351
+ // writes are billed work too; excluding them would make the per-model totals
352
+ // disagree with the host's own `totals` row.
353
+ export function usageTokenCount(tokens) {
354
+ return (toUsageCount(tokens.input) +
355
+ toUsageCount(tokens.output) +
356
+ toUsageCount(tokens.reasoning) +
357
+ toUsageCount(tokens.cache.read) +
358
+ toUsageCount(tokens.cache.write));
359
+ }
360
+ // Kilo's cache rate: the read share of the three buckets a cache hit can be
361
+ // served from. Output and reasoning are excluded on purpose — neither can be
362
+ // cached, so counting them would deflate the rate towards a value that means
363
+ // nothing.
364
+ export function cacheRatePercent(tokens) {
365
+ const denominator = toUsageCount(tokens.input) + toUsageCount(tokens.cache.read) + toUsageCount(tokens.cache.write);
366
+ if (denominator === 0)
367
+ return CACHE_RATE_EMPTY;
368
+ return `${((toUsageCount(tokens.cache.read) / denominator) * 100).toFixed(CACHE_RATE_DECIMALS)}%`;
369
+ }
370
+ // A model's share of the Go tokens spent in this session tree. This is a share
371
+ // of Go tokens and nothing else: it is not a share of the plan, a quota, or a
372
+ // price, and it never carries a currency. A zero total is 0% rather than NaN so
373
+ // the row still renders before any Go tokens are attributed.
374
+ export function goSharePercent(modelTokens, totalGoTokens) {
375
+ const total = toUsageCount(totalGoTokens);
376
+ if (total === 0)
377
+ return 0;
378
+ return (toUsageCount(modelTokens) / total) * 100;
379
+ }
380
+ export function totalGoTokens(models) {
381
+ let total = 0;
382
+ for (const model of models) {
383
+ if (model.providerID !== GO_PROVIDER_ID)
384
+ continue;
385
+ total += usageTokenCount(model.tokens);
386
+ }
387
+ return total;
388
+ }
389
+ // Group in first-seen order (the host's own `models[]` order), which keeps the
390
+ // active provider on top. A provider with no catalog entry falls back to its
391
+ // raw id rather than dropping its models.
392
+ export function groupModelsByProvider(models, providerNames = new Map()) {
393
+ const groups = new Map();
394
+ for (const model of models) {
395
+ const group = groups.get(model.providerID) ?? {
396
+ providerID: model.providerID,
397
+ providerName: providerNames.get(model.providerID) ?? model.providerID,
398
+ models: [],
399
+ };
400
+ group.models.push(model);
401
+ groups.set(model.providerID, group);
402
+ }
403
+ return [...groups.values()];
404
+ }
405
+ // Kilo's truncation: a single ellipsis appended to a fixed-width budget, never
406
+ // a trailing "..." that would make the budget worth two extra cells.
407
+ export function truncateModelName(value, max = KILO_MODEL_NAME_MAX_CHARS) {
408
+ if (value.length <= max)
409
+ return value;
410
+ const budget = Math.max(max - 1, 0);
411
+ return `${value.slice(0, budget)}…`;
412
+ }
413
+ // Kilo's display normalization, applied before truncation: strip a `vendor:`
414
+ // prefix, a lone leading `vendor/`, and a trailing discount badge, then split a
415
+ // letter run that runs straight into digits. Without it a catalog name like
416
+ // "anthropic/claude-sonnet-4" spends the whole 19-cell budget on the vendor.
417
+ export function displayModelName(name) {
418
+ return name
419
+ .trim()
420
+ .replace(/^[^:]+:\s+/, "")
421
+ .replace(/^[^/\s]+\/(?=[^/]+$)/, "")
422
+ .replace(/\s*\([^)]*%\s*off[^)]*\)\s*$/i, "")
423
+ .replace(/^([A-Za-z]{2,})(?=\d)/, "$1 ")
424
+ .replace(/\s+/g, " ");
425
+ }
426
+ export function modelDisplayName(catalogName, modelID, max = KILO_MODEL_NAME_MAX_CHARS) {
427
+ const raw = toNonEmptyString(catalogName) ?? toNonEmptyString(modelID) ?? "";
428
+ return truncateModelName(displayModelName(raw), max);
429
+ }
430
+ // The first segment of a model name, for a mix line that has to fit several of
431
+ // them in one line: `mimo-v2.6-pro` -> `mimo`, `qwen3-max` -> `qwen3`, `gpt-5.1`
432
+ // -> `gpt`. A name with no separator is already short and is only truncated.
433
+ // Lowercased: the rest of the sidebar is lowercase, and the mix line is a
434
+ // ranking of three labels rather than three model names to copy out of.
435
+ export function shortModelName(value, max = GO_MODEL_MIX_NAME_MAX_CHARS) {
436
+ const trimmed = value.trim().toLowerCase();
437
+ if (trimmed.length === 0)
438
+ return "";
439
+ const head = trimmed.split(/[-._/]/)[0] ?? trimmed;
440
+ return truncateModelName(head, max);
441
+ }
442
+ // The plan window label cell ("5h", "7d", "30d"): exactly the longest label the
443
+ // plan has, so every meter starts on the same column and none of the width goes
444
+ // to padding.
445
+ export const PLAN_LABEL_WIDTH = 3;
446
+ // A percent padded into a fixed-width cell, right-aligned by construction. A
447
+ // non-finite percent renders as 0 rather than "NaN%", which would break the
448
+ // column it sits in.
449
+ export function formatPercentCell(percent, width = PERCENT_CELL_WIDTH) {
450
+ const cells = Math.max(Math.floor(width), 1);
451
+ const rounded = Number.isFinite(percent) ? Math.round(percent) : 0;
452
+ return `${`${rounded}%`}`.padStart(cells, " ");
453
+ }
454
+ // A token count as a weight, not an invoice: short enough to sit next to a bar
455
+ // in a 30-cell sidebar, precise enough to rank models. `610K` rather than
456
+ // `0.61M` — below a million the integer form is both shorter and the one people
457
+ // say out loud.
458
+ export function formatTokenCount(value) {
459
+ const count = toUsageCount(value);
460
+ if (count >= 1_000_000_000)
461
+ return `${trimTrailingZeros((count / 1_000_000_000).toFixed(2))}B`;
462
+ if (count >= 1_000_000)
463
+ return `${trimTrailingZeros((count / 1_000_000).toFixed(2))}M`;
464
+ if (count >= 1_000)
465
+ return `${Math.round(count / 1_000)}K`;
466
+ return COUNT_FORMAT.format(count);
467
+ }
468
+ // `1.20M` claims a precision the API never had, and spends a cell on it. Only
469
+ // `toFixed` output goes through this, which always carries a decimal point -- so
470
+ // the trailing zeros it strips are always fractional ones, never `100`.
471
+ function trimTrailingZeros(value) {
472
+ return value.replace(/\.?0+$/, "");
473
+ }
474
+ // The heaviest Go models by token count. Ties break on steps and then on the
475
+ // model id, so the same session always ranks the same way — a list that reshuffles
476
+ // between renders would make the weights unreadable. `otherCount` counts the
477
+ // models the limit dropped, and `goTokens`/`steps`/`cost` cover all of them.
478
+ export function weightGoModels(models, limit = TOP_GO_MODELS_LIMIT) {
479
+ const goModels = models.filter((model) => model.providerID === GO_PROVIDER_ID);
480
+ const goTokens = goModels.reduce((sum, model) => sum + usageTokenCount(model.tokens), 0);
481
+ const ranked = [...goModels].sort((left, right) => usageTokenCount(right.tokens) - usageTokenCount(left.tokens) ||
482
+ toUsageCount(right.steps) - toUsageCount(left.steps) ||
483
+ left.modelID.localeCompare(right.modelID));
484
+ const top = ranked.slice(0, Math.max(Math.floor(limit), 0));
485
+ const listedTokens = top.reduce((sum, model) => sum + usageTokenCount(model.tokens), 0);
486
+ return {
487
+ models: top.map((model) => {
488
+ const tokens = usageTokenCount(model.tokens);
489
+ const share = goSharePercent(tokens, goTokens);
490
+ return {
491
+ providerID: model.providerID,
492
+ modelID: model.modelID,
493
+ tokens,
494
+ share,
495
+ steps: toUsageCount(model.steps),
496
+ cost: toUsageCount(model.cost),
497
+ };
498
+ }),
499
+ goModels: goModels.length,
500
+ goTokens,
501
+ listedTokens,
502
+ listedShare: goSharePercent(listedTokens, goTokens),
503
+ otherCount: Math.max(goModels.length - top.length, 0),
504
+ steps: goModels.reduce((sum, model) => sum + toUsageCount(model.steps), 0),
505
+ cost: goModels.reduce((sum, model) => sum + toUsageCount(model.cost), 0),
506
+ };
507
+ }
508
+ // The collapsed mix line: `mimo 59%·qwen 25%·gpt 12%`, as many entries as fit
509
+ // `budget` cells. Built cell by cell rather than joined from a fixed list because
510
+ // a narrow sidebar truncates mid-entry, and a half-written `qwen 2…` reads as a
511
+ // different number than `qwen 25%`.
512
+ //
513
+ // The leader is always included even when it alone overruns the budget: a mix
514
+ // line without the heaviest model is not a summary of anything, and the entry
515
+ // cannot actually be that wide because the names are capped (see
516
+ // `shortModelName`), so the budget only ever decides the second entry onwards.
517
+ export function buildModelMixSummary(entries, budget = GO_MODEL_MIX_BUDGET) {
518
+ const first = entries[0];
519
+ if (first === undefined)
520
+ return "";
521
+ const parts = [];
522
+ let used = 0;
523
+ for (const entry of entries) {
524
+ const part = `${entry.name} ${Math.round(entry.share)}%`;
525
+ const width = part.length + (parts.length === 0 ? 0 : GO_MODEL_MIX_SEPARATOR.length);
526
+ if (parts.length > 0 && used + width > budget)
527
+ break;
528
+ parts.push(part);
529
+ used += width;
530
+ }
531
+ return parts.join(GO_MODEL_MIX_SEPARATOR);
532
+ }
533
+ // Two muted lines under the rows: what the listed models account for, and the
534
+ // session's own Go totals. Both are counts of this session's tokens and cost —
535
+ // never of the plan.
536
+ export function buildGoModelFooters(weights) {
537
+ if (weights.models.length === 0)
538
+ return [];
539
+ return [
540
+ `${formatTokenCount(weights.listedTokens)} of ${formatTokenCount(weights.goTokens)} Go tokens`,
541
+ `${formatUsageCount(weights.steps)} steps · ${formatUsageCost(weights.cost)}`,
542
+ ];
543
+ }
544
+ // One row per entry of KILO_TOKEN_USAGE_ROWS, in that order. A label with no
545
+ // value is dropped rather than rendered blank, so the row list and the constant
546
+ // can only disagree in a way the unit tier fails on.
547
+ export function buildTokenUsageRows(totals) {
548
+ const values = {
549
+ Input: formatUsageCount(totals.tokens.input),
550
+ Output: formatUsageCount(totals.tokens.output),
551
+ Reasoning: formatUsageCount(totals.tokens.reasoning),
552
+ "Cache read": formatUsageCount(totals.tokens.cache.read),
553
+ "Cache write": formatUsageCount(totals.tokens.cache.write),
554
+ "Cache rate": cacheRatePercent(totals.tokens),
555
+ Cost: formatUsageCost(totals.cost),
556
+ };
557
+ return KILO_TOKEN_USAGE_ROWS.flatMap((label) => {
558
+ const value = values[label];
559
+ return value === undefined ? [] : [{ label, value }];
560
+ });
561
+ }
562
+ // The per-model token breakdown shown when a model row is expanded: the same
563
+ // labels and order as the totals block, minus `Cost`, which the model row
564
+ // already carries in its own cost column.
565
+ export function buildModelTokenRows(tokens) {
566
+ return buildTokenUsageRows({ cost: 0, tokens }).filter((row) => row.label !== "Cost");
567
+ }
568
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,11 +1,7 @@
1
- declare const _default: () => Promise<{
2
- tool: {
3
- go_usage: {
4
- description: string;
5
- args: {};
6
- execute(args: Record<string, never>, context: import("@opencode-ai/plugin").ToolContext): Promise<import("@opencode-ai/plugin").ToolResult>;
7
- };
8
- };
9
- }>;
1
+ import type { Plugin } from "@opencode-ai/plugin";
2
+ declare const _default: {
3
+ id: string;
4
+ server: Plugin;
5
+ };
10
6
  export default _default;
11
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;AAoiBA,wBAiBoB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAS,MAAM,EAAgB,MAAM,qBAAqB,CAAC;;;;;AA6iBvE,wBAA4E"}