@slkiser/opencode-quota 3.11.2 → 4.0.1
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/README.md +92 -62
- package/dist/bin/opencode-quota.d.ts.map +1 -1
- package/dist/bin/opencode-quota.js +16 -7
- package/dist/bin/opencode-quota.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/cli-show.d.ts.map +1 -1
- package/dist/lib/cli-show.js +11 -7
- package/dist/lib/cli-show.js.map +1 -1
- package/dist/lib/command-surfaces.d.ts +10 -0
- package/dist/lib/command-surfaces.d.ts.map +1 -0
- package/dist/lib/command-surfaces.js +9 -0
- package/dist/lib/command-surfaces.js.map +1 -0
- package/dist/lib/config-file-utils.d.ts +5 -0
- package/dist/lib/config-file-utils.d.ts.map +1 -1
- package/dist/lib/config-file-utils.js +20 -3
- package/dist/lib/config-file-utils.js.map +1 -1
- package/dist/lib/config.d.ts +5 -3
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +124 -32
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/copilot.d.ts +19 -12
- package/dist/lib/copilot.d.ts.map +1 -1
- package/dist/lib/copilot.js +462 -566
- package/dist/lib/copilot.js.map +1 -1
- package/dist/lib/display-sanitize.d.ts.map +1 -1
- package/dist/lib/display-sanitize.js +13 -0
- package/dist/lib/display-sanitize.js.map +1 -1
- package/dist/lib/entries.d.ts +55 -4
- package/dist/lib/entries.d.ts.map +1 -1
- package/dist/lib/entries.js.map +1 -1
- package/dist/lib/init-installer.d.ts +11 -1
- package/dist/lib/init-installer.d.ts.map +1 -1
- package/dist/lib/init-installer.js +524 -158
- package/dist/lib/init-installer.js.map +1 -1
- package/dist/lib/maintainer-announcements.d.ts.map +1 -1
- package/dist/lib/maintainer-announcements.js +7 -15
- package/dist/lib/maintainer-announcements.js.map +1 -1
- package/dist/lib/openai.d.ts.map +1 -1
- package/dist/lib/openai.js +15 -0
- package/dist/lib/openai.js.map +1 -1
- package/dist/lib/opencode-config-editor.d.ts +59 -0
- package/dist/lib/opencode-config-editor.d.ts.map +1 -0
- package/dist/lib/opencode-config-editor.js +320 -0
- package/dist/lib/opencode-config-editor.js.map +1 -0
- package/dist/lib/opencode-config-providers.d.ts +18 -0
- package/dist/lib/opencode-config-providers.d.ts.map +1 -1
- package/dist/lib/opencode-config-providers.js +75 -4
- package/dist/lib/opencode-config-providers.js.map +1 -1
- package/dist/lib/opencode-runtime-paths.d.ts.map +1 -1
- package/dist/lib/opencode-runtime-paths.js +10 -3
- package/dist/lib/opencode-runtime-paths.js.map +1 -1
- package/dist/lib/opencode-storage.d.ts +10 -0
- package/dist/lib/opencode-storage.d.ts.map +1 -1
- package/dist/lib/opencode-storage.js +75 -0
- package/dist/lib/opencode-storage.js.map +1 -1
- package/dist/lib/provider-add-command.d.ts +35 -0
- package/dist/lib/provider-add-command.d.ts.map +1 -0
- package/dist/lib/provider-add-command.js +212 -0
- package/dist/lib/provider-add-command.js.map +1 -0
- package/dist/lib/provider-add.d.ts +21 -0
- package/dist/lib/provider-add.d.ts.map +1 -0
- package/dist/lib/provider-add.js +219 -0
- package/dist/lib/provider-add.js.map +1 -0
- package/dist/lib/provider-metadata.d.ts +1 -1
- package/dist/lib/provider-metadata.d.ts.map +1 -1
- package/dist/lib/provider-metadata.js +11 -5
- package/dist/lib/provider-metadata.js.map +1 -1
- package/dist/lib/quota-command-format.d.ts +2 -0
- package/dist/lib/quota-command-format.d.ts.map +1 -1
- package/dist/lib/quota-command-format.js +94 -26
- package/dist/lib/quota-command-format.js.map +1 -1
- package/dist/lib/quota-dialog-commands.d.ts.map +1 -1
- package/dist/lib/quota-dialog-commands.js +8 -4
- package/dist/lib/quota-dialog-commands.js.map +1 -1
- package/dist/lib/quota-export-types.d.ts +48 -27
- package/dist/lib/quota-export-types.d.ts.map +1 -1
- package/dist/lib/quota-export-types.js +0 -7
- package/dist/lib/quota-export-types.js.map +1 -1
- package/dist/lib/quota-export.d.ts.map +1 -1
- package/dist/lib/quota-export.js +63 -16
- package/dist/lib/quota-export.js.map +1 -1
- package/dist/lib/quota-providers-local.d.ts +55 -0
- package/dist/lib/quota-providers-local.d.ts.map +1 -0
- package/dist/lib/quota-providers-local.js +313 -0
- package/dist/lib/quota-providers-local.js.map +1 -0
- package/dist/lib/quota-providers-remote.d.ts +28 -0
- package/dist/lib/quota-providers-remote.d.ts.map +1 -0
- package/dist/lib/quota-providers-remote.js +682 -0
- package/dist/lib/quota-providers-remote.js.map +1 -0
- package/dist/lib/quota-providers.d.ts +158 -0
- package/dist/lib/quota-providers.d.ts.map +1 -0
- package/dist/lib/quota-providers.js +1167 -0
- package/dist/lib/quota-providers.js.map +1 -0
- package/dist/lib/quota-render-data.d.ts +1 -0
- package/dist/lib/quota-render-data.d.ts.map +1 -1
- package/dist/lib/quota-render-data.js +35 -16
- package/dist/lib/quota-render-data.js.map +1 -1
- package/dist/lib/quota-runtime-context.d.ts.map +1 -1
- package/dist/lib/quota-runtime-context.js +3 -4
- package/dist/lib/quota-runtime-context.js.map +1 -1
- package/dist/lib/quota-state.d.ts +5 -2
- package/dist/lib/quota-state.d.ts.map +1 -1
- package/dist/lib/quota-state.js +268 -51
- package/dist/lib/quota-state.js.map +1 -1
- package/dist/lib/quota-status.d.ts +2 -1
- package/dist/lib/quota-status.d.ts.map +1 -1
- package/dist/lib/quota-status.js +247 -69
- package/dist/lib/quota-status.js.map +1 -1
- package/dist/lib/qwen-local-quota.d.ts +12 -11
- package/dist/lib/qwen-local-quota.d.ts.map +1 -1
- package/dist/lib/qwen-local-quota.js +82 -87
- package/dist/lib/qwen-local-quota.js.map +1 -1
- package/dist/lib/scoped-update.d.ts.map +1 -1
- package/dist/lib/scoped-update.js +32 -22
- package/dist/lib/scoped-update.js.map +1 -1
- package/dist/lib/tui-runtime.d.ts +2 -0
- package/dist/lib/tui-runtime.d.ts.map +1 -1
- package/dist/lib/tui-runtime.js +33 -9
- package/dist/lib/tui-runtime.js.map +1 -1
- package/dist/lib/types.d.ts +51 -15
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js +2 -1
- package/dist/lib/types.js.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +90 -111
- package/dist/plugin.js.map +1 -1
- package/dist/providers/alibaba-coding-plan.d.ts.map +1 -1
- package/dist/providers/alibaba-coding-plan.js +35 -4
- package/dist/providers/alibaba-coding-plan.js.map +1 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +13 -1
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/chutes.d.ts.map +1 -1
- package/dist/providers/chutes.js +6 -0
- package/dist/providers/chutes.js.map +1 -1
- package/dist/providers/copilot.d.ts +2 -1
- package/dist/providers/copilot.d.ts.map +1 -1
- package/dist/providers/copilot.js +143 -60
- package/dist/providers/copilot.js.map +1 -1
- package/dist/providers/cursor.d.ts.map +1 -1
- package/dist/providers/cursor.js +30 -1
- package/dist/providers/cursor.js.map +1 -1
- package/dist/providers/deepseek.d.ts.map +1 -1
- package/dist/providers/deepseek.js +13 -1
- package/dist/providers/deepseek.js.map +1 -1
- package/dist/providers/google-agy.d.ts.map +1 -1
- package/dist/providers/google-agy.js +7 -1
- package/dist/providers/google-agy.js.map +1 -1
- package/dist/providers/google-antigravity.d.ts.map +1 -1
- package/dist/providers/google-antigravity.js +10 -2
- package/dist/providers/google-antigravity.js.map +1 -1
- package/dist/providers/google-gemini-cli.d.ts.map +1 -1
- package/dist/providers/google-gemini-cli.js +8 -2
- package/dist/providers/google-gemini-cli.js.map +1 -1
- package/dist/providers/kimi-code.d.ts.map +1 -1
- package/dist/providers/kimi-code.js +6 -0
- package/dist/providers/kimi-code.js.map +1 -1
- package/dist/providers/minimax-coding-plan.d.ts.map +1 -1
- package/dist/providers/minimax-coding-plan.js +41 -15
- package/dist/providers/minimax-coding-plan.js.map +1 -1
- package/dist/providers/nanogpt.d.ts.map +1 -1
- package/dist/providers/nanogpt.js +19 -1
- package/dist/providers/nanogpt.js.map +1 -1
- package/dist/providers/ollama-cloud.d.ts.map +1 -1
- package/dist/providers/ollama-cloud.js +12 -0
- package/dist/providers/ollama-cloud.js.map +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +6 -0
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/opencode-go.d.ts.map +1 -1
- package/dist/providers/opencode-go.js +9 -1
- package/dist/providers/opencode-go.js.map +1 -1
- package/dist/providers/quota-providers.d.ts +6 -0
- package/dist/providers/quota-providers.d.ts.map +1 -0
- package/dist/providers/quota-providers.js +279 -0
- package/dist/providers/quota-providers.js.map +1 -0
- package/dist/providers/qwen-code.d.ts.map +1 -1
- package/dist/providers/qwen-code.js +29 -3
- package/dist/providers/qwen-code.js.map +1 -1
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js +2 -0
- package/dist/providers/registry.js.map +1 -1
- package/dist/providers/result-helpers.d.ts +2 -1
- package/dist/providers/result-helpers.d.ts.map +1 -1
- package/dist/providers/result-helpers.js +6 -1
- package/dist/providers/result-helpers.js.map +1 -1
- package/dist/providers/synthetic.d.ts.map +1 -1
- package/dist/providers/synthetic.js +7 -1
- package/dist/providers/synthetic.js.map +1 -1
- package/dist/providers/zai.d.ts.map +1 -1
- package/dist/providers/zai.js +7 -1
- package/dist/providers/zai.js.map +1 -1
- package/dist/providers/zhipu.d.ts.map +1 -1
- package/dist/providers/zhipu.js +7 -1
- package/dist/providers/zhipu.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +345 -41
- package/dist/tui.tsx +267 -18
- package/package.json +28 -21
package/dist/tui.tsx
CHANGED
|
@@ -8,6 +8,8 @@ import type {
|
|
|
8
8
|
} from "@opencode-ai/plugin/tui";
|
|
9
9
|
import { Show, createEffect, createSignal, onCleanup } from "solid-js";
|
|
10
10
|
|
|
11
|
+
import type { SessionTokenError } from "./lib/quota-status.js";
|
|
12
|
+
import type { TuiCommandDisplay } from "./lib/types.js";
|
|
11
13
|
import type {
|
|
12
14
|
CompactStatusState,
|
|
13
15
|
HomeBottomState,
|
|
@@ -25,11 +27,21 @@ import {
|
|
|
25
27
|
} from "./lib/tui-panel-state.js";
|
|
26
28
|
import { getSidebarBodyLineColor } from "./lib/tui-line-style.js";
|
|
27
29
|
import {
|
|
30
|
+
createTuiQuotaClient,
|
|
31
|
+
getTuiRuntimeRootHints,
|
|
32
|
+
getTuiSessionModelMeta,
|
|
28
33
|
loadTuiHomeBottomStatus,
|
|
29
34
|
loadTuiSessionQuotaSurfaces,
|
|
35
|
+
normalizeTuiSessionID,
|
|
30
36
|
resolveTuiSurfaceRegistration,
|
|
31
37
|
writeTuiQuotaExportIfEnabled,
|
|
32
38
|
} from "./lib/tui-runtime.js";
|
|
39
|
+
import {
|
|
40
|
+
QUOTA_DIALOG_COMMANDS,
|
|
41
|
+
buildQuotaDialogCommandOutput,
|
|
42
|
+
type QuotaDialogCommandId,
|
|
43
|
+
type QuotaDialogCommandSpec,
|
|
44
|
+
} from "./lib/quota-dialog-commands.js";
|
|
33
45
|
|
|
34
46
|
const id = "@slkiser/opencode-quota";
|
|
35
47
|
// Place Quota near the top so variable-height built-in sections
|
|
@@ -41,6 +53,11 @@ const EVENT_REFRESH_DELAYS_MS = [150, 600] as const;
|
|
|
41
53
|
const MOUNT_RECOVERY_DELAYS_MS = [500, 1_500, 4_000] as const;
|
|
42
54
|
|
|
43
55
|
type TuiPromptRefCallback = (ref: TuiPromptRef | undefined) => void;
|
|
56
|
+
type DialogSize = "medium" | "large" | "xlarge";
|
|
57
|
+
|
|
58
|
+
type QuotaDialogCommandState = {
|
|
59
|
+
lastSessionTokenError?: SessionTokenError;
|
|
60
|
+
};
|
|
44
61
|
type SessionQuotaResource = {
|
|
45
62
|
sessionID: string;
|
|
46
63
|
sidebar: () => SidebarPanelState;
|
|
@@ -197,10 +214,13 @@ function acquireSessionQuotaResource(api: TuiPluginApi, sessionID: string): Sess
|
|
|
197
214
|
return next;
|
|
198
215
|
}
|
|
199
216
|
|
|
200
|
-
function createHomeBottomResource(
|
|
217
|
+
function createHomeBottomResource(
|
|
218
|
+
api: TuiPluginApi,
|
|
219
|
+
compactHomeBottomEnabled: boolean,
|
|
220
|
+
): HomeBottomResource {
|
|
201
221
|
const [bottom, setBottom] = createSignal<HomeBottomState>({
|
|
202
222
|
status: "loading",
|
|
203
|
-
compact: { status: "loading" },
|
|
223
|
+
compact: compactHomeBottomEnabled ? { status: "loading" } : { status: "disabled" },
|
|
204
224
|
});
|
|
205
225
|
|
|
206
226
|
let refCount = 0;
|
|
@@ -295,11 +315,14 @@ function createHomeBottomResource(api: TuiPluginApi): HomeBottomResource {
|
|
|
295
315
|
return resource;
|
|
296
316
|
}
|
|
297
317
|
|
|
298
|
-
function acquireHomeBottomResource(
|
|
318
|
+
function acquireHomeBottomResource(
|
|
319
|
+
api: TuiPluginApi,
|
|
320
|
+
compactHomeBottomEnabled: boolean,
|
|
321
|
+
): HomeBottomResource {
|
|
299
322
|
const existing = homeResources.get(api);
|
|
300
323
|
if (existing) return existing.retain();
|
|
301
324
|
|
|
302
|
-
const next = createHomeBottomResource(api).retain();
|
|
325
|
+
const next = createHomeBottomResource(api, compactHomeBottomEnabled).retain();
|
|
303
326
|
homeResources.set(api, next);
|
|
304
327
|
return next;
|
|
305
328
|
}
|
|
@@ -435,30 +458,251 @@ function SessionPromptWithCompactStatus(props: {
|
|
|
435
458
|
);
|
|
436
459
|
}
|
|
437
460
|
|
|
438
|
-
function HomeBottomView(props: { api: TuiPluginApi }) {
|
|
439
|
-
const resource = acquireHomeBottomResource(props.api);
|
|
461
|
+
function HomeBottomView(props: { api: TuiPluginApi; compactHomeBottomEnabled: boolean }) {
|
|
462
|
+
const resource = acquireHomeBottomResource(props.api, props.compactHomeBottomEnabled);
|
|
440
463
|
onCleanup(() => resource.release());
|
|
441
464
|
|
|
442
465
|
const announcement = () => getHomeBottomAnnouncementText(resource.bottom());
|
|
443
466
|
const compact = () => resource.bottom().compact;
|
|
467
|
+
const visible = () => shouldRenderHomeBottom(resource.bottom());
|
|
444
468
|
|
|
445
469
|
return (
|
|
446
|
-
<
|
|
447
|
-
<
|
|
470
|
+
<box gap={0}>
|
|
471
|
+
<Show when={visible()}>
|
|
448
472
|
<text> </text>
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
</
|
|
455
|
-
</
|
|
473
|
+
</Show>
|
|
474
|
+
<Show when={visible() && announcement()}>
|
|
475
|
+
<box flexDirection="row" justifyContent="center">
|
|
476
|
+
<text fg={props.api.theme.current.textMuted} wrapMode="none">
|
|
477
|
+
{announcement()}
|
|
478
|
+
</text>
|
|
479
|
+
</box>
|
|
480
|
+
</Show>
|
|
481
|
+
<Show when={visible()}>
|
|
456
482
|
<CompactStatusLine api={props.api} panel={compact} justifyContent="center" />
|
|
457
|
-
</
|
|
458
|
-
</
|
|
483
|
+
</Show>
|
|
484
|
+
</box>
|
|
459
485
|
);
|
|
460
486
|
}
|
|
461
487
|
|
|
488
|
+
function getActiveTuiSessionID(api: TuiPluginApi): string | undefined {
|
|
489
|
+
if (api.route.current.name !== "session") return undefined;
|
|
490
|
+
return normalizeTuiSessionID(api.route.current.params?.sessionID);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function getTuiCommandArguments(input: unknown): string | undefined {
|
|
494
|
+
if (!input || typeof input !== "object") return undefined;
|
|
495
|
+
const record = input as Record<string, unknown>;
|
|
496
|
+
for (const key of ["arguments", "args", "query"] as const) {
|
|
497
|
+
const value = record[key];
|
|
498
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
499
|
+
}
|
|
500
|
+
return undefined;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function CommandLoadingDialog(props: { api: TuiPluginApi; title: string }) {
|
|
504
|
+
return (
|
|
505
|
+
<box gap={1} paddingLeft={2} paddingRight={2} paddingBottom={1}>
|
|
506
|
+
<text fg={props.api.theme.current.text}>
|
|
507
|
+
<b>{props.title}</b>
|
|
508
|
+
</text>
|
|
509
|
+
<text fg={props.api.theme.current.textMuted}>Loading deterministic local output…</text>
|
|
510
|
+
</box>
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function CommandOutputDialog(props: { api: TuiPluginApi; title: string; output: string }) {
|
|
515
|
+
const lines = () => props.output.split("\n");
|
|
516
|
+
const bodyHeight = () => Math.min(28, Math.max(6, lines().length));
|
|
517
|
+
return (
|
|
518
|
+
<box gap={1} width="100%" flexGrow={1} paddingLeft={2} paddingRight={2} paddingBottom={1}>
|
|
519
|
+
<text fg={props.api.theme.current.text}>
|
|
520
|
+
<b>{props.title}</b>
|
|
521
|
+
</text>
|
|
522
|
+
<scrollbox width="100%" flexGrow={1} minHeight={bodyHeight()} maxHeight={28}>
|
|
523
|
+
<box gap={0} width="100%" minWidth={0}>
|
|
524
|
+
{lines().map((line) => (
|
|
525
|
+
<text fg={props.api.theme.current.text} wrapMode="word" width="100%">
|
|
526
|
+
{line || " "}
|
|
527
|
+
</text>
|
|
528
|
+
))}
|
|
529
|
+
</box>
|
|
530
|
+
</scrollbox>
|
|
531
|
+
<text fg={props.api.theme.current.textMuted}>esc closes</text>
|
|
532
|
+
</box>
|
|
533
|
+
);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
function CommandErrorDialog(props: { api: TuiPluginApi; title: string; error: unknown }) {
|
|
537
|
+
const message = props.error instanceof Error ? props.error.message : String(props.error);
|
|
538
|
+
return (
|
|
539
|
+
<box gap={1} paddingLeft={2} paddingRight={2} paddingBottom={1}>
|
|
540
|
+
<text fg={props.api.theme.current.text}>
|
|
541
|
+
<b>{props.title}</b>
|
|
542
|
+
</text>
|
|
543
|
+
<text fg={props.api.theme.current.text}>OpenCode Quota command failed.</text>
|
|
544
|
+
<text fg={props.api.theme.current.textMuted} wrapMode="none">
|
|
545
|
+
{message || "Unknown error"}
|
|
546
|
+
</text>
|
|
547
|
+
<text fg={props.api.theme.current.textMuted}>esc closes</text>
|
|
548
|
+
</box>
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
function getCommandPromptCopy(spec: QuotaDialogCommandSpec): {
|
|
553
|
+
title: string;
|
|
554
|
+
placeholder: string;
|
|
555
|
+
description: string;
|
|
556
|
+
} {
|
|
557
|
+
switch (spec.id) {
|
|
558
|
+
case "tokens_between":
|
|
559
|
+
return {
|
|
560
|
+
title: "OpenCode Quota Token Range",
|
|
561
|
+
placeholder: "YYYY-MM-DD YYYY-MM-DD",
|
|
562
|
+
description: "Enter start and end dates, for example: 2026-01-01 2026-01-15",
|
|
563
|
+
};
|
|
564
|
+
case "quota_status":
|
|
565
|
+
return {
|
|
566
|
+
title: "OpenCode Quota Status Options",
|
|
567
|
+
placeholder: 'Optional JSON, e.g. {"refreshGoogleTokens":true}',
|
|
568
|
+
description: "Leave blank for normal diagnostics, or enter one JSON options object.",
|
|
569
|
+
};
|
|
570
|
+
default:
|
|
571
|
+
return {
|
|
572
|
+
title: spec.title,
|
|
573
|
+
placeholder: "Optional arguments",
|
|
574
|
+
description: "Leave blank to run with no arguments.",
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
function replaceDialog(api: TuiPluginApi, size: DialogSize, render: () => JSX.Element): void {
|
|
580
|
+
api.ui.dialog.replace(render);
|
|
581
|
+
// OpenCode dialog.replace() resets size to medium.
|
|
582
|
+
api.ui.dialog.setSize(size);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
async function runQuotaDialogCommandAsync(
|
|
586
|
+
api: TuiPluginApi,
|
|
587
|
+
command: QuotaDialogCommandId,
|
|
588
|
+
commandDisplay: TuiCommandDisplay,
|
|
589
|
+
rawInput?: unknown,
|
|
590
|
+
state?: QuotaDialogCommandState,
|
|
591
|
+
): Promise<void> {
|
|
592
|
+
const spec = QUOTA_DIALOG_COMMANDS.find((item) => item.id === command)!;
|
|
593
|
+
const argumentsText = getTuiCommandArguments(rawInput);
|
|
594
|
+
const sessionID = getActiveTuiSessionID(api);
|
|
595
|
+
|
|
596
|
+
if (spec.acceptsArguments && rawInput === undefined) {
|
|
597
|
+
const prompt = getCommandPromptCopy(spec);
|
|
598
|
+
replaceDialog(api, "medium", () => (
|
|
599
|
+
<api.ui.DialogPrompt
|
|
600
|
+
title={prompt.title}
|
|
601
|
+
placeholder={prompt.placeholder}
|
|
602
|
+
description={() => (
|
|
603
|
+
<text fg={api.theme.current.textMuted} wrapMode="word">
|
|
604
|
+
{prompt.description}
|
|
605
|
+
</text>
|
|
606
|
+
)}
|
|
607
|
+
onCancel={() => api.ui.dialog.clear()}
|
|
608
|
+
onConfirm={(value) => {
|
|
609
|
+
void runQuotaDialogCommandAsync(
|
|
610
|
+
api,
|
|
611
|
+
command,
|
|
612
|
+
commandDisplay,
|
|
613
|
+
{ arguments: value.trim() },
|
|
614
|
+
state,
|
|
615
|
+
);
|
|
616
|
+
}}
|
|
617
|
+
/>
|
|
618
|
+
));
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const destination =
|
|
623
|
+
commandDisplay === "inline" && sessionID
|
|
624
|
+
? { type: "inline" as const, sessionID }
|
|
625
|
+
: { type: "dialog" as const };
|
|
626
|
+
if (destination.type === "dialog") {
|
|
627
|
+
replaceDialog(api, spec.dialogSize, () => (
|
|
628
|
+
<CommandLoadingDialog api={api} title={spec.title} />
|
|
629
|
+
));
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
try {
|
|
633
|
+
const result = await buildQuotaDialogCommandOutput({
|
|
634
|
+
command,
|
|
635
|
+
arguments: argumentsText,
|
|
636
|
+
client: createTuiQuotaClient(api),
|
|
637
|
+
roots: getTuiRuntimeRootHints(api),
|
|
638
|
+
sessionID,
|
|
639
|
+
resolveSessionMeta: (id) => getTuiSessionModelMeta(api, id),
|
|
640
|
+
lastSessionTokenError: state?.lastSessionTokenError,
|
|
641
|
+
setLastSessionTokenError: state
|
|
642
|
+
? (error) => {
|
|
643
|
+
state.lastSessionTokenError = error;
|
|
644
|
+
}
|
|
645
|
+
: undefined,
|
|
646
|
+
log: async (message, extra) => {
|
|
647
|
+
await api.client.app.log({
|
|
648
|
+
body: {
|
|
649
|
+
service: "quota-toast",
|
|
650
|
+
level: "debug",
|
|
651
|
+
message,
|
|
652
|
+
extra,
|
|
653
|
+
},
|
|
654
|
+
});
|
|
655
|
+
},
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
if (result.state === "noop") {
|
|
659
|
+
if (destination.type === "dialog") api.ui.dialog.clear();
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
if (destination.type === "inline") {
|
|
664
|
+
await api.client.session.prompt({
|
|
665
|
+
sessionID: destination.sessionID,
|
|
666
|
+
noReply: true,
|
|
667
|
+
parts: [{ type: "text", text: result.output, ignored: true }],
|
|
668
|
+
});
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
replaceDialog(api, result.dialogSize, () => (
|
|
673
|
+
<CommandOutputDialog api={api} title={result.title} output={result.output} />
|
|
674
|
+
));
|
|
675
|
+
} catch (error) {
|
|
676
|
+
replaceDialog(api, "large", () => (
|
|
677
|
+
<CommandErrorDialog api={api} title={spec.title} error={error} />
|
|
678
|
+
));
|
|
679
|
+
api.ui.toast({
|
|
680
|
+
variant: "error",
|
|
681
|
+
message: "OpenCode Quota command failed",
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function registerQuotaDialogCommands(api: TuiPluginApi, commandDisplay: TuiCommandDisplay): void {
|
|
687
|
+
const commandState: QuotaDialogCommandState = {};
|
|
688
|
+
const dispose = api.keymap.registerLayer({
|
|
689
|
+
commands: QUOTA_DIALOG_COMMANDS.map((spec) => ({
|
|
690
|
+
namespace: "palette",
|
|
691
|
+
name: `opencode-quota.${spec.id}`,
|
|
692
|
+
title: spec.title,
|
|
693
|
+
desc: spec.description,
|
|
694
|
+
category: "OpenCode Quota",
|
|
695
|
+
slashName: spec.slashName,
|
|
696
|
+
run(input?: unknown) {
|
|
697
|
+
void runQuotaDialogCommandAsync(api, spec.id, commandDisplay, input, commandState);
|
|
698
|
+
},
|
|
699
|
+
})),
|
|
700
|
+
bindings: [],
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
api.lifecycle.onDispose(dispose);
|
|
704
|
+
}
|
|
705
|
+
|
|
462
706
|
function registerSidebarSlots(api: TuiPluginApi): void {
|
|
463
707
|
api.slots.register({
|
|
464
708
|
order: SIDEBAR_ORDER,
|
|
@@ -475,10 +719,13 @@ const tui: TuiPlugin = async (api) => {
|
|
|
475
719
|
try {
|
|
476
720
|
surfaceRegistration = await resolveTuiSurfaceRegistration(api);
|
|
477
721
|
} catch {
|
|
722
|
+
registerQuotaDialogCommands(api, "inline");
|
|
478
723
|
registerSidebarSlots(api);
|
|
479
724
|
return;
|
|
480
725
|
}
|
|
481
726
|
|
|
727
|
+
registerQuotaDialogCommands(api, surfaceRegistration.commandDisplay);
|
|
728
|
+
|
|
482
729
|
if (surfaceRegistration.sidebar.enabled) {
|
|
483
730
|
registerSidebarSlots(api);
|
|
484
731
|
}
|
|
@@ -511,7 +758,9 @@ const tui: TuiPlugin = async (api) => {
|
|
|
511
758
|
}
|
|
512
759
|
|
|
513
760
|
if (surfaceRegistration.homeBottom) {
|
|
514
|
-
compactSlots.home_bottom = () =>
|
|
761
|
+
compactSlots.home_bottom = () => (
|
|
762
|
+
<HomeBottomView api={api} compactHomeBottomEnabled={surfaceRegistration.compact.homeBottom} />
|
|
763
|
+
);
|
|
515
764
|
}
|
|
516
765
|
|
|
517
766
|
if (Object.keys(compactSlots).length > 0) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slkiser/opencode-quota",
|
|
3
|
-
"version": "
|
|
4
|
-
"packageManager": "pnpm@11.0.0",
|
|
3
|
+
"version": "4.0.1",
|
|
5
4
|
"description": "OpenCode quota & tokens usage with zero context window pollution. Supports GitHub Copilot, OpenAI (Plus/Pro), Qwen Code, Chutes AI, Synthetic, Google Antigravity, Z.ai coding plan and more.",
|
|
6
5
|
"type": "module",
|
|
7
6
|
"main": "./dist/index.js",
|
|
@@ -32,21 +31,6 @@
|
|
|
32
31
|
"README.md",
|
|
33
32
|
"LICENSE"
|
|
34
33
|
],
|
|
35
|
-
"scripts": {
|
|
36
|
-
"build": "node scripts/clean-dist.mjs && tsc && node scripts/copy-data.mjs && node scripts/prepare-tui-dist.mjs",
|
|
37
|
-
"build:check": "pnpm run build && pnpm pack --dry-run",
|
|
38
|
-
"pricing:refresh": "node scripts/refresh-modelsdev-pricing.mjs",
|
|
39
|
-
"pricing:refresh:if-stale": "node scripts/refresh-modelsdev-pricing-if-stale.mjs",
|
|
40
|
-
"upstream:check": "node scripts/check-upstream-plugin-updates.mjs",
|
|
41
|
-
"upstream:prepare-review": "node scripts/prepare-upstream-plugin-review.mjs",
|
|
42
|
-
"upstream:sync": "node scripts/sync-upstream-plugin-references.mjs",
|
|
43
|
-
"verify:release-version": "node scripts/verify-release-version.mjs",
|
|
44
|
-
"typecheck": "tsc --noEmit",
|
|
45
|
-
"test": "vitest run",
|
|
46
|
-
"test:watch": "vitest",
|
|
47
|
-
"prepublishOnly": "pnpm run build",
|
|
48
|
-
"prepare": "husky"
|
|
49
|
-
},
|
|
50
34
|
"keywords": [
|
|
51
35
|
"opencode",
|
|
52
36
|
"plugin",
|
|
@@ -72,14 +56,15 @@
|
|
|
72
56
|
"devDependencies": {
|
|
73
57
|
"@babel/core": "^7.28.0",
|
|
74
58
|
"@babel/preset-typescript": "^7.27.1",
|
|
75
|
-
"@opencode-ai/plugin": "
|
|
59
|
+
"@opencode-ai/plugin": "1.18.1",
|
|
76
60
|
"@types/node": "^22.0.0",
|
|
77
61
|
"babel-preset-solid": "^1.9.12",
|
|
78
62
|
"husky": "^9.1.7",
|
|
79
63
|
"lint-staged": "^16.2.7",
|
|
80
64
|
"prettier": "^3.8.0",
|
|
81
65
|
"typescript": "^5.9.3",
|
|
82
|
-
"vitest": "^4.0.17"
|
|
66
|
+
"vitest": "^4.0.17",
|
|
67
|
+
"yaml": "^2.8.3"
|
|
83
68
|
},
|
|
84
69
|
"dependencies": {
|
|
85
70
|
"@clack/prompts": "^1.2.0",
|
|
@@ -97,6 +82,28 @@
|
|
|
97
82
|
"@opencode-ai/plugin": "^1.4.3"
|
|
98
83
|
},
|
|
99
84
|
"engines": {
|
|
100
|
-
"node": ">=
|
|
85
|
+
"node": ">=22.0.0"
|
|
86
|
+
},
|
|
87
|
+
"scripts": {
|
|
88
|
+
"build": "node scripts/clean-dist.mjs && tsc && node scripts/copy-data.mjs && node scripts/prepare-tui-dist.mjs",
|
|
89
|
+
"build:check": "pnpm run build && pnpm pack --dry-run",
|
|
90
|
+
"pack:release-package": "node scripts/pack-release-package.mjs",
|
|
91
|
+
"format:check": "node scripts/verify-v4-formatting.mjs",
|
|
92
|
+
"pricing:refresh": "node scripts/refresh-modelsdev-pricing.mjs",
|
|
93
|
+
"pricing:refresh:if-stale": "node scripts/refresh-modelsdev-pricing-if-stale.mjs",
|
|
94
|
+
"upstream:check": "node scripts/check-upstream-plugin-updates.mjs",
|
|
95
|
+
"upstream:prepare-review": "node scripts/prepare-upstream-plugin-review.mjs",
|
|
96
|
+
"upstream:sync": "node scripts/sync-upstream-plugin-references.mjs",
|
|
97
|
+
"release:check": "pnpm run format:check && pnpm run verify:typescript-version && pnpm run verify:v4-history && pnpm run typecheck && pnpm run build && pnpm test && pnpm run test:four-surfaces && pnpm run verify:release-package && pnpm run verify:release-version",
|
|
98
|
+
"smoke:package": "node scripts/smoke-packed-package.mjs",
|
|
99
|
+
"test:four-surfaces": "vitest run tests/v4-phase5-cross-surface.test.ts",
|
|
100
|
+
"verify:package-contents": "node scripts/verify-package-contents.mjs",
|
|
101
|
+
"verify:release-package": "node scripts/verify-release-package.mjs",
|
|
102
|
+
"verify:release-version": "node scripts/verify-release-version.mjs",
|
|
103
|
+
"verify:typescript-version": "node scripts/verify-typescript-version.mjs",
|
|
104
|
+
"verify:v4-history": "node scripts/verify-v4-history.mjs",
|
|
105
|
+
"typecheck": "tsc --noEmit",
|
|
106
|
+
"test": "vitest run",
|
|
107
|
+
"test:watch": "vitest"
|
|
101
108
|
}
|
|
102
|
-
}
|
|
109
|
+
}
|