@jeffreyjyz/opencode-command-code 0.3.13 → 0.3.15
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 +933 -220
- package/dist/sidebar/rows.d.ts +8 -0
- package/dist/sidebar/windows.d.ts +4 -3
- package/dist/tui.js +38 -17
- package/package.json +1 -1
package/dist/sidebar/rows.d.ts
CHANGED
|
@@ -51,6 +51,14 @@ export interface ModelMeta {
|
|
|
51
51
|
};
|
|
52
52
|
intelligence?: number;
|
|
53
53
|
tps?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Promotion CommandCode is running on this model (0.3.13): the badge from
|
|
56
|
+
* the docs row, with its expiry line when the page publishes one.
|
|
57
|
+
*/
|
|
58
|
+
deal?: {
|
|
59
|
+
badge: string;
|
|
60
|
+
ends?: string;
|
|
61
|
+
};
|
|
54
62
|
/**
|
|
55
63
|
* The OpenCode Go / Zen side of the same mpc row (0.4.0): the CommandCode
|
|
56
64
|
* fields above are the default, this is what a Go/Zen session reads.
|
|
@@ -9,9 +9,10 @@ export declare const WEEKLY_SECS: number;
|
|
|
9
9
|
*/
|
|
10
10
|
export declare function elapsedPct(resetAtMs: number | undefined, durSecs: number, nowSecs: number): number | undefined;
|
|
11
11
|
/**
|
|
12
|
-
* `elapsedPct` as text: a seven-day window forty minutes in is
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* `elapsedPct` as text, one decimal: a seven-day window forty minutes in is
|
|
13
|
+
* "0.4%". Only a fraction too small to show at one decimal (<0.05%) reads
|
|
14
|
+
* "<0.1%", so a just-started window is not mistaken for an unstarted one.
|
|
15
|
+
* Exact zero stays "0.0%".
|
|
15
16
|
*/
|
|
16
17
|
export declare function elapsedLabel(resetAtMs: number | undefined, durSecs: number, nowSecs: number): string | undefined;
|
|
17
18
|
/**
|
package/dist/tui.js
CHANGED
|
@@ -458,15 +458,15 @@ function elapsedPct(resetAtMs, durSecs, nowSecs) {
|
|
|
458
458
|
if (nowSecs < start)
|
|
459
459
|
return;
|
|
460
460
|
const pct = (nowSecs - start) / durSecs * 100;
|
|
461
|
-
return Math.round(Math.min(100, Math.max(0, pct)));
|
|
461
|
+
return Math.round(Math.min(100, Math.max(0, pct)) * 10) / 10;
|
|
462
462
|
}
|
|
463
463
|
function elapsedLabel(resetAtMs, durSecs, nowSecs) {
|
|
464
464
|
const pct = elapsedPct(resetAtMs, durSecs, nowSecs);
|
|
465
465
|
if (pct === undefined)
|
|
466
466
|
return;
|
|
467
467
|
if (pct === 0 && nowSecs > Math.floor(resetAtMs / 1000) - durSecs)
|
|
468
|
-
return "<1%";
|
|
469
|
-
return `${pct}%`;
|
|
468
|
+
return "<0.1%";
|
|
469
|
+
return `${pct.toFixed(1)}%`;
|
|
470
470
|
}
|
|
471
471
|
function paceEtaSecs(resetAtMs, durSecs, used, cap, nowSecs) {
|
|
472
472
|
if (typeof resetAtMs !== "number" || !Number.isFinite(resetAtMs))
|
|
@@ -551,14 +551,14 @@ function windowRows(label, w, now, durSecs) {
|
|
|
551
551
|
if (!w || typeof w.cap !== "number" || w.cap <= 0)
|
|
552
552
|
return [];
|
|
553
553
|
const used = typeof w.used === "number" ? w.used : 0;
|
|
554
|
-
const pct =
|
|
554
|
+
const pct = used / w.cap * 100;
|
|
555
555
|
const nowSecs = Math.floor(now / 1000);
|
|
556
556
|
const elapsed = elapsedLabel(w.resetAt, durSecs, nowSecs);
|
|
557
557
|
const eta = paceEtaSecs(w.resetAt, durSecs, used, w.cap, nowSecs);
|
|
558
558
|
const reset = until(w.resetAt, now);
|
|
559
559
|
const lead = w.exceeded ? "LIMIT EXCEEDED" : eta === undefined ? elapsed === undefined ? "" : `${elapsed} elapsed` : `cap in ${until(now + eta * 1000, now)}`;
|
|
560
560
|
const detail = [lead, reset ? `resets ${reset}` : ""].filter(Boolean).join(" \xB7 ");
|
|
561
|
-
return [[label, `${money(used)}/${money(w.cap)} (${pct}%)`, w.exceeded ? "crit" : pctTone(pct)], ...detail ? [["", detail, "muted"]] : []];
|
|
561
|
+
return [[label, `${money(used)}/${money(w.cap)} (${pct.toFixed(1)}%)`, w.exceeded ? "crit" : pctTone(pct)], ...detail ? [["", detail, "muted"]] : []];
|
|
562
562
|
}
|
|
563
563
|
function monthlyDetail(usage, now) {
|
|
564
564
|
const {
|
|
@@ -585,8 +585,8 @@ function usageRows(usage, now = Date.now()) {
|
|
|
585
585
|
}
|
|
586
586
|
if (typeof usage.monthlyCap === "number" && typeof usage.monthlyCredits === "number") {
|
|
587
587
|
const used = Math.min(usage.monthlyCap, Math.max(0, usage.monthlyCap - usage.monthlyCredits));
|
|
588
|
-
const pct = usage.monthlyCap > 0 ?
|
|
589
|
-
rows.push(["Monthly", `${money(used)} / ${money(usage.monthlyCap)} (${pct}%)`, pctTone(pct)]);
|
|
588
|
+
const pct = usage.monthlyCap > 0 ? used / usage.monthlyCap * 100 : 0;
|
|
589
|
+
rows.push(["Monthly", `${money(used)} / ${money(usage.monthlyCap)} (${pct.toFixed(1)}%)`, pctTone(pct)]);
|
|
590
590
|
const detail = monthlyDetail(usage, now);
|
|
591
591
|
if (detail)
|
|
592
592
|
rows.push(["", detail, "muted"]);
|
|
@@ -608,8 +608,12 @@ function modelRows(meta, usage, session) {
|
|
|
608
608
|
return [];
|
|
609
609
|
const rows = [["Model", clip(meta.name, valueWidth("Model")), "strong", true]];
|
|
610
610
|
if (usage) {
|
|
611
|
-
|
|
612
|
-
|
|
611
|
+
rows.push(["Usage (this model)", `${count(usage.requests)} req`, "base"]);
|
|
612
|
+
const spend = usage.cost > 0 ? money(usage.cost) : "";
|
|
613
|
+
const share = usage.cost > 0 && session && session.cost > 0 ? `${Math.round(usage.cost / session.cost * 100)}% of session` : "";
|
|
614
|
+
const detail = [spend, share].filter(Boolean).join(" \xB7 ");
|
|
615
|
+
if (detail)
|
|
616
|
+
rows.push(["", detail, "muted"]);
|
|
613
617
|
}
|
|
614
618
|
if (session) {
|
|
615
619
|
const spent = session.cost > 0 ? ` \xB7 ${money(session.cost)}` : "";
|
|
@@ -621,6 +625,10 @@ function modelRows(meta, usage, session) {
|
|
|
621
625
|
rows.push(["Min plan", meta.minPlan, "base"]);
|
|
622
626
|
if (typeof meta.allowance === "number")
|
|
623
627
|
rows.push(["Allowance", `${money(meta.allowance)}/mo`, "base"]);
|
|
628
|
+
if (meta.deal) {
|
|
629
|
+
const ends = meta.deal.ends?.match(/([A-Z][a-z]{2})[a-z]*\s+(\d{1,2})/);
|
|
630
|
+
rows.push(["Deal", ends ? `${meta.deal.badge} \xB7 ends ${ends[1]} ${ends[2]}` : meta.deal.badge, "ok"]);
|
|
631
|
+
}
|
|
624
632
|
if (meta.rates) {
|
|
625
633
|
const cache = [`cache read ${rate(meta.rates.cacheRead)}`];
|
|
626
634
|
if (typeof meta.rates.cacheWrite === "number" && meta.rates.cacheWrite > 0) {
|
|
@@ -1913,8 +1921,8 @@ function windowRows2(label, spent, limit, share) {
|
|
|
1913
1921
|
return [[label, `${money(spent.cost)} \xB7 ${count(spent.requests)} req`, "base"]];
|
|
1914
1922
|
}
|
|
1915
1923
|
const cap = limit * share;
|
|
1916
|
-
const pct = cap > 0 ?
|
|
1917
|
-
const rows = [[label, `${money(spent.cost)}/${money(cap)} (${pct}%)`, pctTone(pct)]];
|
|
1924
|
+
const pct = cap > 0 ? spent.cost / cap * 100 : 0;
|
|
1925
|
+
const rows = [[label, `${money(spent.cost)}/${money(cap)} (${pct.toFixed(1)}%)`, pctTone(pct)]];
|
|
1918
1926
|
if (spent.requests > 0)
|
|
1919
1927
|
rows.push(["", `${count(spent.requests)} req`, "muted"]);
|
|
1920
1928
|
return rows;
|
|
@@ -1961,7 +1969,7 @@ function zenRows(usage, meta, session) {
|
|
|
1961
1969
|
var CMDUSE = cmduseCandidates();
|
|
1962
1970
|
var MPC = ["mpc", join2(homedir2(), ".bun/bin/mpc"), "/opt/homebrew/bin/mpc"];
|
|
1963
1971
|
var OCUSE = [process.env.OCUSE_BIN, "ocuse", "/opt/homebrew/bin/ocuse", "/usr/local/bin/ocuse"].filter((bin) => Boolean(bin));
|
|
1964
|
-
var CACHE_TTL_MS =
|
|
1972
|
+
var CACHE_TTL_MS = 60 * 60 * 1000;
|
|
1965
1973
|
var SPAWN_OPTIONS = {
|
|
1966
1974
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1967
1975
|
detached: true
|
|
@@ -2032,6 +2040,10 @@ function parseMpcJson(text) {
|
|
|
2032
2040
|
rates: cc?.pricing,
|
|
2033
2041
|
intelligence: cc?.ability ?? undefined,
|
|
2034
2042
|
tps: cc?.tps ?? undefined,
|
|
2043
|
+
deal: cc?.deal?.badge !== undefined ? {
|
|
2044
|
+
badge: cc.deal.badge,
|
|
2045
|
+
ends: cc.deal.ends
|
|
2046
|
+
} : undefined,
|
|
2035
2047
|
oc: oc ? {
|
|
2036
2048
|
provider: oc.provider,
|
|
2037
2049
|
plan: oc.plan,
|
|
@@ -2105,20 +2117,25 @@ function loadModelUsage(modelID, sinceMs, path = usageDbPath(), sessionID) {
|
|
|
2105
2117
|
}
|
|
2106
2118
|
try {
|
|
2107
2119
|
if (hasV2(db)) {
|
|
2108
|
-
const rows = db.query(`SELECT json_extract(data, '$.model.id') AS model,
|
|
2120
|
+
const rows = db.query(`SELECT json_extract(data, '$.model.id') AS model,
|
|
2121
|
+
count(*) AS c,
|
|
2122
|
+
coalesce(sum(json_extract(data, '$.cost')), 0) AS cost
|
|
2109
2123
|
FROM session_message
|
|
2110
2124
|
WHERE type = 'assistant'
|
|
2111
2125
|
${sessionID ? "AND session_id = ?" : "AND time_created >= ?"}
|
|
2112
2126
|
GROUP BY model`).all(sessionID ?? sinceMs);
|
|
2113
2127
|
const key = modelKey(modelID);
|
|
2114
2128
|
let requests = 0;
|
|
2129
|
+
let cost = 0;
|
|
2115
2130
|
for (const row of rows) {
|
|
2116
|
-
if (row.model && modelKey(row.model) === key)
|
|
2131
|
+
if (row.model && modelKey(row.model) === key) {
|
|
2117
2132
|
requests += row.c;
|
|
2133
|
+
cost += row.cost;
|
|
2134
|
+
}
|
|
2118
2135
|
}
|
|
2119
2136
|
return {
|
|
2120
2137
|
requests,
|
|
2121
|
-
cost
|
|
2138
|
+
cost
|
|
2122
2139
|
};
|
|
2123
2140
|
}
|
|
2124
2141
|
const rows = db.query(`SELECT data, time_created FROM message
|
|
@@ -2206,7 +2223,7 @@ function loadSessionUsage(sessionID, path = usageDbPath()) {
|
|
|
2206
2223
|
}
|
|
2207
2224
|
|
|
2208
2225
|
// src/sidebar/useRows.ts
|
|
2209
|
-
var POLL_MS =
|
|
2226
|
+
var POLL_MS = 5000;
|
|
2210
2227
|
function sessionKind(providerID) {
|
|
2211
2228
|
if (!providerID)
|
|
2212
2229
|
return "unknown";
|
|
@@ -2256,7 +2273,10 @@ function useRows(activeModelId, providerID, sessionID) {
|
|
|
2256
2273
|
const [modelUsage, setModelUsage] = createSignal(lastModelUsage);
|
|
2257
2274
|
const [sessionUsage, setSessionUsage] = createSignal();
|
|
2258
2275
|
const [wasOurs, setWasOurs] = createSignal(false);
|
|
2259
|
-
|
|
2276
|
+
const refreshMeta = () => {
|
|
2277
|
+
loadMeta().then(setMeta).catch(() => {});
|
|
2278
|
+
};
|
|
2279
|
+
refreshMeta();
|
|
2260
2280
|
const refreshModelUsage = (id) => {
|
|
2261
2281
|
if (!id)
|
|
2262
2282
|
return;
|
|
@@ -2268,6 +2288,7 @@ function useRows(activeModelId, providerID, sessionID) {
|
|
|
2268
2288
|
const refresh = async () => {
|
|
2269
2289
|
const kind = sessionKind(providerID());
|
|
2270
2290
|
const session = sessionID();
|
|
2291
|
+
refreshMeta();
|
|
2271
2292
|
if (session)
|
|
2272
2293
|
setSessionUsage(loadSessionUsage(session) ?? undefined);
|
|
2273
2294
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jeffreyjyz/opencode-command-code",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.15",
|
|
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",
|