@jeffreyjyz/opencode-command-code 0.5.0 → 0.5.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/dist/index.js +1 -1
- package/dist/sidebar/rows.d.ts +18 -0
- package/dist/sidebar/zen.d.ts +12 -3
- package/dist/tui.js +56 -35
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2414,7 +2414,7 @@ function superRefine(fn) {
|
|
|
2414
2414
|
// package.json
|
|
2415
2415
|
var package_default = {
|
|
2416
2416
|
name: "@jeffreyjyz/opencode-command-code",
|
|
2417
|
-
version: "0.5.
|
|
2417
|
+
version: "0.5.1",
|
|
2418
2418
|
description: "Command Code provider + usage dashboard for opencode: two providers (Anthropic wire for Claude, OpenAI wire for everything else) against api.commandcode.ai, live model list, plan gating, /cmd-usage. Requires the cmduse CLI for usage rendering.",
|
|
2419
2419
|
type: "module",
|
|
2420
2420
|
main: "dist/index.js",
|
package/dist/sidebar/rows.d.ts
CHANGED
|
@@ -130,6 +130,24 @@ export declare function rate(value: number): string;
|
|
|
130
130
|
export declare function count(value: number): string;
|
|
131
131
|
/** "3h 12m" / "1d 20h" / "<1m" for a reset epoch. */
|
|
132
132
|
export declare function until(epoch: number | undefined, now?: number): string;
|
|
133
|
+
/** A rolling window as two or three rows: the use line, then resets plus whatever
|
|
134
|
+
* needs flagging, then an optional `extra` continuation. The lead segment follows
|
|
135
|
+
* cmduse's importance order — over-cap flag, then the cap ETA, then the
|
|
136
|
+
* informational elapsed share — because the 37-column budget fits exactly one of
|
|
137
|
+
* them beside the reset countdown.
|
|
138
|
+
*
|
|
139
|
+
* Shared by both panels: CommandCode passes four arguments (output unchanged),
|
|
140
|
+
* the OpenCode Go/Zen side adds the window's request count as `extra`, so
|
|
141
|
+
* `LIMIT EXCEEDED`, the tone, `cap in …`, `elapsed` and `resets` all have one
|
|
142
|
+
* implementation. */
|
|
143
|
+
export declare function windowRows(label: string, w: WindowUsage | undefined, now: number, durSecs: number, extra?: string): SidebarRow[];
|
|
144
|
+
/**
|
|
145
|
+
* The two store-backed rows for the active model — its requests under `Usage
|
|
146
|
+
* (this model)`, then this conversation's own totals under `Session`. They need
|
|
147
|
+
* no network, so both panels keep them when the catalog is missing, and both
|
|
148
|
+
* families build them here rather than in two places.
|
|
149
|
+
*/
|
|
150
|
+
export declare function localUsageRows(usage?: ModelUsage, session?: ModelUsage): SidebarRow[];
|
|
133
151
|
/** Plan + rolling windows + period totals, from a cmduse snapshot. */
|
|
134
152
|
export declare function usageRows(usage: Usage | undefined, now?: number): SidebarRow[];
|
|
135
153
|
/** Active model's allowance, rates and benchmarks, from mpc's catalog; its
|
package/dist/sidebar/zen.d.ts
CHANGED
|
@@ -14,7 +14,15 @@ export interface ZenModel {
|
|
|
14
14
|
month: ZenTotals;
|
|
15
15
|
}
|
|
16
16
|
export interface ZenUsage {
|
|
17
|
+
/**
|
|
18
|
+
* Billing period start, epoch ms: `periodStart` on current ocuse, or
|
|
19
|
+
* `periodStartAt` once it publishes the bounds (the same instants cmduse
|
|
20
|
+
* 0.7.2+ carries).
|
|
21
|
+
*/
|
|
17
22
|
periodStart?: number;
|
|
23
|
+
/** Billing period end, epoch ms. Optional: older ocuse does not publish it
|
|
24
|
+
* and the Monthly row must then degrade to spend alone. */
|
|
25
|
+
periodEndAt?: number;
|
|
18
26
|
source?: string;
|
|
19
27
|
totals: {
|
|
20
28
|
fiveHour: ZenTotals;
|
|
@@ -28,6 +36,7 @@ export interface ZenUsage {
|
|
|
28
36
|
export declare function parseZenJson(text: string): ZenUsage;
|
|
29
37
|
/** The OpenCode Go / Zen panel: period windows, a rule, then the active model.
|
|
30
38
|
* Like `modelRows`, `fallbackName` (the session's own id) keeps the model block
|
|
31
|
-
* — and the local `
|
|
32
|
-
* unreachable; only the catalog-derived rows
|
|
33
|
-
|
|
39
|
+
* — and the local `Usage (this model)` / `Session` figures, which need no network
|
|
40
|
+
* — on screen when mpc's catalog is unreachable; only the catalog-derived rows
|
|
41
|
+
* then drop out. */
|
|
42
|
+
export declare function zenRows(usage: ZenUsage | undefined, meta: ModelMeta | undefined, modelUsage?: ModelUsage, session?: ModelUsage, fallbackName?: string): SidebarRow[];
|
package/dist/tui.js
CHANGED
|
@@ -621,7 +621,7 @@ function until(epoch, now = Date.now()) {
|
|
|
621
621
|
const days = Math.floor(hours / 24);
|
|
622
622
|
return hours % 24 ? `${days}d ${hours % 24}h` : `${days}d`;
|
|
623
623
|
}
|
|
624
|
-
function windowRows(label, w, now, durSecs) {
|
|
624
|
+
function windowRows(label, w, now, durSecs, extra) {
|
|
625
625
|
if (!w || typeof w.cap !== "number" || w.cap <= 0)
|
|
626
626
|
return [];
|
|
627
627
|
const used = typeof w.used === "number" ? w.used : 0;
|
|
@@ -632,7 +632,23 @@ function windowRows(label, w, now, durSecs) {
|
|
|
632
632
|
const reset = until(w.resetAt, now);
|
|
633
633
|
const lead = w.exceeded ? "LIMIT EXCEEDED" : eta === undefined ? elapsed === undefined ? "" : `${elapsed} elapsed` : `cap in ${until(now + eta * 1000, now)}`;
|
|
634
634
|
const detail = [lead, reset ? `resets ${reset}` : ""].filter(Boolean).join(" \xB7 ");
|
|
635
|
-
return [[label, `${money(used)}/${money(w.cap)} (${pct.toFixed(1)}%)`, w.exceeded ? "crit" : pctTone(pct)], ...detail ? [["", detail, "muted"]] : []];
|
|
635
|
+
return [[label, `${money(used)}/${money(w.cap)} (${pct.toFixed(1)}%)`, w.exceeded ? "crit" : pctTone(pct)], ...detail ? [["", detail, "muted"]] : [], ...extra ? [["", extra, "muted"]] : []];
|
|
636
|
+
}
|
|
637
|
+
function localUsageRows(usage, session) {
|
|
638
|
+
const rows = [];
|
|
639
|
+
if (usage) {
|
|
640
|
+
rows.push(["Usage (this model)", `${count(usage.requests)} req`, "base"]);
|
|
641
|
+
const spend = usage.cost > 0 ? money(usage.cost) : "";
|
|
642
|
+
const share = usage.cost > 0 && session && session.cost > 0 ? `${Math.min(100, Math.round(usage.cost / session.cost * 100))}% of session` : "";
|
|
643
|
+
const detail = [spend, share].filter(Boolean).join(" \xB7 ");
|
|
644
|
+
if (detail)
|
|
645
|
+
rows.push(["", detail, "muted"]);
|
|
646
|
+
}
|
|
647
|
+
if (session) {
|
|
648
|
+
const spent = session.cost > 0 ? ` \xB7 ${money(session.cost)}` : "";
|
|
649
|
+
rows.push(["Session", `${count(session.requests)} req${spent}`, "base"]);
|
|
650
|
+
}
|
|
651
|
+
return rows;
|
|
636
652
|
}
|
|
637
653
|
function monthlyDetail(usage, now) {
|
|
638
654
|
const {
|
|
@@ -681,19 +697,7 @@ function modelRows(meta, usage, session, fallbackName) {
|
|
|
681
697
|
const name = meta?.name ?? fallbackName;
|
|
682
698
|
if (!name)
|
|
683
699
|
return [];
|
|
684
|
-
const rows = [["Model", clip(name, valueWidth("Model")), "strong", true]];
|
|
685
|
-
if (usage) {
|
|
686
|
-
rows.push(["Usage (this model)", `${count(usage.requests)} req`, "base"]);
|
|
687
|
-
const spend = usage.cost > 0 ? money(usage.cost) : "";
|
|
688
|
-
const share = usage.cost > 0 && session && session.cost > 0 ? `${Math.min(100, Math.round(usage.cost / session.cost * 100))}% of session` : "";
|
|
689
|
-
const detail = [spend, share].filter(Boolean).join(" \xB7 ");
|
|
690
|
-
if (detail)
|
|
691
|
-
rows.push(["", detail, "muted"]);
|
|
692
|
-
}
|
|
693
|
-
if (session) {
|
|
694
|
-
const spent = session.cost > 0 ? ` \xB7 ${money(session.cost)}` : "";
|
|
695
|
-
rows.push(["Session", `${count(session.requests)} req${spent}`, "base"]);
|
|
696
|
-
}
|
|
700
|
+
const rows = [["Model", clip(name, valueWidth("Model")), "strong", true], ...localUsageRows(usage, session)];
|
|
697
701
|
if (!meta)
|
|
698
702
|
return rows;
|
|
699
703
|
if (meta.tier)
|
|
@@ -2060,7 +2064,8 @@ function parseZenJson(text) {
|
|
|
2060
2064
|
}
|
|
2061
2065
|
const top = body.totals ?? {};
|
|
2062
2066
|
return {
|
|
2063
|
-
periodStart: typeof body.periodStart === "number" ? body.periodStart : undefined,
|
|
2067
|
+
periodStart: typeof body.periodStartAt === "number" ? body.periodStartAt : typeof body.periodStart === "number" ? body.periodStart : undefined,
|
|
2068
|
+
periodEndAt: typeof body.periodEndAt === "number" ? body.periodEndAt : undefined,
|
|
2064
2069
|
source: typeof body.source === "string" ? body.source : undefined,
|
|
2065
2070
|
totals: {
|
|
2066
2071
|
fiveHour: totals(top.fiveHour),
|
|
@@ -2070,38 +2075,53 @@ function parseZenJson(text) {
|
|
|
2070
2075
|
models
|
|
2071
2076
|
};
|
|
2072
2077
|
}
|
|
2073
|
-
function
|
|
2074
|
-
|
|
2078
|
+
function monthPeriod(usage) {
|
|
2079
|
+
const {
|
|
2080
|
+
periodStart,
|
|
2081
|
+
periodEndAt
|
|
2082
|
+
} = usage;
|
|
2083
|
+
if (typeof periodStart !== "number" || typeof periodEndAt !== "number")
|
|
2084
|
+
return;
|
|
2085
|
+
const durSecs = Math.round((periodEndAt - periodStart) / 1000);
|
|
2086
|
+
if (durSecs <= 0)
|
|
2087
|
+
return;
|
|
2088
|
+
return {
|
|
2089
|
+
resetAt: periodEndAt,
|
|
2090
|
+
durSecs
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
function zenWindow(label, spent, limit, share, now, durSecs, resetAt) {
|
|
2094
|
+
const cap = typeof limit === "number" && limit > 0 ? limit * share : undefined;
|
|
2095
|
+
if (cap === undefined) {
|
|
2075
2096
|
return [[label, `${money(spent.cost)} \xB7 ${count(spent.requests)} req`, "base"]];
|
|
2076
2097
|
}
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
}
|
|
2084
|
-
function zenRows(usage, meta, session, fallbackName) {
|
|
2098
|
+
return windowRows(label, {
|
|
2099
|
+
cap,
|
|
2100
|
+
used: spent.cost,
|
|
2101
|
+
resetAt,
|
|
2102
|
+
exceeded: spent.cost >= cap
|
|
2103
|
+
}, now, durSecs, spent.requests > 0 ? `${count(spent.requests)} req` : undefined);
|
|
2104
|
+
}
|
|
2105
|
+
function zenRows(usage, meta, modelUsage, session, fallbackName) {
|
|
2085
2106
|
if (!usage)
|
|
2086
2107
|
return [];
|
|
2108
|
+
const now = Date.now();
|
|
2087
2109
|
const oc = meta?.oc;
|
|
2088
2110
|
const rows = [["Plan", `${oc?.plan ?? "Go"} \xB7 limits per model`, "base"]];
|
|
2089
2111
|
const mine = meta ? usage.models.get(modelKey(meta.name)) : undefined;
|
|
2090
2112
|
const limit = oc?.allowance ?? mine?.limit;
|
|
2091
2113
|
const cap = mine ? limit : undefined;
|
|
2092
|
-
rows.push(...
|
|
2093
|
-
rows.push(...
|
|
2094
|
-
|
|
2114
|
+
rows.push(...zenWindow("5-hour", mine?.fiveHour ?? usage.totals.fiveHour, cap, GO_WINDOW_SHARE.fiveHour, now, FIVE_HOUR_SECS));
|
|
2115
|
+
rows.push(...zenWindow("Weekly", mine?.weekly ?? usage.totals.weekly, cap, GO_WINDOW_SHARE.weekly, now, WEEKLY_SECS));
|
|
2116
|
+
const period = monthPeriod(usage);
|
|
2117
|
+
rows.push(...zenWindow("Monthly", mine?.month ?? usage.totals.month, cap, GO_WINDOW_SHARE.month, now, period?.durSecs ?? 0, period?.resetAt));
|
|
2095
2118
|
rows.push(["Period", `${count(usage.totals.month.requests)} requests \xB7 ${money(usage.totals.month.cost)}`, "base"]);
|
|
2096
2119
|
rows.push(separator());
|
|
2097
2120
|
const name = meta?.name ?? fallbackName;
|
|
2098
2121
|
if (!name)
|
|
2099
2122
|
return rows;
|
|
2100
2123
|
rows.push(["Model", clip(name, valueWidth("Model")), "strong", true]);
|
|
2101
|
-
|
|
2102
|
-
const spent = session.cost > 0 ? ` \xB7 ${money(session.cost)}` : "";
|
|
2103
|
-
rows.push(["Session", `${count(session.requests)} req${spent}`, "base"]);
|
|
2104
|
-
}
|
|
2124
|
+
rows.push(...localUsageRows(modelUsage, session));
|
|
2105
2125
|
if (!meta)
|
|
2106
2126
|
return rows;
|
|
2107
2127
|
if (typeof limit === "number") {
|
|
@@ -2503,6 +2523,7 @@ function useRows(activeModelId, providerID, sessionID) {
|
|
|
2503
2523
|
refreshModelUsage(activeModelId());
|
|
2504
2524
|
} else if (kind === "go" || kind === "zen") {
|
|
2505
2525
|
setZen(await loadZen(loadPrefs().ocPlan));
|
|
2526
|
+
refreshModelUsage(activeModelId());
|
|
2506
2527
|
}
|
|
2507
2528
|
} catch {} finally {
|
|
2508
2529
|
inFlight = false;
|
|
@@ -2520,7 +2541,7 @@ function useRows(activeModelId, providerID, sessionID) {
|
|
|
2520
2541
|
createEffect(() => {
|
|
2521
2542
|
const id = activeModelId();
|
|
2522
2543
|
const session = sessionID();
|
|
2523
|
-
if (sessionKind(providerID())
|
|
2544
|
+
if (!shows(sessionKind(providerID())) || !id || !session)
|
|
2524
2545
|
return;
|
|
2525
2546
|
refreshModelUsage(id);
|
|
2526
2547
|
});
|
|
@@ -2540,7 +2561,7 @@ function useRows(activeModelId, providerID, sessionID) {
|
|
|
2540
2561
|
const found = id ? meta().get(modelKey(id)) ?? meta().get(id) : undefined;
|
|
2541
2562
|
const fallbackName = id ? id.split("/").pop() ?? id : undefined;
|
|
2542
2563
|
if (kind === "go" || kind === "zen") {
|
|
2543
|
-
return zenRows(zen(), found, sessionUsage(), fallbackName);
|
|
2564
|
+
return zenRows(zen(), found, usageFor(id), sessionUsage(), fallbackName);
|
|
2544
2565
|
}
|
|
2545
2566
|
const model = found ? {
|
|
2546
2567
|
...found,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jeffreyjyz/opencode-command-code",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Command Code provider + usage dashboard for opencode: two providers (Anthropic wire for Claude, OpenAI wire for everything else) against api.commandcode.ai, live model list, plan gating, /cmd-usage. Requires the cmduse CLI for usage rendering.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|