@jeffreyjyz/opencode-command-code 0.3.2 → 0.3.3
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 +63 -14
- package/dist/modelsCache.d.ts +18 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3702,21 +3702,53 @@ function createCommandCode(options = {}, images = () => false) {
|
|
|
3702
3702
|
return { languageModel: model };
|
|
3703
3703
|
}
|
|
3704
3704
|
|
|
3705
|
-
// src/
|
|
3706
|
-
import { mkdir,
|
|
3705
|
+
// src/modelsCache.ts
|
|
3706
|
+
import { mkdir, readFile as readFile2, writeFile } from "fs/promises";
|
|
3707
3707
|
import { homedir as homedir2 } from "os";
|
|
3708
3708
|
import { join } from "path";
|
|
3709
|
+
function cachePath() {
|
|
3710
|
+
const base = process.env.XDG_CACHE_HOME ?? join(homedir2(), ".cache");
|
|
3711
|
+
return join(base, "command-code", "models.json");
|
|
3712
|
+
}
|
|
3713
|
+
async function readModelsCache() {
|
|
3714
|
+
try {
|
|
3715
|
+
const parsed = JSON.parse(await readFile2(cachePath(), "utf8"));
|
|
3716
|
+
if (!Array.isArray(parsed.claude) || !Array.isArray(parsed.open))
|
|
3717
|
+
return;
|
|
3718
|
+
return parsed;
|
|
3719
|
+
} catch {
|
|
3720
|
+
return;
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
async function writeModelsCache(cache) {
|
|
3724
|
+
try {
|
|
3725
|
+
const path = cachePath();
|
|
3726
|
+
await mkdir(join(path, ".."), { recursive: true });
|
|
3727
|
+
await writeFile(path, JSON.stringify(cache));
|
|
3728
|
+
} catch {}
|
|
3729
|
+
}
|
|
3730
|
+
function idsDiffer(a, b) {
|
|
3731
|
+
if (a.length !== b.length)
|
|
3732
|
+
return true;
|
|
3733
|
+
const left = new Set(a.map((m) => m.id));
|
|
3734
|
+
return b.some((m) => !left.has(m.id));
|
|
3735
|
+
}
|
|
3736
|
+
|
|
3737
|
+
// src/startupLog.ts
|
|
3738
|
+
import { mkdir as mkdir2, appendFile } from "fs/promises";
|
|
3739
|
+
import { homedir as homedir3 } from "os";
|
|
3740
|
+
import { join as join2 } from "path";
|
|
3709
3741
|
function setupTimingLine(t) {
|
|
3710
3742
|
return `setup: key=${t.key}ms register=${t.register}ms connection=${t.connection}ms refresh=${t.refresh}ms models=${t.models}`;
|
|
3711
3743
|
}
|
|
3712
3744
|
function startupLogPath() {
|
|
3713
|
-
const base = process.env.XDG_CACHE_HOME ??
|
|
3714
|
-
return
|
|
3745
|
+
const base = process.env.XDG_CACHE_HOME ?? join2(homedir3(), ".cache");
|
|
3746
|
+
return join2(base, "command-code", "startup.log");
|
|
3715
3747
|
}
|
|
3716
3748
|
async function writeStartupLine(line) {
|
|
3717
3749
|
try {
|
|
3718
3750
|
const path = startupLogPath();
|
|
3719
|
-
await
|
|
3751
|
+
await mkdir2(join2(path, ".."), { recursive: true });
|
|
3720
3752
|
await appendFile(path, `[${new Date().toISOString()}] ${line}
|
|
3721
3753
|
`);
|
|
3722
3754
|
} catch {}
|
|
@@ -3839,6 +3871,11 @@ var commandCodeV2 = {
|
|
|
3839
3871
|
}, { providerID: lane.id });
|
|
3840
3872
|
}
|
|
3841
3873
|
const seed = staticSeedModels();
|
|
3874
|
+
const cached = await readModelsCache();
|
|
3875
|
+
if (cached) {
|
|
3876
|
+
seed["command-code-anthropic"] = mergeModels(seed["command-code-anthropic"], cached.claude.map((m) => toV2Model(m, LANES[0])));
|
|
3877
|
+
seed["command-code-openai"] = mergeModels(seed["command-code-openai"], cached.open.map((m) => toV2Model(m, LANES[1])));
|
|
3878
|
+
}
|
|
3842
3879
|
await ctx.provider.transform((editor) => {
|
|
3843
3880
|
for (const lane of LANES) {
|
|
3844
3881
|
editor.update(lane.id, (provider) => {
|
|
@@ -3901,6 +3938,15 @@ var commandCodeV2 = {
|
|
|
3901
3938
|
}
|
|
3902
3939
|
const controller = new AbortController;
|
|
3903
3940
|
let refreshing = false;
|
|
3941
|
+
let appliedClaude = cached?.claude ?? [];
|
|
3942
|
+
let appliedOpen = cached?.open ?? [];
|
|
3943
|
+
const logTimings = (refreshMs, modelCount) => void writeStartupLine(setupTimingLine({
|
|
3944
|
+
key: keyMs,
|
|
3945
|
+
register: registerMs,
|
|
3946
|
+
connection: connectionMs,
|
|
3947
|
+
refresh: refreshMs,
|
|
3948
|
+
models: modelCount
|
|
3949
|
+
}));
|
|
3904
3950
|
const refresh = async () => {
|
|
3905
3951
|
if (refreshing || controller.signal.aborted)
|
|
3906
3952
|
return;
|
|
@@ -3913,27 +3959,30 @@ var commandCodeV2 = {
|
|
|
3913
3959
|
const split = await loadModels(key);
|
|
3914
3960
|
if (controller.signal.aborted)
|
|
3915
3961
|
return;
|
|
3962
|
+
writeModelsCache({ fetchedAt: Date.now(), claude: split.claude, open: split.open });
|
|
3963
|
+
const modelCount = split.claude.length + split.open.length;
|
|
3964
|
+
if (!idsDiffer(split.claude, appliedClaude) && !idsDiffer(split.open, appliedOpen)) {
|
|
3965
|
+
logTimings(Date.now() - refreshStart, modelCount);
|
|
3966
|
+
return;
|
|
3967
|
+
}
|
|
3916
3968
|
await ctx.provider.transform((editor) => {
|
|
3917
3969
|
editor.models.set("command-code-anthropic", mergeModels(seed["command-code-anthropic"], split.claude.map((m) => toV2Model(m, LANES[0]))));
|
|
3918
3970
|
editor.models.set("command-code-openai", mergeModels(seed["command-code-openai"], split.open.map((m) => toV2Model(m, LANES[1]))));
|
|
3919
3971
|
});
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
connection: connectionMs,
|
|
3924
|
-
refresh: Date.now() - refreshStart,
|
|
3925
|
-
models: split.claude.length + split.open.length
|
|
3926
|
-
}));
|
|
3972
|
+
appliedClaude = split.claude;
|
|
3973
|
+
appliedOpen = split.open;
|
|
3974
|
+
logTimings(Date.now() - refreshStart, modelCount);
|
|
3927
3975
|
} catch (e) {
|
|
3928
3976
|
console.warn("[command-code] live model list unavailable, keeping the snapshot:", e);
|
|
3929
3977
|
} finally {
|
|
3930
3978
|
refreshing = false;
|
|
3931
3979
|
}
|
|
3932
3980
|
};
|
|
3933
|
-
refresh();
|
|
3981
|
+
const firstRefresh = setTimeout(() => void refresh(), 3000);
|
|
3934
3982
|
const timer = setInterval(() => void refresh(), 30 * 60 * 1000);
|
|
3935
3983
|
return () => {
|
|
3936
3984
|
controller.abort();
|
|
3985
|
+
clearTimeout(firstRefresh);
|
|
3937
3986
|
clearInterval(timer);
|
|
3938
3987
|
};
|
|
3939
3988
|
}
|
|
@@ -3941,7 +3990,7 @@ var commandCodeV2 = {
|
|
|
3941
3990
|
// package.json
|
|
3942
3991
|
var package_default = {
|
|
3943
3992
|
name: "@jeffreyjyz/opencode-command-code",
|
|
3944
|
-
version: "0.3.
|
|
3993
|
+
version: "0.3.3",
|
|
3945
3994
|
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.",
|
|
3946
3995
|
type: "module",
|
|
3947
3996
|
main: "dist/index.js",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface CachedModel {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
contextLength: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ModelsCache {
|
|
7
|
+
fetchedAt: number;
|
|
8
|
+
claude: CachedModel[];
|
|
9
|
+
open: CachedModel[];
|
|
10
|
+
}
|
|
11
|
+
/** Never throws: a missing or corrupt cache is simply "no cache". */
|
|
12
|
+
export declare function readModelsCache(): Promise<ModelsCache | undefined>;
|
|
13
|
+
/** Best-effort write; diagnostics must never break setup. */
|
|
14
|
+
export declare function writeModelsCache(cache: ModelsCache): Promise<void>;
|
|
15
|
+
/** True when two lists differ by ids (the only thing a picker shows). */
|
|
16
|
+
export declare function idsDiffer(a: readonly CachedModel[], b: readonly CachedModel[]): boolean;
|
|
17
|
+
/** Path for tests and diagnostics. */
|
|
18
|
+
export declare function modelsCachePath(): string;
|
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.3",
|
|
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",
|