@jeffreyjyz/opencode-command-code 0.2.1 → 0.2.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 +66 -13
- package/dist/v2.d.ts +17 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -548,6 +548,8 @@ async function loadModels(key) {
|
|
|
548
548
|
import { Plugin } from "@opencode/plugin";
|
|
549
549
|
var PLUGIN_ID = "command-code";
|
|
550
550
|
var PROVIDER_BASE = "https://api.commandcode.ai/provider/v1";
|
|
551
|
+
var INTEGRATION_ID = "command-code";
|
|
552
|
+
var INTEGRATION_NAME = "Command Code";
|
|
551
553
|
var LANES = [
|
|
552
554
|
{ id: "command-code-anthropic", name: "Command Code (Anthropic)", pkg: "@opencode/ai/providers/anthropic" },
|
|
553
555
|
{
|
|
@@ -586,16 +588,52 @@ function staticSeedModels() {
|
|
|
586
588
|
}
|
|
587
589
|
return seed;
|
|
588
590
|
}
|
|
591
|
+
async function credentialKey(ctx) {
|
|
592
|
+
try {
|
|
593
|
+
const connection = await ctx.integration.connection.active(INTEGRATION_ID);
|
|
594
|
+
if (connection) {
|
|
595
|
+
const credential = await ctx.integration.connection.resolve(connection);
|
|
596
|
+
if (credential?.type === "key")
|
|
597
|
+
return credential.key;
|
|
598
|
+
if (credential?.type === "oauth")
|
|
599
|
+
return credential.access;
|
|
600
|
+
}
|
|
601
|
+
} catch {}
|
|
602
|
+
try {
|
|
603
|
+
return await resolveKey();
|
|
604
|
+
} catch {
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
589
608
|
var commandCodeV2 = Plugin.define({
|
|
590
609
|
id: PLUGIN_ID,
|
|
591
610
|
async setup(ctx) {
|
|
592
|
-
let
|
|
611
|
+
let localKey;
|
|
612
|
+
try {
|
|
613
|
+
localKey = await resolveKey();
|
|
614
|
+
} catch {}
|
|
615
|
+
let hasConnection = false;
|
|
593
616
|
try {
|
|
594
|
-
|
|
617
|
+
hasConnection = await ctx.integration.connection.active(INTEGRATION_ID) !== undefined;
|
|
595
618
|
} catch {}
|
|
596
|
-
if (!
|
|
597
|
-
console.warn(
|
|
619
|
+
if (!localKey && !hasConnection) {
|
|
620
|
+
console.warn(`[command-code] no API key found. Run /connect and choose "${INTEGRATION_NAME}", or \`cmd login\` (~/.commandcode/auth.json), or set CMD_API_KEY.`);
|
|
598
621
|
}
|
|
622
|
+
await ctx.integration.transform((editor) => {
|
|
623
|
+
editor.update(INTEGRATION_ID, (integration) => {
|
|
624
|
+
if (integration.name === integration.id) {
|
|
625
|
+
integration.name = INTEGRATION_NAME;
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
editor.method.update({
|
|
629
|
+
integrationID: INTEGRATION_ID,
|
|
630
|
+
method: { type: "env", names: ["CMD_API_KEY"] }
|
|
631
|
+
});
|
|
632
|
+
editor.method.update({
|
|
633
|
+
integrationID: INTEGRATION_ID,
|
|
634
|
+
method: { type: "key", label: "Command Code API key" }
|
|
635
|
+
});
|
|
636
|
+
});
|
|
599
637
|
const seed = staticSeedModels();
|
|
600
638
|
await ctx.provider.transform((editor) => {
|
|
601
639
|
for (const lane of LANES) {
|
|
@@ -604,10 +642,12 @@ var commandCodeV2 = Plugin.define({
|
|
|
604
642
|
provider.name = lane.name;
|
|
605
643
|
if (provider.package === "")
|
|
606
644
|
provider.package = lane.pkg;
|
|
607
|
-
provider.activation =
|
|
645
|
+
provider.activation = hasConnection || localKey ? "enabled" : "auto";
|
|
608
646
|
provider.settings = { ...provider.settings, baseURL: PROVIDER_BASE };
|
|
609
|
-
if (
|
|
610
|
-
provider.settings.apiKey =
|
|
647
|
+
if (!hasConnection && localKey && provider.settings.apiKey === undefined) {
|
|
648
|
+
provider.settings.apiKey = localKey;
|
|
649
|
+
}
|
|
650
|
+
provider.integrationID ??= INTEGRATION_ID;
|
|
611
651
|
});
|
|
612
652
|
editor.models.set(lane.id, seed[lane.id]);
|
|
613
653
|
}
|
|
@@ -628,17 +668,23 @@ var commandCodeV2 = Plugin.define({
|
|
|
628
668
|
},
|
|
629
669
|
async execute(input) {
|
|
630
670
|
const arg = typeof input?.arg === "string" ? input.arg : "";
|
|
671
|
+
const key = await credentialKey(ctx);
|
|
631
672
|
return {
|
|
632
673
|
content: await runCmduse(arg, { env: key ? { CMD_API_KEY: key } : undefined })
|
|
633
674
|
};
|
|
634
675
|
}
|
|
635
676
|
});
|
|
636
677
|
});
|
|
637
|
-
if (!key)
|
|
638
|
-
return;
|
|
639
678
|
const controller = new AbortController;
|
|
640
|
-
|
|
679
|
+
let refreshing = false;
|
|
680
|
+
const refresh = async () => {
|
|
681
|
+
if (refreshing || controller.signal.aborted)
|
|
682
|
+
return;
|
|
683
|
+
refreshing = true;
|
|
641
684
|
try {
|
|
685
|
+
const key = await credentialKey(ctx);
|
|
686
|
+
if (!key)
|
|
687
|
+
return;
|
|
642
688
|
const split = await loadModels(key);
|
|
643
689
|
if (controller.signal.aborted)
|
|
644
690
|
return;
|
|
@@ -647,10 +693,17 @@ var commandCodeV2 = Plugin.define({
|
|
|
647
693
|
editor.models.set("command-code-openai", split.open.map((m) => toV2Model(m, LANES[1])));
|
|
648
694
|
});
|
|
649
695
|
} catch (e) {
|
|
650
|
-
console.warn("[command-code] live model list unavailable, keeping
|
|
696
|
+
console.warn("[command-code] live model list unavailable, keeping previous list:", e);
|
|
697
|
+
} finally {
|
|
698
|
+
refreshing = false;
|
|
651
699
|
}
|
|
652
|
-
}
|
|
653
|
-
|
|
700
|
+
};
|
|
701
|
+
refresh();
|
|
702
|
+
const timer = setInterval(() => void refresh(), 30 * 60 * 1000);
|
|
703
|
+
return () => {
|
|
704
|
+
controller.abort();
|
|
705
|
+
clearInterval(timer);
|
|
706
|
+
};
|
|
654
707
|
}
|
|
655
708
|
});
|
|
656
709
|
|
package/dist/v2.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ import { Plugin } from "@opencode/plugin";
|
|
|
2
2
|
import { type CmdModel } from "./models";
|
|
3
3
|
export declare const PLUGIN_ID = "command-code";
|
|
4
4
|
export declare const PROVIDER_BASE = "https://api.commandcode.ai/provider/v1";
|
|
5
|
+
/** Shared integration backing both lanes' credentials (/connect + env). */
|
|
6
|
+
export declare const INTEGRATION_ID = "command-code";
|
|
7
|
+
export declare const INTEGRATION_NAME = "Command Code";
|
|
5
8
|
type Lane = {
|
|
6
9
|
id: "command-code-anthropic" | "command-code-openai";
|
|
7
10
|
name: string;
|
|
@@ -20,4 +23,18 @@ export declare function toV2Model(m: CmdModel, lane: Lane): unknown;
|
|
|
20
23
|
* Replaced by the gated live list once the background fetch lands; also the
|
|
21
24
|
* fallback shown when the live fetch fails. */
|
|
22
25
|
export declare function staticSeedModels(): Record<Lane["id"], unknown[]>;
|
|
26
|
+
/** The slice of the plugin context the credential resolver needs. */
|
|
27
|
+
type CredentialContext = {
|
|
28
|
+
integration: {
|
|
29
|
+
connection: {
|
|
30
|
+
active(integrationID: string): Promise<unknown>;
|
|
31
|
+
resolve(connection: unknown): Promise<unknown>;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
/** Credential for spawning cmduse, host-first: a key stored by /connect lives
|
|
36
|
+
* only in opencode's credential store, so ask the connection before falling
|
|
37
|
+
* back to CMD_API_KEY / ~/.commandcode/auth.json. Resolved per call — a
|
|
38
|
+
* /connect mid-session must be picked up. */
|
|
39
|
+
export declare function credentialKey(ctx: CredentialContext): Promise<string | undefined>;
|
|
23
40
|
export declare const commandCodeV2: Plugin.Plugin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jeffreyjyz/opencode-command-code",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.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",
|