@jeffreyjyz/opencode-command-code 0.5.16 → 0.5.18
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/cli.d.ts +11 -0
- package/dist/constants/binaries.d.ts +2 -0
- package/dist/constants/providers.d.ts +8 -0
- package/dist/constants/timing.d.ts +5 -0
- package/dist/index.js +64 -1
- package/dist/sidebar/ark.d.ts +58 -0
- package/dist/sidebar/data.d.ts +8 -0
- package/dist/sidebar/useRows.d.ts +6 -1
- package/dist/tui.js +257 -15
- package/package.json +1 -1
package/dist/cli.d.ts
CHANGED
|
@@ -10,6 +10,9 @@ export declare function mpcCandidates(env?: Record<string, string | undefined>):
|
|
|
10
10
|
/** Same lookup for ocuse, the OpenCode Go/Zen reader shipped in the cmd-usage
|
|
11
11
|
* crate: `OCUSE_BIN` wins when set, then the homebrew fallbacks. */
|
|
12
12
|
export declare function ocuseCandidates(env?: Record<string, string | undefined>): string[];
|
|
13
|
+
/** Same lookup for arkuse, the Volcengine ARK Agent Plan reader in the same
|
|
14
|
+
* crate: `ARKUSE_BIN` wins when set, then the homebrew fallbacks. */
|
|
15
|
+
export declare function arkuseCandidates(env?: Record<string, string | undefined>): string[];
|
|
13
16
|
/** Shell-words split: whitespace-separated, with single/double quoting and
|
|
14
17
|
* backslash escapes ("--tz +05:30", arg='a b'). Unterminated quotes close at
|
|
15
18
|
* end of input. */
|
|
@@ -28,6 +31,10 @@ export declare function buildMpcArgs(arg: string): string[];
|
|
|
28
31
|
* watch loop and would never return, so empty input never passes through.
|
|
29
32
|
*/
|
|
30
33
|
export declare function ocuseArgs(arg: string | undefined): string;
|
|
34
|
+
/** The arg the arkuse_usage tool and the /arkuse-usage dialog pass on: the
|
|
35
|
+
* agent's (or slash) args when given, else `-1`. A bare arkuse is the live
|
|
36
|
+
* watch loop and would never return. */
|
|
37
|
+
export declare function arkuseArgs(arg: string | undefined): string;
|
|
31
38
|
export type RunOptions = {
|
|
32
39
|
signal?: AbortSignal;
|
|
33
40
|
/** Extra env for the child (CMD_API_KEY when the plugin resolved one). */
|
|
@@ -58,3 +65,7 @@ export declare function runMpc(arg: string | readonly string[], opts?: RunOption
|
|
|
58
65
|
* hint is the same brew formula. A string arg is shell-split, an array used
|
|
59
66
|
* as-is. */
|
|
60
67
|
export declare function runOcuse(arg: string | readonly string[], opts?: RunOptions): Promise<string>;
|
|
68
|
+
/** Run arkuse and return its plain-text stdout (Volcengine ARK usage). Same
|
|
69
|
+
* contract as runCmduse; arkuse ships in the cmd-usage crate, so its install
|
|
70
|
+
* hint is the same brew formula. */
|
|
71
|
+
export declare function runArkuse(arg: string | readonly string[], opts?: RunOptions): Promise<string>;
|
|
@@ -4,3 +4,5 @@ export declare const CMDUSE_BIN_CANDIDATES: readonly string[];
|
|
|
4
4
|
export declare const MPC_BIN_CANDIDATES: readonly string[];
|
|
5
5
|
/** Fallback lookup paths for ocuse (OCUSE_BIN wins when set). */
|
|
6
6
|
export declare const OCUSE_BIN_CANDIDATES: readonly string[];
|
|
7
|
+
/** Fallback lookup paths for arkuse (ARKUSE_BIN wins when set). */
|
|
8
|
+
export declare const ARKUSE_BIN_CANDIDATES: readonly string[];
|
|
@@ -11,12 +11,16 @@ export declare const GO_PROVIDER_ID = "opencode-go";
|
|
|
11
11
|
/** OpenCode Zen provider id and its `opencode-zen` alias prefix. */
|
|
12
12
|
export declare const ZEN_PROVIDER_ID = "opencode";
|
|
13
13
|
export declare const ZEN_PROVIDER_PREFIX = "opencode-zen";
|
|
14
|
+
/** Volcengine ARK Agent Plan provider id (what opencode records for its rows). */
|
|
15
|
+
export declare const ARK_PROVIDER_ID = "agent-plan";
|
|
14
16
|
/** TUI plugin id (stable contract; test/tui.test.ts pins it). */
|
|
15
17
|
export declare const TUI_ID = "command-code.tui";
|
|
16
18
|
/** The v2 /cmd-usage slash command id (registered and bound in tui.tsx). */
|
|
17
19
|
export declare const CMD_USAGE_COMMAND_ID = "command-code.cmd-usage";
|
|
18
20
|
/** The v2 /ocuse-usage slash command id (registered and bound in tui.tsx). */
|
|
19
21
|
export declare const OCUSE_USAGE_COMMAND_ID = "command-code.ocuse-usage";
|
|
22
|
+
/** The v2 /arkuse-usage slash command id (registered and bound in tui.tsx). */
|
|
23
|
+
export declare const ARKUSE_USAGE_COMMAND_ID = "command-code.arkuse-usage";
|
|
20
24
|
/** The cmd_usage tool description, shared by the v1 and v2 halves. */
|
|
21
25
|
export declare const TOOL_DESCRIPTION = "Fetch live Command Code plan/usage: plan name, monthly credits, 5-hour & weekly windows, billing-period summary. Pass arg='plans' for the plan comparison table only, or extra cmduse flags (e.g. '--tz +05:30 daily').";
|
|
22
26
|
/** The mpc_prices tool description, shared by the v1 and v2 halves. */
|
|
@@ -27,6 +31,10 @@ export declare const MPC_TOOL_ARG_DESCRIPTION = "Optional mpc flags: '--model <r
|
|
|
27
31
|
export declare const OCUSE_TOOL_DESCRIPTION = "Fetch live OpenCode Go/Zen usage: the account's window meters, per-model spend against limits, 5-hour & weekly windows, billing-period summary. Defaults to the one-shot dashboard; pass extra ocuse flags for more (e.g. '--plan go-plus', 'daily', '--json').";
|
|
28
32
|
/** The ocuse_usage `arg` description, shared by the v1 and v2 halves. */
|
|
29
33
|
export declare const OCUSE_TOOL_ARG_DESCRIPTION = "Optional: extra ocuse flags (e.g. '--plan go-plus', 'daily', '--json'); empty means the one-shot dashboard";
|
|
34
|
+
/** The arkuse_usage tool description, shared by the v1 and v2 halves. */
|
|
35
|
+
export declare const ARKUSE_TOOL_DESCRIPTION = "Fetch live Volcengine ARK Agent Plan usage in AFP: the plan's 5-hour/weekly/monthly meters from arkcli, this machine's per-model AFP, and the reconciliation between them. Defaults to the one-shot dashboard; pass extra arkuse flags for more (e.g. 'daily', '--plan medium', '--json').";
|
|
36
|
+
/** The arkuse_usage `arg` description, shared by the v1 and v2 halves. */
|
|
37
|
+
export declare const ARKUSE_TOOL_ARG_DESCRIPTION = "Optional: extra arkuse flags (e.g. '--plan medium', '--profile <name>', 'daily', '--json'); empty means the one-shot dashboard";
|
|
30
38
|
export type Lane = {
|
|
31
39
|
id: "command-code-anthropic" | "command-code-openai";
|
|
32
40
|
name: string;
|
|
@@ -11,3 +11,8 @@ export declare const MODELS_CACHE_TTL_MS: number;
|
|
|
11
11
|
export declare const CATALOG_CACHE_TTL_MS: number;
|
|
12
12
|
/** Re-read window for the sidebar colour prefs file (src/sidebar/prefs.ts). */
|
|
13
13
|
export declare const PREFS_CACHE_MS = 5000;
|
|
14
|
+
/** Process-lifetime cache for the ARK sidebar snapshot: every `arkuse` run
|
|
15
|
+
* shells out to `arkcli` for the plan meters, so polling it at the 5s cadence
|
|
16
|
+
* would be one control-plane round-trip per tick. A minute keeps the meters
|
|
17
|
+
* fresh enough while the store-backed rows still update on the poll. */
|
|
18
|
+
export declare const ARK_SNAPSHOT_TTL_MS = 60000;
|
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.18",
|
|
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",
|
|
@@ -3242,6 +3242,11 @@ var OCUSE_BIN_CANDIDATES = [
|
|
|
3242
3242
|
"/opt/homebrew/bin/ocuse",
|
|
3243
3243
|
"/usr/local/bin/ocuse"
|
|
3244
3244
|
];
|
|
3245
|
+
var ARKUSE_BIN_CANDIDATES = [
|
|
3246
|
+
"arkuse",
|
|
3247
|
+
"/opt/homebrew/bin/arkuse",
|
|
3248
|
+
"/usr/local/bin/arkuse"
|
|
3249
|
+
];
|
|
3245
3250
|
|
|
3246
3251
|
// src/constants/cli.ts
|
|
3247
3252
|
var DEFAULT_ARGS = ["-1", "--plain"];
|
|
@@ -3273,6 +3278,11 @@ function ocuseCandidates(env = process.env) {
|
|
|
3273
3278
|
return candidates.filter((bin) => Boolean(bin));
|
|
3274
3279
|
}
|
|
3275
3280
|
var OCUSE_CANDIDATES = ocuseCandidates();
|
|
3281
|
+
function arkuseCandidates(env = process.env) {
|
|
3282
|
+
const candidates = [env.ARKUSE_BIN, ...ARKUSE_BIN_CANDIDATES];
|
|
3283
|
+
return candidates.filter((bin) => Boolean(bin));
|
|
3284
|
+
}
|
|
3285
|
+
var ARKUSE_CANDIDATES = arkuseCandidates();
|
|
3276
3286
|
function splitCliArgs(input) {
|
|
3277
3287
|
const out = [];
|
|
3278
3288
|
let cur = "";
|
|
@@ -3328,6 +3338,9 @@ function buildMpcArgs(arg) {
|
|
|
3328
3338
|
function ocuseArgs(arg) {
|
|
3329
3339
|
return arg !== undefined && arg.trim() !== "" ? arg : "-1";
|
|
3330
3340
|
}
|
|
3341
|
+
function arkuseArgs(arg) {
|
|
3342
|
+
return arg !== undefined && arg.trim() !== "" ? arg : "-1";
|
|
3343
|
+
}
|
|
3331
3344
|
function stderrTail(text) {
|
|
3332
3345
|
const lines = text.trimEnd().split(`
|
|
3333
3346
|
`);
|
|
@@ -3428,6 +3441,21 @@ async function runOcuse(arg, opts = {}) {
|
|
|
3428
3441
|
}
|
|
3429
3442
|
throw new Error(`ocuse binary not found (install: brew install JeffreyJYZ/tap/cmduse)${last instanceof Error && last.message !== last.name ? ` \u2014 ${last.message}` : ""}`, { cause: last });
|
|
3430
3443
|
}
|
|
3444
|
+
async function runArkuse(arg, opts = {}) {
|
|
3445
|
+
const args = resolveArgs(arg, splitCliArgs);
|
|
3446
|
+
const candidates = opts.candidates ?? ARKUSE_CANDIDATES;
|
|
3447
|
+
let last;
|
|
3448
|
+
for (const bin of candidates) {
|
|
3449
|
+
try {
|
|
3450
|
+
return await runOnce(bin, args, opts, "arkuse");
|
|
3451
|
+
} catch (e) {
|
|
3452
|
+
last = e;
|
|
3453
|
+
if (e?.code !== "ENOENT")
|
|
3454
|
+
throw e;
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
throw new Error(`arkuse binary not found (install: brew install JeffreyJYZ/tap/cmduse)${last instanceof Error && last.message !== last.name ? ` \u2014 ${last.message}` : ""}`, { cause: last });
|
|
3458
|
+
}
|
|
3431
3459
|
|
|
3432
3460
|
// src/constants/models.ts
|
|
3433
3461
|
var MODEL_CAPABILITIES = {
|
|
@@ -3458,6 +3486,8 @@ var MPC_TOOL_DESCRIPTION = "Per-model price comparison: what a model costs per r
|
|
|
3458
3486
|
var MPC_TOOL_ARG_DESCRIPTION = "Optional mpc flags: '--model <regex>' filters rows, '--minimal' | '--medium' | '--detail' set table width, '--json' for full structured rows, '--cc-plan'/'--oc-plan' pick a plan, '--usage' projects real usage";
|
|
3459
3487
|
var OCUSE_TOOL_DESCRIPTION = "Fetch live OpenCode Go/Zen usage: the account's window meters, per-model spend against limits, 5-hour & weekly windows, billing-period summary. Defaults to the one-shot dashboard; pass extra ocuse flags for more (e.g. '--plan go-plus', 'daily', '--json').";
|
|
3460
3488
|
var OCUSE_TOOL_ARG_DESCRIPTION = "Optional: extra ocuse flags (e.g. '--plan go-plus', 'daily', '--json'); empty means the one-shot dashboard";
|
|
3489
|
+
var ARKUSE_TOOL_DESCRIPTION = "Fetch live Volcengine ARK Agent Plan usage in AFP: the plan's 5-hour/weekly/monthly meters from arkcli, this machine's per-model AFP, and the reconciliation between them. Defaults to the one-shot dashboard; pass extra arkuse flags for more (e.g. 'daily', '--plan medium', '--json').";
|
|
3490
|
+
var ARKUSE_TOOL_ARG_DESCRIPTION = "Optional: extra arkuse flags (e.g. '--plan medium', '--profile <name>', 'daily', '--json'); empty means the one-shot dashboard";
|
|
3461
3491
|
var LANES = [
|
|
3462
3492
|
{
|
|
3463
3493
|
id: "command-code-anthropic",
|
|
@@ -5015,6 +5045,26 @@ var commandCodeV2 = {
|
|
|
5015
5045
|
};
|
|
5016
5046
|
}
|
|
5017
5047
|
});
|
|
5048
|
+
editor.add({
|
|
5049
|
+
name: "arkuse_usage",
|
|
5050
|
+
description: ARKUSE_TOOL_DESCRIPTION,
|
|
5051
|
+
input: {
|
|
5052
|
+
type: "object",
|
|
5053
|
+
properties: {
|
|
5054
|
+
arg: {
|
|
5055
|
+
type: "string",
|
|
5056
|
+
description: ARKUSE_TOOL_ARG_DESCRIPTION
|
|
5057
|
+
}
|
|
5058
|
+
},
|
|
5059
|
+
additionalProperties: false
|
|
5060
|
+
},
|
|
5061
|
+
async execute(input) {
|
|
5062
|
+
const arg = typeof input?.arg === "string" ? input.arg : undefined;
|
|
5063
|
+
return {
|
|
5064
|
+
content: await runArkuse(arkuseArgs(arg))
|
|
5065
|
+
};
|
|
5066
|
+
}
|
|
5067
|
+
});
|
|
5018
5068
|
});
|
|
5019
5069
|
let hasConnection = false;
|
|
5020
5070
|
let connectionMs = 0;
|
|
@@ -5231,6 +5281,10 @@ var CommandCodePlugin = async (_input) => {
|
|
|
5231
5281
|
description: "Show OpenCode Go/Zen usage: account meters and per-model spend",
|
|
5232
5282
|
template: "Call the ocuse_usage tool and present its markdown output verbatim to the user. If the tool errors, the Go key is missing or has no subscription \u2014 usage still shows where the store has it. $ARGUMENTS"
|
|
5233
5283
|
};
|
|
5284
|
+
cfg.command["arkuse-usage"] = {
|
|
5285
|
+
description: "Show Volcengine ARK Agent Plan usage: AFP meters per model",
|
|
5286
|
+
template: "Call the arkuse_usage tool and present its markdown output verbatim to the user. If the tool errors, arkcli or its agent-plan profile is missing \u2014 usage still shows where the store has it. $ARGUMENTS"
|
|
5287
|
+
};
|
|
5234
5288
|
},
|
|
5235
5289
|
provider: {
|
|
5236
5290
|
id: ANTHROPIC.id,
|
|
@@ -5276,6 +5330,15 @@ var CommandCodePlugin = async (_input) => {
|
|
|
5276
5330
|
async execute(args) {
|
|
5277
5331
|
return runOcuse(ocuseArgs(args.arg));
|
|
5278
5332
|
}
|
|
5333
|
+
}),
|
|
5334
|
+
arkuse_usage: tool({
|
|
5335
|
+
description: ARKUSE_TOOL_DESCRIPTION,
|
|
5336
|
+
args: {
|
|
5337
|
+
arg: string2().optional().describe(ARKUSE_TOOL_ARG_DESCRIPTION)
|
|
5338
|
+
},
|
|
5339
|
+
async execute(args) {
|
|
5340
|
+
return runArkuse(arkuseArgs(args.arg));
|
|
5341
|
+
}
|
|
5279
5342
|
})
|
|
5280
5343
|
}
|
|
5281
5344
|
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type SidebarRow } from "./rows";
|
|
2
|
+
export interface ArkTotals {
|
|
3
|
+
afp: number;
|
|
4
|
+
requests: number;
|
|
5
|
+
tokensIn: number;
|
|
6
|
+
tokensOut: number;
|
|
7
|
+
cacheRead: number;
|
|
8
|
+
}
|
|
9
|
+
/** One of the plan's own meters (`arkuse`'s `account` block). Every field is
|
|
10
|
+
* optional-ish by parsing: a malformed meter must not raise a cap flag. */
|
|
11
|
+
export interface ArkMeter {
|
|
12
|
+
status: string;
|
|
13
|
+
percent: number;
|
|
14
|
+
used: number;
|
|
15
|
+
total: number;
|
|
16
|
+
resetAt?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface ArkModel {
|
|
19
|
+
id: string;
|
|
20
|
+
coef: number;
|
|
21
|
+
fiveHour: ArkTotals;
|
|
22
|
+
weekly: ArkTotals;
|
|
23
|
+
month: ArkTotals;
|
|
24
|
+
}
|
|
25
|
+
export interface ArkUsage {
|
|
26
|
+
plan: string;
|
|
27
|
+
profile?: string;
|
|
28
|
+
periodStart?: number;
|
|
29
|
+
periodEndAt?: number;
|
|
30
|
+
summary: ArkTotals & {
|
|
31
|
+
yuan?: number;
|
|
32
|
+
};
|
|
33
|
+
fiveHour: ArkTotals;
|
|
34
|
+
weekly: ArkTotals;
|
|
35
|
+
month: ArkTotals;
|
|
36
|
+
daily?: ArkTotals;
|
|
37
|
+
account?: {
|
|
38
|
+
fiveHour: ArkMeter;
|
|
39
|
+
daily?: ArkMeter;
|
|
40
|
+
weekly: ArkMeter;
|
|
41
|
+
monthly: ArkMeter;
|
|
42
|
+
};
|
|
43
|
+
accountError?: string;
|
|
44
|
+
afpPerRequest?: number;
|
|
45
|
+
reconciledPct?: number;
|
|
46
|
+
/** Keyed by model id, the same key the session's model id uses. */
|
|
47
|
+
models: Map<string, ArkModel>;
|
|
48
|
+
}
|
|
49
|
+
/** Parse `arkuse -1 --json`. A malformed body reads as an empty snapshot, never
|
|
50
|
+
* as a fabricated plan. */
|
|
51
|
+
export declare function parseArkJson(text: string): ArkUsage;
|
|
52
|
+
/**
|
|
53
|
+
* The ARK panel: plan, the window meters, a rule, then the active model's own
|
|
54
|
+
* AFP for the period. `fallbackName` is the session's model id, which is the
|
|
55
|
+
* key `arkuse` uses, so the model block renders even when nothing else knows the
|
|
56
|
+
* name.
|
|
57
|
+
*/
|
|
58
|
+
export declare function arkRows(usage: ArkUsage | undefined, fallbackName?: string): SidebarRow[];
|
package/dist/sidebar/data.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type OcPlan } from "../constants/sidebar";
|
|
2
|
+
import { type ArkUsage } from "./ark";
|
|
2
3
|
import { type ModelMeta, type Usage } from "./rows";
|
|
3
4
|
import { type ZenUsage } from "./zen";
|
|
4
5
|
/** Parse `cmduse -1 --json` into the usage snapshot. */
|
|
@@ -39,3 +40,10 @@ export declare function loadUsage(): Promise<Usage>;
|
|
|
39
40
|
* caller then omits the panel.
|
|
40
41
|
*/
|
|
41
42
|
export declare function loadZen(plan?: OcPlan): Promise<ZenUsage>;
|
|
43
|
+
/**
|
|
44
|
+
* One Volcengine ARK snapshot from `arkuse -1 --json`: the plan's own meters
|
|
45
|
+
* (through `arkcli`) plus this store's AFP per model. Cached for a minute
|
|
46
|
+
* because the spawn costs a control-plane round-trip; throws when `arkuse` is
|
|
47
|
+
* missing or fails, and the caller then keeps the last snapshot.
|
|
48
|
+
*/
|
|
49
|
+
export declare function loadArk(): Promise<ArkUsage>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ArkUsage } from "./ark";
|
|
1
2
|
import { type ModelMeta, type ModelUsage, type SidebarRow, type Usage } from "./rows";
|
|
2
3
|
import { type ZenUsage } from "./zen";
|
|
3
4
|
/**
|
|
@@ -6,7 +7,7 @@ import { type ZenUsage } from "./zen";
|
|
|
6
7
|
* resolved the new session's model; it must not be read as someone else's, or
|
|
7
8
|
* the panel blanks and refetches on every tab change.
|
|
8
9
|
*/
|
|
9
|
-
export type SessionKind = "ours" | "go" | "zen" | "other" | "unknown";
|
|
10
|
+
export type SessionKind = "ours" | "go" | "zen" | "ark" | "other" | "unknown";
|
|
10
11
|
export declare function sessionKind(providerID: string | undefined): SessionKind;
|
|
11
12
|
/** The section's title, per family. */
|
|
12
13
|
export declare function panelTitle(kind: SessionKind): string;
|
|
@@ -40,4 +41,8 @@ export declare function seededMeta(): Map<string, ModelMeta>;
|
|
|
40
41
|
export declare function rememberZen(usage: ZenUsage): void;
|
|
41
42
|
/** The remembered Go/Zen snapshot, or undefined on the first panel. */
|
|
42
43
|
export declare function seededZen(): ZenUsage | undefined;
|
|
44
|
+
/** Keep an ARK snapshot for the next panel that needs it. */
|
|
45
|
+
export declare function rememberArk(usage: ArkUsage): void;
|
|
46
|
+
/** The remembered ARK snapshot, or undefined on the first panel. */
|
|
47
|
+
export declare function seededArk(): ArkUsage | undefined;
|
|
43
48
|
export declare function useRows(activeModelId: () => string | undefined, providerID: () => string | undefined, sessionID: () => string | undefined): import("solid-js").Accessor<SidebarRow[]>;
|
package/dist/tui.js
CHANGED
|
@@ -11,6 +11,7 @@ import { join } from "path";
|
|
|
11
11
|
var CMDUSE_BIN_CANDIDATES = ["cmduse", "/opt/homebrew/bin/cmduse", "/usr/local/bin/cmduse"];
|
|
12
12
|
var MPC_BIN_CANDIDATES = ["mpc", join(homedir(), ".bun/bin/mpc"), "/opt/homebrew/bin/mpc"];
|
|
13
13
|
var OCUSE_BIN_CANDIDATES = ["ocuse", "/opt/homebrew/bin/ocuse", "/usr/local/bin/ocuse"];
|
|
14
|
+
var ARKUSE_BIN_CANDIDATES = ["arkuse", "/opt/homebrew/bin/arkuse", "/usr/local/bin/arkuse"];
|
|
14
15
|
|
|
15
16
|
// src/constants/cli.ts
|
|
16
17
|
var DEFAULT_ARGS = ["-1", "--plain"];
|
|
@@ -37,6 +38,11 @@ function ocuseCandidates(env = process.env) {
|
|
|
37
38
|
return candidates.filter((bin) => Boolean(bin));
|
|
38
39
|
}
|
|
39
40
|
var OCUSE_CANDIDATES = ocuseCandidates();
|
|
41
|
+
function arkuseCandidates(env = process.env) {
|
|
42
|
+
const candidates = [env.ARKUSE_BIN, ...ARKUSE_BIN_CANDIDATES];
|
|
43
|
+
return candidates.filter((bin) => Boolean(bin));
|
|
44
|
+
}
|
|
45
|
+
var ARKUSE_CANDIDATES = arkuseCandidates();
|
|
40
46
|
function splitCliArgs(input) {
|
|
41
47
|
const out = [];
|
|
42
48
|
let cur = "";
|
|
@@ -92,6 +98,9 @@ function buildMpcArgs(arg) {
|
|
|
92
98
|
function ocuseArgs(arg) {
|
|
93
99
|
return arg !== undefined && arg.trim() !== "" ? arg : "-1";
|
|
94
100
|
}
|
|
101
|
+
function arkuseArgs(arg) {
|
|
102
|
+
return arg !== undefined && arg.trim() !== "" ? arg : "-1";
|
|
103
|
+
}
|
|
95
104
|
function stderrTail(text) {
|
|
96
105
|
const lines = text.trimEnd().split(`
|
|
97
106
|
`);
|
|
@@ -203,15 +212,34 @@ async function runOcuse(arg, opts = {}) {
|
|
|
203
212
|
cause: last
|
|
204
213
|
});
|
|
205
214
|
}
|
|
215
|
+
async function runArkuse(arg, opts = {}) {
|
|
216
|
+
const args = resolveArgs(arg, splitCliArgs);
|
|
217
|
+
const candidates = opts.candidates ?? ARKUSE_CANDIDATES;
|
|
218
|
+
let last;
|
|
219
|
+
for (const bin of candidates) {
|
|
220
|
+
try {
|
|
221
|
+
return await runOnce(bin, args, opts, "arkuse");
|
|
222
|
+
} catch (e) {
|
|
223
|
+
last = e;
|
|
224
|
+
if (e?.code !== "ENOENT")
|
|
225
|
+
throw e;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
throw new Error(`arkuse binary not found (install: brew install JeffreyJYZ/tap/cmduse)${last instanceof Error && last.message !== last.name ? ` \u2014 ${last.message}` : ""}`, {
|
|
229
|
+
cause: last
|
|
230
|
+
});
|
|
231
|
+
}
|
|
206
232
|
|
|
207
233
|
// src/constants/providers.ts
|
|
208
234
|
var PROVIDER_ID_PREFIX = "command-code";
|
|
209
235
|
var GO_PROVIDER_ID = "opencode-go";
|
|
210
236
|
var ZEN_PROVIDER_ID = "opencode";
|
|
211
237
|
var ZEN_PROVIDER_PREFIX = "opencode-zen";
|
|
238
|
+
var ARK_PROVIDER_ID = "agent-plan";
|
|
212
239
|
var TUI_ID = "command-code.tui";
|
|
213
240
|
var CMD_USAGE_COMMAND_ID = "command-code.cmd-usage";
|
|
214
241
|
var OCUSE_USAGE_COMMAND_ID = "command-code.ocuse-usage";
|
|
242
|
+
var ARKUSE_USAGE_COMMAND_ID = "command-code.arkuse-usage";
|
|
215
243
|
|
|
216
244
|
// src/sidebar/panel.tsx
|
|
217
245
|
import { createComponent as _$createComponent } from "@opentui/solid";
|
|
@@ -926,6 +954,7 @@ var CHILD_TIMEOUT_MS = 30000;
|
|
|
926
954
|
var MODELS_CACHE_TTL_MS = 5 * 60 * 1000;
|
|
927
955
|
var CATALOG_CACHE_TTL_MS = 60 * 60 * 1000;
|
|
928
956
|
var PREFS_CACHE_MS = 5000;
|
|
957
|
+
var ARK_SNAPSHOT_TTL_MS = 60000;
|
|
929
958
|
|
|
930
959
|
// src/sidebar/prefs.ts
|
|
931
960
|
var cached;
|
|
@@ -2095,13 +2124,167 @@ function minPlan(id) {
|
|
|
2095
2124
|
return MODEL_CATALOG[id]?.minPlan ?? null;
|
|
2096
2125
|
}
|
|
2097
2126
|
|
|
2127
|
+
// src/sidebar/ark.ts
|
|
2128
|
+
function totals(value) {
|
|
2129
|
+
const v = value ?? {};
|
|
2130
|
+
const num = (key) => typeof v[key] === "number" ? v[key] : 0;
|
|
2131
|
+
return {
|
|
2132
|
+
afp: num("afp"),
|
|
2133
|
+
requests: num("requests"),
|
|
2134
|
+
tokensIn: num("tokensIn"),
|
|
2135
|
+
tokensOut: num("tokensOut"),
|
|
2136
|
+
cacheRead: num("cacheRead")
|
|
2137
|
+
};
|
|
2138
|
+
}
|
|
2139
|
+
function meter(value) {
|
|
2140
|
+
const v = value && typeof value === "object" ? value : {};
|
|
2141
|
+
return {
|
|
2142
|
+
status: typeof v.status === "string" ? v.status : "ok",
|
|
2143
|
+
percent: typeof v.percent === "number" ? v.percent : 0,
|
|
2144
|
+
used: typeof v.used === "number" ? v.used : 0,
|
|
2145
|
+
total: typeof v.total === "number" ? v.total : 0,
|
|
2146
|
+
resetAt: typeof v.resetAt === "number" ? v.resetAt : undefined
|
|
2147
|
+
};
|
|
2148
|
+
}
|
|
2149
|
+
function parseArkJson(text) {
|
|
2150
|
+
let body;
|
|
2151
|
+
try {
|
|
2152
|
+
body = JSON.parse(text);
|
|
2153
|
+
} catch {
|
|
2154
|
+
body = {};
|
|
2155
|
+
}
|
|
2156
|
+
const account = body.account ?? {};
|
|
2157
|
+
const models = new Map;
|
|
2158
|
+
const rawModels = body.models ?? {};
|
|
2159
|
+
for (const [id, raw] of Object.entries(rawModels)) {
|
|
2160
|
+
const m = raw ?? {};
|
|
2161
|
+
models.set(id, {
|
|
2162
|
+
id,
|
|
2163
|
+
coef: typeof m.coef === "number" ? m.coef : 0,
|
|
2164
|
+
fiveHour: totals(m.fiveHour),
|
|
2165
|
+
weekly: totals(m.weekly),
|
|
2166
|
+
month: totals(m.month)
|
|
2167
|
+
});
|
|
2168
|
+
}
|
|
2169
|
+
const summary = body.summary ?? {};
|
|
2170
|
+
return {
|
|
2171
|
+
plan: typeof body.plan === "string" ? body.plan : "medium",
|
|
2172
|
+
profile: typeof body.profile === "string" ? body.profile : undefined,
|
|
2173
|
+
periodStart: typeof body.periodStart === "number" ? body.periodStart : undefined,
|
|
2174
|
+
periodEndAt: typeof body.periodEndAt === "number" ? body.periodEndAt : undefined,
|
|
2175
|
+
summary: {
|
|
2176
|
+
...totals(summary),
|
|
2177
|
+
yuan: typeof summary.yuan === "number" ? summary.yuan : undefined
|
|
2178
|
+
},
|
|
2179
|
+
fiveHour: totals(body.fiveHour),
|
|
2180
|
+
weekly: totals(body.weekly),
|
|
2181
|
+
month: totals(body.monthly),
|
|
2182
|
+
daily: body.daily ? totals(body.daily) : undefined,
|
|
2183
|
+
account: body.account ? {
|
|
2184
|
+
fiveHour: meter(account.fiveHour),
|
|
2185
|
+
daily: account.daily ? meter(account.daily) : undefined,
|
|
2186
|
+
weekly: meter(account.weekly),
|
|
2187
|
+
monthly: meter(account.monthly)
|
|
2188
|
+
} : undefined,
|
|
2189
|
+
accountError: typeof body.accountError === "string" && body.accountError ? body.accountError : undefined,
|
|
2190
|
+
afpPerRequest: typeof body.afpPerRequest === "number" ? body.afpPerRequest : undefined,
|
|
2191
|
+
reconciledPct: typeof body.reconciledPct === "number" ? body.reconciledPct : undefined,
|
|
2192
|
+
models
|
|
2193
|
+
};
|
|
2194
|
+
}
|
|
2195
|
+
function monthPeriod(usage) {
|
|
2196
|
+
const {
|
|
2197
|
+
periodStart,
|
|
2198
|
+
periodEndAt
|
|
2199
|
+
} = usage;
|
|
2200
|
+
if (typeof periodStart !== "number" || typeof periodEndAt !== "number")
|
|
2201
|
+
return;
|
|
2202
|
+
const durSecs = Math.round((periodEndAt - periodStart) / 1000);
|
|
2203
|
+
if (durSecs <= 0)
|
|
2204
|
+
return;
|
|
2205
|
+
return {
|
|
2206
|
+
resetAt: periodEndAt,
|
|
2207
|
+
durSecs
|
|
2208
|
+
};
|
|
2209
|
+
}
|
|
2210
|
+
function afp(value) {
|
|
2211
|
+
return `${grouped(Math.round(value))} AFP`;
|
|
2212
|
+
}
|
|
2213
|
+
function grouped(value) {
|
|
2214
|
+
return String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
2215
|
+
}
|
|
2216
|
+
function brief(value) {
|
|
2217
|
+
const rounded = Math.round(value);
|
|
2218
|
+
const trim = (n) => n.toFixed(1).replace(/\.0$/, "");
|
|
2219
|
+
if (rounded >= 1e6)
|
|
2220
|
+
return `${trim(rounded / 1e6)}M`;
|
|
2221
|
+
if (rounded >= 1000)
|
|
2222
|
+
return `${trim(rounded / 1000)}K`;
|
|
2223
|
+
return String(rounded);
|
|
2224
|
+
}
|
|
2225
|
+
function meterRows(label, meter, local, now, durSecs) {
|
|
2226
|
+
const pct = meter.percent;
|
|
2227
|
+
const pctText = Number.isInteger(pct) ? String(pct) : pct.toFixed(1);
|
|
2228
|
+
return windowRows(label, {
|
|
2229
|
+
cap: meter.total > 0 ? meter.total : undefined,
|
|
2230
|
+
used: meter.used,
|
|
2231
|
+
resetAt: meter.resetAt,
|
|
2232
|
+
sharePct: pct,
|
|
2233
|
+
exceeded: pct >= 100 || meter.status !== "ok"
|
|
2234
|
+
}, now, durSecs, `${afp(local.afp)} local${local.requests > 0 ? ` \xB7 ${count(local.requests)} req` : ""}`, (used, cap) => `${brief(used)}/${brief(cap)} (${pctText}%)`);
|
|
2235
|
+
}
|
|
2236
|
+
function localRows(label, totals) {
|
|
2237
|
+
const detail = totals.requests > 0 ? ` \xB7 ${count(totals.requests)} req` : "";
|
|
2238
|
+
return [[label, `${afp(totals.afp)}${detail}`, "base"]];
|
|
2239
|
+
}
|
|
2240
|
+
function arkRows(usage, fallbackName) {
|
|
2241
|
+
if (!usage)
|
|
2242
|
+
return [];
|
|
2243
|
+
const now = Date.now();
|
|
2244
|
+
const rows = [["Plan", clip(`${usage.plan} \xB7 AFP plan${usage.profile ? ` \xB7 ${usage.profile}` : ""}`, valueWidth("Plan")), "base", true]];
|
|
2245
|
+
if (usage.accountError) {
|
|
2246
|
+
rows.push(["", clip(`usage API: ${usage.accountError}`, valueWidth("")), "warn"]);
|
|
2247
|
+
}
|
|
2248
|
+
const period = monthPeriod(usage);
|
|
2249
|
+
if (usage.account) {
|
|
2250
|
+
const account = usage.account;
|
|
2251
|
+
rows.push(...meterRows("5-hour", account.fiveHour, usage.fiveHour, now, FIVE_HOUR_SECS));
|
|
2252
|
+
if (account.daily) {
|
|
2253
|
+
rows.push(...meterRows("Daily", account.daily, usage.daily ?? usage.month, now, 86400));
|
|
2254
|
+
}
|
|
2255
|
+
rows.push(...meterRows("Weekly", account.weekly, usage.weekly, now, WEEKLY_SECS));
|
|
2256
|
+
rows.push(...meterRows("Monthly", account.monthly, usage.month, now, period?.durSecs ?? 0));
|
|
2257
|
+
} else {
|
|
2258
|
+
rows.push(...localRows("5-hour", usage.fiveHour));
|
|
2259
|
+
rows.push(...localRows("Weekly", usage.weekly));
|
|
2260
|
+
rows.push(...localRows("Monthly", usage.month));
|
|
2261
|
+
}
|
|
2262
|
+
const yuan = typeof usage.summary.yuan === "number" ? ` (${money(usage.summary.yuan)})` : "";
|
|
2263
|
+
rows.push(["Period", clip(`${count(usage.summary.requests)} requests \xB7 ${afp(usage.summary.afp)}${yuan}`, valueWidth("Period")), "base"]);
|
|
2264
|
+
if (typeof usage.afpPerRequest === "number" && usage.afpPerRequest > 0) {
|
|
2265
|
+
const drift = typeof usage.reconciledPct === "number" ? ` \xB7 ${usage.reconciledPct >= 0 ? "+" : ""}${usage.reconciledPct.toFixed(1)}% vs meter` : "";
|
|
2266
|
+
rows.push(["", clip(`${usage.afpPerRequest.toFixed(0)} AFP/request${drift}`, valueWidth("")), "muted"]);
|
|
2267
|
+
}
|
|
2268
|
+
rows.push(separator());
|
|
2269
|
+
if (!fallbackName)
|
|
2270
|
+
return rows;
|
|
2271
|
+
const model = usage.models.get(fallbackName);
|
|
2272
|
+
rows.push(["Model", clip(fallbackName, valueWidth("Model")), "strong", true]);
|
|
2273
|
+
rows.push(["AFP (this model)", model ? clip(`${afp(model.month.afp)} \xB7 ${count(model.month.requests)} req`, valueWidth("AFP (this model)")) : "no usage in this period", "base"]);
|
|
2274
|
+
if (model && usage.summary.afp > 0) {
|
|
2275
|
+
const share = model.month.afp / usage.summary.afp * 100;
|
|
2276
|
+
rows.push(["", clip(`${share.toFixed(1)}% of the period \xB7 coef ${model.coef.toFixed(2)}`, Math.min(ROW_WIDTH, valueWidth(""))), "muted"]);
|
|
2277
|
+
}
|
|
2278
|
+
return rows;
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2098
2281
|
// src/sidebar/data.ts
|
|
2099
2282
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
2100
2283
|
import { homedir as homedir3 } from "os";
|
|
2101
2284
|
import { dirname, join as join3 } from "path";
|
|
2102
2285
|
|
|
2103
2286
|
// src/sidebar/zen.ts
|
|
2104
|
-
function
|
|
2287
|
+
function totals2(value) {
|
|
2105
2288
|
const v = value ?? {};
|
|
2106
2289
|
const num = (key) => typeof v[key] === "number" ? v[key] : 0;
|
|
2107
2290
|
return {
|
|
@@ -2110,7 +2293,7 @@ function totals(value) {
|
|
|
2110
2293
|
tokens: num("tokens")
|
|
2111
2294
|
};
|
|
2112
2295
|
}
|
|
2113
|
-
function
|
|
2296
|
+
function meter2(value) {
|
|
2114
2297
|
const v = value ?? {};
|
|
2115
2298
|
return {
|
|
2116
2299
|
status: typeof v.status === "string" ? v.status : "ok",
|
|
@@ -2133,9 +2316,9 @@ function parseZenJson(text) {
|
|
|
2133
2316
|
id: raw.id,
|
|
2134
2317
|
provider: typeof raw.provider === "string" ? raw.provider : "",
|
|
2135
2318
|
limit: typeof raw.limit === "number" ? raw.limit : undefined,
|
|
2136
|
-
fiveHour:
|
|
2137
|
-
weekly:
|
|
2138
|
-
month:
|
|
2319
|
+
fiveHour: totals2(raw.fiveHour),
|
|
2320
|
+
weekly: totals2(raw.weekly),
|
|
2321
|
+
month: totals2(raw.month)
|
|
2139
2322
|
});
|
|
2140
2323
|
}
|
|
2141
2324
|
const top = body.totals ?? {};
|
|
@@ -2144,20 +2327,20 @@ function parseZenJson(text) {
|
|
|
2144
2327
|
periodEndAt: typeof body.periodEndAt === "number" ? body.periodEndAt : undefined,
|
|
2145
2328
|
source: typeof body.source === "string" ? body.source : undefined,
|
|
2146
2329
|
account: body.account ? {
|
|
2147
|
-
rolling:
|
|
2148
|
-
weekly:
|
|
2149
|
-
monthly:
|
|
2330
|
+
rolling: meter2(body.account.rolling),
|
|
2331
|
+
weekly: meter2(body.account.weekly),
|
|
2332
|
+
monthly: meter2(body.account.monthly)
|
|
2150
2333
|
} : undefined,
|
|
2151
2334
|
accountError: typeof body.accountError === "string" && body.accountError ? body.accountError : undefined,
|
|
2152
2335
|
totals: {
|
|
2153
|
-
fiveHour:
|
|
2154
|
-
weekly:
|
|
2155
|
-
month:
|
|
2336
|
+
fiveHour: totals2(top.fiveHour),
|
|
2337
|
+
weekly: totals2(top.weekly),
|
|
2338
|
+
month: totals2(top.month)
|
|
2156
2339
|
},
|
|
2157
2340
|
models
|
|
2158
2341
|
};
|
|
2159
2342
|
}
|
|
2160
|
-
function
|
|
2343
|
+
function monthPeriod2(usage) {
|
|
2161
2344
|
const {
|
|
2162
2345
|
periodStart,
|
|
2163
2346
|
periodEndAt
|
|
@@ -2213,7 +2396,7 @@ function zenRows(usage, meta, modelUsage, session, fallbackName, windows) {
|
|
|
2213
2396
|
const mine = usage.models.get(modelKey(fallbackName ?? "")) ?? (meta ? usage.models.get(modelKey(meta.name)) : undefined);
|
|
2214
2397
|
const limit = oc?.allowance ?? mine?.limit;
|
|
2215
2398
|
const cap = mine ? limit : undefined;
|
|
2216
|
-
const period =
|
|
2399
|
+
const period = monthPeriod2(usage);
|
|
2217
2400
|
if (usage.account) {
|
|
2218
2401
|
rows.push(...zenMeterRows("5-hour", usage.account.rolling, now, FIVE_HOUR_SECS, usage.totals.fiveHour.cost));
|
|
2219
2402
|
rows.push(...zenMeterRows("Weekly", usage.account.weekly, now, WEEKLY_SECS, usage.totals.weekly.cost));
|
|
@@ -2370,6 +2553,19 @@ async function loadUsage() {
|
|
|
2370
2553
|
async function loadZen(plan = OC_PLAN_DEFAULT) {
|
|
2371
2554
|
return parseZenJson(await runOcuse(zenArgs(plan), SIDEBAR_OPTS));
|
|
2372
2555
|
}
|
|
2556
|
+
var arkCache;
|
|
2557
|
+
async function loadArk() {
|
|
2558
|
+
const now = Date.now();
|
|
2559
|
+
if (arkCache && now - arkCache.at < ARK_SNAPSHOT_TTL_MS) {
|
|
2560
|
+
return arkCache.usage;
|
|
2561
|
+
}
|
|
2562
|
+
const usage = parseArkJson(await runArkuse("-1 --json", SIDEBAR_OPTS));
|
|
2563
|
+
arkCache = {
|
|
2564
|
+
at: now,
|
|
2565
|
+
usage
|
|
2566
|
+
};
|
|
2567
|
+
return usage;
|
|
2568
|
+
}
|
|
2373
2569
|
|
|
2374
2570
|
// src/sidebar/usageDb.ts
|
|
2375
2571
|
import { Database } from "bun:sqlite";
|
|
@@ -2561,16 +2757,20 @@ function sessionKind(providerID) {
|
|
|
2561
2757
|
return "go";
|
|
2562
2758
|
if (providerID === ZEN_PROVIDER_ID || providerID.startsWith(ZEN_PROVIDER_PREFIX))
|
|
2563
2759
|
return "zen";
|
|
2760
|
+
if (providerID.startsWith(ARK_PROVIDER_ID))
|
|
2761
|
+
return "ark";
|
|
2564
2762
|
return "other";
|
|
2565
2763
|
}
|
|
2566
2764
|
function shows(kind) {
|
|
2567
|
-
return kind === "ours" || kind === "go" || kind === "zen";
|
|
2765
|
+
return kind === "ours" || kind === "go" || kind === "zen" || kind === "ark";
|
|
2568
2766
|
}
|
|
2569
2767
|
function panelTitle(kind) {
|
|
2570
2768
|
if (kind === "ours")
|
|
2571
2769
|
return "Command Code";
|
|
2572
2770
|
if (kind === "zen")
|
|
2573
2771
|
return "OpenCode Zen";
|
|
2772
|
+
if (kind === "ark")
|
|
2773
|
+
return "Volcengine ARK";
|
|
2574
2774
|
return "OpenCode Go";
|
|
2575
2775
|
}
|
|
2576
2776
|
var lastSnapshot;
|
|
@@ -2613,9 +2813,17 @@ function rememberZen(usage) {
|
|
|
2613
2813
|
function seededZen() {
|
|
2614
2814
|
return lastZen;
|
|
2615
2815
|
}
|
|
2816
|
+
var lastArk;
|
|
2817
|
+
function rememberArk(usage) {
|
|
2818
|
+
lastArk = usage;
|
|
2819
|
+
}
|
|
2820
|
+
function seededArk() {
|
|
2821
|
+
return lastArk;
|
|
2822
|
+
}
|
|
2616
2823
|
function useRows(activeModelId, providerID, sessionID) {
|
|
2617
2824
|
const [usage, setUsage] = createSignal(seededRows());
|
|
2618
2825
|
const [zen, setZen] = createSignal(seededZen());
|
|
2826
|
+
const [ark, setArk] = createSignal(seededArk());
|
|
2619
2827
|
const [meta, setMeta] = createSignal(seededMeta());
|
|
2620
2828
|
const [modelUsage, setModelUsage] = createSignal(lastModelUsage);
|
|
2621
2829
|
const [sessionUsage, setSessionUsage] = createSignal();
|
|
@@ -2671,6 +2879,10 @@ function useRows(activeModelId, providerID, sessionID) {
|
|
|
2671
2879
|
setZen(snapshot);
|
|
2672
2880
|
refreshModelUsage(activeModelId());
|
|
2673
2881
|
refreshModelWindows(activeModelId());
|
|
2882
|
+
} else if (kind === "ark") {
|
|
2883
|
+
const snapshot = await loadArk();
|
|
2884
|
+
rememberArk(snapshot);
|
|
2885
|
+
setArk(snapshot);
|
|
2674
2886
|
}
|
|
2675
2887
|
} catch {} finally {
|
|
2676
2888
|
inFlight = false;
|
|
@@ -2715,6 +2927,9 @@ function useRows(activeModelId, providerID, sessionID) {
|
|
|
2715
2927
|
if (kind === "go" || kind === "zen") {
|
|
2716
2928
|
return zenRows(zen(), found, usageFor(id), sessionUsage(), fallbackName, modelWindows());
|
|
2717
2929
|
}
|
|
2930
|
+
if (kind === "ark") {
|
|
2931
|
+
return arkRows(ark(), fallbackName);
|
|
2932
|
+
}
|
|
2718
2933
|
const model = found ? {
|
|
2719
2934
|
...found,
|
|
2720
2935
|
tier: found.tier ?? (id ? tierFor(id) : undefined),
|
|
@@ -2834,8 +3049,35 @@ var commandCodeTui = {
|
|
|
2834
3049
|
message: text.trimEnd()
|
|
2835
3050
|
});
|
|
2836
3051
|
}
|
|
3052
|
+
}, {
|
|
3053
|
+
id: ARKUSE_USAGE_COMMAND_ID,
|
|
3054
|
+
title: "Volcengine ARK usage",
|
|
3055
|
+
group: "Command Code",
|
|
3056
|
+
slash: {
|
|
3057
|
+
name: "arkuse-usage",
|
|
3058
|
+
arguments: true
|
|
3059
|
+
},
|
|
3060
|
+
enabled: () => true,
|
|
3061
|
+
suggested: true,
|
|
3062
|
+
run: async (input) => {
|
|
3063
|
+
let text;
|
|
3064
|
+
try {
|
|
3065
|
+
text = await runArkuse(arkuseArgs(input));
|
|
3066
|
+
} catch (error) {
|
|
3067
|
+
ctx.ui.toast.show({
|
|
3068
|
+
title: "arkuse-usage failed",
|
|
3069
|
+
message: error instanceof Error ? error.message : String(error),
|
|
3070
|
+
variant: "error"
|
|
3071
|
+
});
|
|
3072
|
+
return;
|
|
3073
|
+
}
|
|
3074
|
+
await ctx.ui.dialog.alert({
|
|
3075
|
+
title: "Volcengine ARK usage",
|
|
3076
|
+
message: text.trimEnd()
|
|
3077
|
+
});
|
|
3078
|
+
}
|
|
2837
3079
|
}],
|
|
2838
|
-
bindings: [CMD_USAGE_COMMAND_ID, OCUSE_USAGE_COMMAND_ID]
|
|
3080
|
+
bindings: [CMD_USAGE_COMMAND_ID, OCUSE_USAGE_COMMAND_ID, ARKUSE_USAGE_COMMAND_ID]
|
|
2839
3081
|
}));
|
|
2840
3082
|
}
|
|
2841
3083
|
});
|
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.18",
|
|
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",
|