@jeffreyjyz/opencode-command-code 0.5.15 → 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 +267 -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));
|
|
@@ -2224,6 +2407,16 @@ function zenRows(usage, meta, modelUsage, session, fallbackName, windows) {
|
|
|
2224
2407
|
rows.push(...zenWindow("Monthly", mine?.month ?? usage.totals.month, cap, GO_WINDOW_SHARE.month, now, period?.durSecs ?? 0, period?.resetAt));
|
|
2225
2408
|
}
|
|
2226
2409
|
rows.push(["Period", `${count(usage.totals.month.requests)} requests \xB7 ${money(usage.totals.month.cost)}`, "base"]);
|
|
2410
|
+
const ranked = [...usage.models.values()].sort((a, b) => b.month.cost - a.month.cost).slice(0, 3);
|
|
2411
|
+
if (ranked.length > 1) {
|
|
2412
|
+
rows.push(["", "by model \xB7 this month", "muted"]);
|
|
2413
|
+
for (const entry of ranked) {
|
|
2414
|
+
const allowance = entry.limit;
|
|
2415
|
+
const share = typeof allowance === "number" && allowance > 0 ? ` (${(entry.month.cost / allowance * 100).toFixed(1)}%)` : "";
|
|
2416
|
+
const value = typeof allowance === "number" && allowance > 0 ? `${money(entry.month.cost)}/${money(allowance)}${share}` : money(entry.month.cost);
|
|
2417
|
+
rows.push([clip(entry.id, valueWidth("") - value.length - 1), value, "base"]);
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2227
2420
|
rows.push(separator());
|
|
2228
2421
|
const name = meta?.name ?? fallbackName;
|
|
2229
2422
|
if (!name)
|
|
@@ -2360,6 +2553,19 @@ async function loadUsage() {
|
|
|
2360
2553
|
async function loadZen(plan = OC_PLAN_DEFAULT) {
|
|
2361
2554
|
return parseZenJson(await runOcuse(zenArgs(plan), SIDEBAR_OPTS));
|
|
2362
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
|
+
}
|
|
2363
2569
|
|
|
2364
2570
|
// src/sidebar/usageDb.ts
|
|
2365
2571
|
import { Database } from "bun:sqlite";
|
|
@@ -2551,16 +2757,20 @@ function sessionKind(providerID) {
|
|
|
2551
2757
|
return "go";
|
|
2552
2758
|
if (providerID === ZEN_PROVIDER_ID || providerID.startsWith(ZEN_PROVIDER_PREFIX))
|
|
2553
2759
|
return "zen";
|
|
2760
|
+
if (providerID.startsWith(ARK_PROVIDER_ID))
|
|
2761
|
+
return "ark";
|
|
2554
2762
|
return "other";
|
|
2555
2763
|
}
|
|
2556
2764
|
function shows(kind) {
|
|
2557
|
-
return kind === "ours" || kind === "go" || kind === "zen";
|
|
2765
|
+
return kind === "ours" || kind === "go" || kind === "zen" || kind === "ark";
|
|
2558
2766
|
}
|
|
2559
2767
|
function panelTitle(kind) {
|
|
2560
2768
|
if (kind === "ours")
|
|
2561
2769
|
return "Command Code";
|
|
2562
2770
|
if (kind === "zen")
|
|
2563
2771
|
return "OpenCode Zen";
|
|
2772
|
+
if (kind === "ark")
|
|
2773
|
+
return "Volcengine ARK";
|
|
2564
2774
|
return "OpenCode Go";
|
|
2565
2775
|
}
|
|
2566
2776
|
var lastSnapshot;
|
|
@@ -2603,9 +2813,17 @@ function rememberZen(usage) {
|
|
|
2603
2813
|
function seededZen() {
|
|
2604
2814
|
return lastZen;
|
|
2605
2815
|
}
|
|
2816
|
+
var lastArk;
|
|
2817
|
+
function rememberArk(usage) {
|
|
2818
|
+
lastArk = usage;
|
|
2819
|
+
}
|
|
2820
|
+
function seededArk() {
|
|
2821
|
+
return lastArk;
|
|
2822
|
+
}
|
|
2606
2823
|
function useRows(activeModelId, providerID, sessionID) {
|
|
2607
2824
|
const [usage, setUsage] = createSignal(seededRows());
|
|
2608
2825
|
const [zen, setZen] = createSignal(seededZen());
|
|
2826
|
+
const [ark, setArk] = createSignal(seededArk());
|
|
2609
2827
|
const [meta, setMeta] = createSignal(seededMeta());
|
|
2610
2828
|
const [modelUsage, setModelUsage] = createSignal(lastModelUsage);
|
|
2611
2829
|
const [sessionUsage, setSessionUsage] = createSignal();
|
|
@@ -2661,6 +2879,10 @@ function useRows(activeModelId, providerID, sessionID) {
|
|
|
2661
2879
|
setZen(snapshot);
|
|
2662
2880
|
refreshModelUsage(activeModelId());
|
|
2663
2881
|
refreshModelWindows(activeModelId());
|
|
2882
|
+
} else if (kind === "ark") {
|
|
2883
|
+
const snapshot = await loadArk();
|
|
2884
|
+
rememberArk(snapshot);
|
|
2885
|
+
setArk(snapshot);
|
|
2664
2886
|
}
|
|
2665
2887
|
} catch {} finally {
|
|
2666
2888
|
inFlight = false;
|
|
@@ -2705,6 +2927,9 @@ function useRows(activeModelId, providerID, sessionID) {
|
|
|
2705
2927
|
if (kind === "go" || kind === "zen") {
|
|
2706
2928
|
return zenRows(zen(), found, usageFor(id), sessionUsage(), fallbackName, modelWindows());
|
|
2707
2929
|
}
|
|
2930
|
+
if (kind === "ark") {
|
|
2931
|
+
return arkRows(ark(), fallbackName);
|
|
2932
|
+
}
|
|
2708
2933
|
const model = found ? {
|
|
2709
2934
|
...found,
|
|
2710
2935
|
tier: found.tier ?? (id ? tierFor(id) : undefined),
|
|
@@ -2824,8 +3049,35 @@ var commandCodeTui = {
|
|
|
2824
3049
|
message: text.trimEnd()
|
|
2825
3050
|
});
|
|
2826
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
|
+
}
|
|
2827
3079
|
}],
|
|
2828
|
-
bindings: [CMD_USAGE_COMMAND_ID, OCUSE_USAGE_COMMAND_ID]
|
|
3080
|
+
bindings: [CMD_USAGE_COMMAND_ID, OCUSE_USAGE_COMMAND_ID, ARKUSE_USAGE_COMMAND_ID]
|
|
2829
3081
|
}));
|
|
2830
3082
|
}
|
|
2831
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",
|