Skip to content
Source
Sign inSign up
Open History to see the last commit

useUsageLimitsPanel.ts

77 lines2.7 KB

1import type {
2 EnvironmentId,
3 ProviderInstanceId,
4 ServerProvider,
5 UsageLimitSourceSnapshots,
6} from "@t3tools/contracts";
7import { collectProviderUsageLimits, hasProviderUsageLimits } from "@t3tools/shared/usageLimits";
8import { useState } from "react";
9import { useStableCallback } from "../../hooks/useStableCallback";
10import { toastManager } from "../ui/toast";
11import { usageLimitsBannerItem } from "./ComposerUsageLimits";
12​
13/** Keep opened data live. Retain hidden panels during reconnect; clear when quota-spending work resumes. */
14export function useUsageLimitsPanel(input: {
15 readonly environmentId: EnvironmentId;
16 readonly threadKey: string;
17 readonly panelKey: string | null;
18 readonly providerInstanceId: ProviderInstanceId | null;
19 readonly providerDriver: ServerProvider["driver"] | null;
20 readonly providers: readonly ServerProvider[];
21 readonly sources: UsageLimitSourceSnapshots;
22}) {
23 const {
24 environmentId,
25 threadKey,
26 panelKey,
27 providerInstanceId,
28 providerDriver,
29 providers,
30 sources,
31 } = input;
32 const [panel, setPanel] = useState<{
33 readonly key: string;
34 readonly threadKey: string;
35 readonly now: number;
36 } | null>(null);
37 if (panel !== null && panelKey !== null && panel.key !== panelKey) {
38 setPanel(null);
39 }
40 const report =
41 panel !== null && panelKey !== null && panel.key === panelKey && providerInstanceId !== null
42 ? collectProviderUsageLimits(providerInstanceId, providers, sources, panel.now)
43 : null;
44 const banner =
45 report !== null && panel !== null
46 ? // A fresh id per opening: the stack keeps the last dismissed id as "exiting".
47 usageLimitsBannerItem(`usage-limits:${panel.key}:${panel.now}`, report, environmentId, () =>
48 setPanel(null),
49 )
50 : null;
51 // Intercept /usage-limits only when Limits has selected-provider data.
52 const offered =
53 providerDriver !== null && hasProviderUsageLimits(providerDriver, providers, sources);
54​
55 const open = useStableCallback(() => {
56 const now = Date.now();
57 const nextReport =
58 providerInstanceId !== null && panelKey !== null
59 ? collectProviderUsageLimits(providerInstanceId, providers, sources, now)
60 : null;
61 if (nextReport && panelKey !== null) {
62 setPanel({ key: panelKey, threadKey, now });
63 return true;
64 }
65 setPanel(null);
66 toastManager.add({ type: "info", title: "Usage limits are unavailable for this provider" });
67 return false;
68 });
69 // Async responses may clear only their originating thread's panel.
70 const clearFor = useStableCallback((originThreadKey: string) =>
71 setPanel((current) =>
72 current !== null && current.threadKey === originThreadKey ? null : current,
73 ),
74 );
75​
76 return { banner, offered, open, clearFor };