@jeffreyjyz/opencode-command-code 0.3.8 → 0.3.10
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/panel.d.ts +6 -0
- package/dist/sidebar/prefs.d.ts +10 -0
- package/dist/sidebar/useRows.d.ts +14 -1
- package/dist/tui.js +93 -18
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4063,7 +4063,7 @@ var commandCodeV2 = {
|
|
|
4063
4063
|
// package.json
|
|
4064
4064
|
var package_default = {
|
|
4065
4065
|
name: "@jeffreyjyz/opencode-command-code",
|
|
4066
|
-
version: "0.3.
|
|
4066
|
+
version: "0.3.10",
|
|
4067
4067
|
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.",
|
|
4068
4068
|
type: "module",
|
|
4069
4069
|
main: "dist/index.js",
|
package/dist/sidebar/panel.d.ts
CHANGED
|
@@ -37,6 +37,12 @@ export declare function legacyColors(theme: {
|
|
|
37
37
|
text: RGBA;
|
|
38
38
|
textMuted: RGBA;
|
|
39
39
|
}): PanelColors;
|
|
40
|
+
/**
|
|
41
|
+
* Colours off: every tone renders as plain text, so only bold and dim carry
|
|
42
|
+
* structure. Headlines lose their accent, status rows their green/amber/red —
|
|
43
|
+
* which is the point of the default.
|
|
44
|
+
*/
|
|
45
|
+
export declare function mono(colors: PanelColors): PanelColors;
|
|
40
46
|
/** Bold title, then one line per row. Renders nothing when there are no rows. */
|
|
41
47
|
export declare function Panel(props: {
|
|
42
48
|
rows: () => SidebarRow[];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface Prefs {
|
|
2
|
+
colors: boolean;
|
|
3
|
+
}
|
|
4
|
+
export declare const DEFAULTS: Prefs;
|
|
5
|
+
/** Preferences live beside opencode's own config, XDG layout honoured. */
|
|
6
|
+
export declare function prefsPath(env?: NodeJS.ProcessEnv): string;
|
|
7
|
+
/** Only a literal `true` enables colour, so a typo cannot turn the panel on. */
|
|
8
|
+
export declare function parsePrefs(raw: unknown): Prefs;
|
|
9
|
+
/** Env override, then the file, then the default. Cached for `CACHE_MS`. */
|
|
10
|
+
export declare function loadPrefs(env?: NodeJS.ProcessEnv, now?: number): Prefs;
|
|
@@ -1 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
import { type SidebarRow, type Usage } from "./rows";
|
|
2
|
+
/** Which provider a session is on, as far as this panel is concerned. */
|
|
3
|
+
export type SessionKind = "ours" | "other" | "unknown";
|
|
4
|
+
/**
|
|
5
|
+
* `unknown` is the frame during a session switch, before the host has resolved
|
|
6
|
+
* the new session's model. It must not be read as "another provider", or the
|
|
7
|
+
* panel blanks and refetches on every tab change.
|
|
8
|
+
*/
|
|
9
|
+
export declare function sessionKind(providerID: string | undefined): SessionKind;
|
|
10
|
+
/** Keep an account snapshot for the next panel that needs it. */
|
|
11
|
+
export declare function rememberSnapshot(snapshot: Usage): void;
|
|
12
|
+
/** Rows to paint before this panel's first fetch of the session completes. */
|
|
13
|
+
export declare function seededRows(): SidebarRow[];
|
|
14
|
+
export declare function useRows(activeModelId: () => string | undefined, providerID: () => string | undefined): import("solid-js").Accessor<SidebarRow[]>;
|
package/dist/tui.js
CHANGED
|
@@ -643,6 +643,18 @@ function legacyColors(theme) {
|
|
|
643
643
|
crit: RGBA.fromValues(0.88, 0.42, 0.46, 1)
|
|
644
644
|
};
|
|
645
645
|
}
|
|
646
|
+
function mono(colors) {
|
|
647
|
+
return {
|
|
648
|
+
base: colors.base,
|
|
649
|
+
muted: colors.muted,
|
|
650
|
+
strong: colors.base,
|
|
651
|
+
label: colors.base,
|
|
652
|
+
headline: colors.base,
|
|
653
|
+
ok: colors.base,
|
|
654
|
+
warn: colors.base,
|
|
655
|
+
crit: colors.base
|
|
656
|
+
};
|
|
657
|
+
}
|
|
646
658
|
var spanStyle = (fg) => ({
|
|
647
659
|
style: {
|
|
648
660
|
fg
|
|
@@ -710,6 +722,50 @@ function Panel(props) {
|
|
|
710
722
|
});
|
|
711
723
|
}
|
|
712
724
|
|
|
725
|
+
// src/sidebar/prefs.ts
|
|
726
|
+
import { readFileSync } from "fs";
|
|
727
|
+
import { homedir } from "os";
|
|
728
|
+
import { join } from "path";
|
|
729
|
+
var DEFAULTS = {
|
|
730
|
+
colors: false
|
|
731
|
+
};
|
|
732
|
+
var CACHE_MS = 5000;
|
|
733
|
+
var cached;
|
|
734
|
+
function prefsPath(env = process.env) {
|
|
735
|
+
const base = env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
|
|
736
|
+
return join(base, "opencode", "command-code.json");
|
|
737
|
+
}
|
|
738
|
+
function parsePrefs(raw) {
|
|
739
|
+
const value = raw?.colors;
|
|
740
|
+
return {
|
|
741
|
+
colors: value === true
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
function loadPrefs(env = process.env, now = Date.now()) {
|
|
745
|
+
if (cached && now - cached.at < CACHE_MS)
|
|
746
|
+
return cached.prefs;
|
|
747
|
+
const flag = env.CMD_COLORS;
|
|
748
|
+
let prefs = DEFAULTS;
|
|
749
|
+
if (flag === "1" || flag === "true")
|
|
750
|
+
prefs = {
|
|
751
|
+
colors: true
|
|
752
|
+
};
|
|
753
|
+
else if (flag === "0" || flag === "false")
|
|
754
|
+
prefs = {
|
|
755
|
+
colors: false
|
|
756
|
+
};
|
|
757
|
+
else {
|
|
758
|
+
try {
|
|
759
|
+
prefs = parsePrefs(JSON.parse(readFileSync(prefsPath(env), "utf8")));
|
|
760
|
+
} catch {}
|
|
761
|
+
}
|
|
762
|
+
cached = {
|
|
763
|
+
at: now,
|
|
764
|
+
prefs
|
|
765
|
+
};
|
|
766
|
+
return prefs;
|
|
767
|
+
}
|
|
768
|
+
|
|
713
769
|
// src/sidebar/useRows.ts
|
|
714
770
|
import { createEffect, createMemo, createSignal, onCleanup } from "solid-js";
|
|
715
771
|
|
|
@@ -1776,10 +1832,10 @@ function minPlan(id) {
|
|
|
1776
1832
|
// src/sidebar/data.ts
|
|
1777
1833
|
import { spawn as spawn2 } from "child_process";
|
|
1778
1834
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
1779
|
-
import { homedir } from "os";
|
|
1780
|
-
import { dirname, join } from "path";
|
|
1835
|
+
import { homedir as homedir2 } from "os";
|
|
1836
|
+
import { dirname, join as join2 } from "path";
|
|
1781
1837
|
var CMDUSE = cmduseCandidates();
|
|
1782
|
-
var MPC = ["mpc",
|
|
1838
|
+
var MPC = ["mpc", join2(homedir2(), ".bun/bin/mpc"), "/opt/homebrew/bin/mpc"];
|
|
1783
1839
|
var CACHE_TTL_MS = 6 * 60 * 60 * 1000;
|
|
1784
1840
|
var SPAWN_OPTIONS = {
|
|
1785
1841
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -1856,8 +1912,8 @@ function parseMpcJson(text) {
|
|
|
1856
1912
|
return meta;
|
|
1857
1913
|
}
|
|
1858
1914
|
function cachePath() {
|
|
1859
|
-
const base = process.env.XDG_CACHE_HOME ??
|
|
1860
|
-
return
|
|
1915
|
+
const base = process.env.XDG_CACHE_HOME ?? join2(homedir2(), ".cache");
|
|
1916
|
+
return join2(base, "command-code", "cc-catalog.json");
|
|
1861
1917
|
}
|
|
1862
1918
|
async function loadMeta() {
|
|
1863
1919
|
try {
|
|
@@ -1885,13 +1941,13 @@ async function loadUsage() {
|
|
|
1885
1941
|
|
|
1886
1942
|
// src/sidebar/usageDb.ts
|
|
1887
1943
|
import { Database } from "bun:sqlite";
|
|
1888
|
-
import { homedir as
|
|
1889
|
-
import { join as
|
|
1944
|
+
import { homedir as homedir3 } from "os";
|
|
1945
|
+
import { join as join3 } from "path";
|
|
1890
1946
|
function usageDbPath() {
|
|
1891
1947
|
if (process.env.OPENCODE_DB)
|
|
1892
1948
|
return process.env.OPENCODE_DB;
|
|
1893
|
-
const base = process.env.XDG_DATA_HOME ??
|
|
1894
|
-
return
|
|
1949
|
+
const base = process.env.XDG_DATA_HOME ?? join3(homedir3(), ".local", "share");
|
|
1950
|
+
return join3(base, "opencode", "opencode.db");
|
|
1895
1951
|
}
|
|
1896
1952
|
function periodStart(usage, now = Date.now()) {
|
|
1897
1953
|
if (typeof usage.periodStartAt === "number")
|
|
@@ -1953,28 +2009,47 @@ function loadModelUsage(modelID, sinceMs, path = usageDbPath()) {
|
|
|
1953
2009
|
|
|
1954
2010
|
// src/sidebar/useRows.ts
|
|
1955
2011
|
var POLL_MS = 60000;
|
|
1956
|
-
function
|
|
1957
|
-
|
|
2012
|
+
function sessionKind(providerID) {
|
|
2013
|
+
if (!providerID)
|
|
2014
|
+
return "unknown";
|
|
2015
|
+
return providerID.startsWith("command-code") ? "ours" : "other";
|
|
2016
|
+
}
|
|
2017
|
+
var lastSnapshot;
|
|
2018
|
+
function rememberSnapshot(snapshot) {
|
|
2019
|
+
lastSnapshot = snapshot;
|
|
2020
|
+
}
|
|
2021
|
+
function seededRows() {
|
|
2022
|
+
return lastSnapshot ? usageRows(lastSnapshot) : [];
|
|
2023
|
+
}
|
|
2024
|
+
function useRows(activeModelId, providerID) {
|
|
2025
|
+
const [usage, setUsage] = createSignal(seededRows());
|
|
1958
2026
|
const [meta, setMeta] = createSignal(new Map);
|
|
1959
2027
|
const [modelUsage, setModelUsage] = createSignal();
|
|
2028
|
+
const [wasOurs, setWasOurs] = createSignal(false);
|
|
1960
2029
|
loadMeta().then(setMeta).catch(() => {});
|
|
1961
2030
|
const refresh = async () => {
|
|
1962
2031
|
try {
|
|
1963
2032
|
const snapshot = await loadUsage();
|
|
2033
|
+
rememberSnapshot(snapshot);
|
|
1964
2034
|
setUsage(usageRows(snapshot));
|
|
1965
2035
|
const id = activeModelId();
|
|
1966
2036
|
setModelUsage(id ? loadModelUsage(id, periodStart(snapshot)) ?? undefined : undefined);
|
|
1967
2037
|
} catch {}
|
|
1968
2038
|
};
|
|
1969
2039
|
createEffect(() => {
|
|
1970
|
-
|
|
2040
|
+
const kind = sessionKind(providerID());
|
|
2041
|
+
if (kind !== "ours")
|
|
1971
2042
|
return;
|
|
2043
|
+
setWasOurs(true);
|
|
1972
2044
|
refresh();
|
|
1973
2045
|
const timer = setInterval(() => void refresh(), POLL_MS);
|
|
1974
2046
|
onCleanup(() => clearInterval(timer));
|
|
1975
2047
|
});
|
|
1976
2048
|
return createMemo(() => {
|
|
1977
|
-
|
|
2049
|
+
const kind = sessionKind(providerID());
|
|
2050
|
+
if (kind === "other")
|
|
2051
|
+
return [];
|
|
2052
|
+
if (kind === "unknown" && !wasOurs())
|
|
1978
2053
|
return [];
|
|
1979
2054
|
const id = activeModelId();
|
|
1980
2055
|
const found = id ? meta().get(modelKey(id)) ?? meta().get(id) : undefined;
|
|
@@ -1989,13 +2064,13 @@ function useRows(activeModelId, active) {
|
|
|
1989
2064
|
|
|
1990
2065
|
// src/tui.tsx
|
|
1991
2066
|
var ID = "command-code.tui";
|
|
1992
|
-
var
|
|
2067
|
+
var themed = (colors) => loadPrefs().colors ? colors : mono(colors);
|
|
1993
2068
|
function PanelV1(props) {
|
|
1994
2069
|
const current = () => props.api.state.session.get(props.sessionID)?.model;
|
|
1995
|
-
const rows = useRows(() => current()?.id, () =>
|
|
2070
|
+
const rows = useRows(() => current()?.id, () => current()?.providerID);
|
|
1996
2071
|
return _$createComponent2(Panel, {
|
|
1997
2072
|
rows,
|
|
1998
|
-
colors: () => legacyColors(props.api.theme.current)
|
|
2073
|
+
colors: () => themed(legacyColors(props.api.theme.current))
|
|
1999
2074
|
});
|
|
2000
2075
|
}
|
|
2001
2076
|
var tui = async (api) => {
|
|
@@ -2018,10 +2093,10 @@ function PanelV2(props) {
|
|
|
2018
2093
|
ctx
|
|
2019
2094
|
} = props;
|
|
2020
2095
|
const current = () => ctx.data.session.get(props.sessionID)?.model;
|
|
2021
|
-
const rows = useRows(() => current()?.id, () =>
|
|
2096
|
+
const rows = useRows(() => current()?.id, () => current()?.providerID);
|
|
2022
2097
|
return _$createComponent2(Panel, {
|
|
2023
2098
|
rows,
|
|
2024
|
-
colors: () => hostColors(ctx.theme)
|
|
2099
|
+
colors: () => themed(hostColors(ctx.theme))
|
|
2025
2100
|
});
|
|
2026
2101
|
}
|
|
2027
2102
|
var commandCodeTui = {
|
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.10",
|
|
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",
|