@slkiser/opencode-quota 4.10.0 → 4.10.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 +16 -15
- package/dist/lib/alibaba-token-plan.d.ts +88 -0
- package/dist/lib/alibaba-token-plan.d.ts.map +1 -0
- package/dist/lib/alibaba-token-plan.js +505 -0
- package/dist/lib/alibaba-token-plan.js.map +1 -0
- package/dist/lib/atomic-json.d.ts +3 -0
- package/dist/lib/atomic-json.d.ts.map +1 -1
- package/dist/lib/atomic-json.js +16 -4
- package/dist/lib/atomic-json.js.map +1 -1
- package/dist/lib/config-write-target.d.ts +28 -0
- package/dist/lib/config-write-target.d.ts.map +1 -0
- package/dist/lib/config-write-target.js +159 -0
- package/dist/lib/config-write-target.js.map +1 -0
- package/dist/lib/init-installer.d.ts.map +1 -1
- package/dist/lib/init-installer.js +2 -2
- package/dist/lib/init-installer.js.map +1 -1
- package/dist/lib/opencode-config-editor.d.ts +3 -0
- package/dist/lib/opencode-config-editor.d.ts.map +1 -1
- package/dist/lib/opencode-config-editor.js +71 -10
- package/dist/lib/opencode-config-editor.js.map +1 -1
- package/dist/lib/opencode-go.d.ts.map +1 -1
- package/dist/lib/opencode-go.js +3 -2
- package/dist/lib/opencode-go.js.map +1 -1
- package/dist/lib/openrouter.d.ts +2 -1
- package/dist/lib/openrouter.d.ts.map +1 -1
- package/dist/lib/openrouter.js +3 -4
- package/dist/lib/openrouter.js.map +1 -1
- package/dist/lib/provider-registration.d.ts +11 -0
- package/dist/lib/provider-registration.d.ts.map +1 -1
- package/dist/lib/provider-registration.js +12 -0
- package/dist/lib/provider-registration.js.map +1 -1
- package/dist/lib/quota-status.d.ts.map +1 -1
- package/dist/lib/quota-status.js +18 -0
- package/dist/lib/quota-status.js.map +1 -1
- package/dist/lib/scoped-update.d.ts +2 -0
- package/dist/lib/scoped-update.d.ts.map +1 -1
- package/dist/lib/scoped-update.js +43 -7
- package/dist/lib/scoped-update.js.map +1 -1
- package/dist/lib/synthetic.d.ts.map +1 -1
- package/dist/lib/synthetic.js +9 -0
- package/dist/lib/synthetic.js.map +1 -1
- package/dist/lib/tui-compact-format.d.ts.map +1 -1
- package/dist/lib/tui-compact-format.js +79 -5
- package/dist/lib/tui-compact-format.js.map +1 -1
- package/dist/lib/tui-panel-state.d.ts +5 -1
- package/dist/lib/tui-panel-state.d.ts.map +1 -1
- package/dist/lib/tui-panel-state.js.map +1 -1
- package/dist/lib/tui-prompt-bar-format.d.ts +25 -0
- package/dist/lib/tui-prompt-bar-format.d.ts.map +1 -0
- package/dist/lib/tui-prompt-bar-format.js +206 -0
- package/dist/lib/tui-prompt-bar-format.js.map +1 -0
- package/dist/lib/tui-runtime.d.ts.map +1 -1
- package/dist/lib/tui-runtime.js +5 -93
- package/dist/lib/tui-runtime.js.map +1 -1
- package/dist/lib/tui-sidebar-content.d.ts +32 -0
- package/dist/lib/tui-sidebar-content.d.ts.map +1 -0
- package/dist/lib/tui-sidebar-content.js +52 -0
- package/dist/lib/tui-sidebar-content.js.map +1 -0
- package/dist/providers/alibaba-token-plan.d.ts +3 -0
- package/dist/providers/alibaba-token-plan.d.ts.map +1 -0
- package/dist/providers/alibaba-token-plan.js +89 -0
- package/dist/providers/alibaba-token-plan.js.map +1 -0
- package/dist/providers/cache-policies.d.ts +3 -0
- package/dist/providers/cache-policies.d.ts.map +1 -1
- package/dist/providers/cache-policies.js +1 -0
- package/dist/providers/cache-policies.js.map +1 -1
- package/dist/providers/openrouter.d.ts.map +1 -1
- package/dist/providers/openrouter.js +11 -4
- package/dist/providers/openrouter.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/tui.d.ts.map +1 -1
- package/dist/tui.js +226 -219
- package/dist/tui.tsx +57 -49
- package/package.json +5 -1
package/dist/tui.tsx
CHANGED
|
@@ -7,9 +7,8 @@ import type {
|
|
|
7
7
|
TuiPromptRef,
|
|
8
8
|
} from "@opencode-ai/plugin/tui";
|
|
9
9
|
import type { JSX } from "@opentui/solid";
|
|
10
|
-
import { createEffect, createSignal, onCleanup, Show } from "solid-js";
|
|
10
|
+
import { createEffect, createSignal, Index, onCleanup, Show } from "solid-js";
|
|
11
11
|
import {
|
|
12
|
-
formatDisplayedPercentLabel,
|
|
13
12
|
formatQuotaModeHeading,
|
|
14
13
|
formatResetCountdown,
|
|
15
14
|
isResetTimeDecimals,
|
|
@@ -21,8 +20,6 @@ import {
|
|
|
21
20
|
type QuotaDialogCommandId,
|
|
22
21
|
type QuotaDialogCommandSpec,
|
|
23
22
|
} from "./lib/quota-dialog-commands.js";
|
|
24
|
-
import { extractSingleWindowWindowLabel } from "./lib/quota-entry-display.js";
|
|
25
|
-
import { formatQuotaRunway } from "./lib/quota-exhaustion-projection.js";
|
|
26
23
|
import type { SessionTokenError } from "./lib/quota-status.js";
|
|
27
24
|
import { disposeQuotaTelemetryOwner } from "./lib/quota-telemetry.js";
|
|
28
25
|
import { getSidebarBodyLineColor } from "./lib/tui-line-style.js";
|
|
@@ -41,6 +38,11 @@ import {
|
|
|
41
38
|
shouldRenderHomeBottom,
|
|
42
39
|
shouldRenderSidebarPanel,
|
|
43
40
|
} from "./lib/tui-panel-state.js";
|
|
41
|
+
import {
|
|
42
|
+
formatPromptBarPercentMeta,
|
|
43
|
+
PROMPT_BAR_WIDTH,
|
|
44
|
+
resolvePromptBarLabel,
|
|
45
|
+
} from "./lib/tui-prompt-bar-format.js";
|
|
44
46
|
import { createTuiRefreshLifecycle } from "./lib/tui-refresh-lifecycle.js";
|
|
45
47
|
import {
|
|
46
48
|
createTuiQuotaClient,
|
|
@@ -54,6 +56,7 @@ import {
|
|
|
54
56
|
type TuiSurfaceRegistration,
|
|
55
57
|
writeTuiQuotaExportIfEnabled,
|
|
56
58
|
} from "./lib/tui-runtime.js";
|
|
59
|
+
import { buildSidebarContentRows, type SidebarContentRow } from "./lib/tui-sidebar-content.js";
|
|
57
60
|
import type { TuiCommandDisplay } from "./lib/types.js";
|
|
58
61
|
|
|
59
62
|
const id = "@slkiser/opencode-quota";
|
|
@@ -378,33 +381,46 @@ function SidebarContentView(props: {
|
|
|
378
381
|
return collapsed() ? lines() : getSidebarPanelLinesExpanded(panel());
|
|
379
382
|
};
|
|
380
383
|
|
|
381
|
-
const
|
|
382
|
-
const providerCount = () => panel().providerCount ?? 0;
|
|
383
|
-
const headerText = () => {
|
|
384
|
+
const contentRows = (): SidebarContentRow[] => {
|
|
384
385
|
const heading = panel().headerPercentMode
|
|
385
386
|
? formatQuotaModeHeading(panel().headerPercentMode)
|
|
386
387
|
: "Quota";
|
|
387
|
-
return
|
|
388
|
+
return buildSidebarContentRows({
|
|
389
|
+
collapsed: collapsed(),
|
|
390
|
+
heading,
|
|
391
|
+
hasDetailLines: hasDetailLines(),
|
|
392
|
+
providerCount: panel().providerCount ?? 0,
|
|
393
|
+
lines: displayLines(),
|
|
394
|
+
});
|
|
388
395
|
};
|
|
389
396
|
|
|
390
397
|
return (
|
|
391
398
|
<Show when={shouldRenderSidebarPanel(panel())}>
|
|
392
|
-
<box gap={0}>
|
|
393
|
-
<
|
|
394
|
-
|
|
395
|
-
<
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
399
|
+
<box gap={0} width="100%">
|
|
400
|
+
<Index each={contentRows()}>
|
|
401
|
+
{(row: () => SidebarContentRow) => (
|
|
402
|
+
<text
|
|
403
|
+
fg={
|
|
404
|
+
row().kind === "header"
|
|
405
|
+
? props.api.theme.current.text
|
|
406
|
+
: getSidebarBodyLineColor(row().text, props.api.theme.current)
|
|
407
|
+
}
|
|
408
|
+
wrapMode="none"
|
|
409
|
+
width="100%"
|
|
410
|
+
onMouseDown={row().kind === "header" ? toggleCollapsed : undefined}
|
|
411
|
+
>
|
|
412
|
+
{row().kind === "header"
|
|
413
|
+
? row().segments.map((segment) =>
|
|
414
|
+
segment.style === "muted" ? (
|
|
415
|
+
<span fg={props.api.theme.current.textMuted}>{segment.text}</span>
|
|
416
|
+
) : (
|
|
417
|
+
<b>{segment.text}</b>
|
|
418
|
+
),
|
|
419
|
+
)
|
|
420
|
+
: row().text || " "}
|
|
405
421
|
</text>
|
|
406
|
-
)
|
|
407
|
-
</
|
|
422
|
+
)}
|
|
423
|
+
</Index>
|
|
408
424
|
</box>
|
|
409
425
|
</Show>
|
|
410
426
|
);
|
|
@@ -468,8 +484,6 @@ function SessionPromptWithCompactStatus(props: {
|
|
|
468
484
|
);
|
|
469
485
|
}
|
|
470
486
|
|
|
471
|
-
const PROMPT_BAR_WIDTH = 12;
|
|
472
|
-
|
|
473
487
|
function shouldRenderPromptBar(
|
|
474
488
|
bar: PromptBarState,
|
|
475
489
|
): bar is Extract<PromptBarState, { status: "ready" }> {
|
|
@@ -528,31 +542,20 @@ function buildPromptBarParts(params: {
|
|
|
528
542
|
if (!shouldRenderPromptBar(bar)) return undefined;
|
|
529
543
|
const entry = bar.entry;
|
|
530
544
|
if (!entry) return undefined;
|
|
531
|
-
const reset = entry.resetTimeIso
|
|
532
|
-
? formatResetCountdown(
|
|
533
|
-
entry.resetTimeIso,
|
|
534
|
-
isResetTimeDecimals(bar.resetTimeDecimals)
|
|
535
|
-
? { compactRounded: true, decimals: bar.resetTimeDecimals }
|
|
536
|
-
: { spaced: bar.resetTimeSpaced },
|
|
537
|
-
)
|
|
538
|
-
: "";
|
|
539
|
-
const runway = formatQuotaRunway(entry.runway);
|
|
540
545
|
|
|
541
546
|
const hasPercent = Number.isFinite(entry.percentRemaining);
|
|
542
547
|
if (entry.semanticSegment && !hasPercent) {
|
|
543
|
-
|
|
548
|
+
const reset = entry.resetTimeIso
|
|
549
|
+
? formatResetCountdown(
|
|
550
|
+
entry.resetTimeIso,
|
|
551
|
+
isResetTimeDecimals(bar.resetTimeDecimals)
|
|
552
|
+
? { compactRounded: true, decimals: bar.resetTimeDecimals }
|
|
553
|
+
: { spaced: bar.resetTimeSpaced },
|
|
554
|
+
)
|
|
555
|
+
: "";
|
|
556
|
+
return { label: resolvePromptBarLabel(entry), barText: "", meta: reset };
|
|
544
557
|
}
|
|
545
558
|
|
|
546
|
-
const windowLabel =
|
|
547
|
-
entry.semanticSegment ??
|
|
548
|
-
extractSingleWindowWindowLabel(entry.label ?? "") ??
|
|
549
|
-
extractSingleWindowWindowLabel(entry.name ?? "") ??
|
|
550
|
-
"Quota";
|
|
551
|
-
const percent = formatDisplayedPercentLabel(
|
|
552
|
-
entry.percentRemaining ?? 0,
|
|
553
|
-
bar.percentDisplayMode ?? "remaining",
|
|
554
|
-
"bare",
|
|
555
|
-
);
|
|
556
559
|
const p = Math.min(
|
|
557
560
|
100,
|
|
558
561
|
resolveDisplayedPercent(entry.percentRemaining ?? 0, bar.percentDisplayMode ?? "remaining"),
|
|
@@ -571,11 +574,16 @@ function buildPromptBarParts(params: {
|
|
|
571
574
|
barText = cells.join("") + "░".repeat(empty);
|
|
572
575
|
}
|
|
573
576
|
return {
|
|
574
|
-
label:
|
|
577
|
+
label: resolvePromptBarLabel(entry),
|
|
575
578
|
barText,
|
|
576
|
-
meta:
|
|
577
|
-
|
|
578
|
-
:
|
|
579
|
+
meta: formatPromptBarPercentMeta({
|
|
580
|
+
percentRemaining: entry.percentRemaining ?? 0,
|
|
581
|
+
percentDisplayMode: bar.percentDisplayMode,
|
|
582
|
+
resetTimeIso: entry.resetTimeIso,
|
|
583
|
+
resetTimeDecimals: bar.resetTimeDecimals,
|
|
584
|
+
resetTimeSpaced: bar.resetTimeSpaced,
|
|
585
|
+
runway: entry.runway,
|
|
586
|
+
}),
|
|
579
587
|
};
|
|
580
588
|
}
|
|
581
589
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slkiser/opencode-quota",
|
|
3
|
-
"version": "4.10.
|
|
3
|
+
"version": "4.10.1",
|
|
4
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.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -109,6 +109,10 @@
|
|
|
109
109
|
"typecheck": "tsc --noEmit",
|
|
110
110
|
"test": "vitest run",
|
|
111
111
|
"test:watch": "vitest",
|
|
112
|
+
"test:stabilization:tui": "node scripts/test-stabilization-connected.mjs --tui",
|
|
113
|
+
"test:stabilization:tui:prompt-bar": "node scripts/test-stabilization-connected.mjs --tui --prompt-bar",
|
|
114
|
+
"test:stabilization:web": "node scripts/test-stabilization-connected.mjs --web",
|
|
115
|
+
"test:stabilization:fixtures": "node scripts/test-stabilization-fixtures.mjs",
|
|
112
116
|
"verify": "pnpm run 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:package-contents"
|
|
113
117
|
}
|
|
114
118
|
}
|