@columenlabs/lumen-ui 0.1.234 → 0.1.235
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.
|
@@ -17,7 +17,7 @@ import { Label } from '../ui/label.js';
|
|
|
17
17
|
import { Switch } from '../ui/switch.js';
|
|
18
18
|
import { ToggleGroup, ToggleGroupItem } from '../ui/toggle-group.js';
|
|
19
19
|
import { allowanceAmount, assistantStatusKey, usd, useAssistantStatus } from './lumen-assistant.js';
|
|
20
|
-
import { UsageHistoryView } from './usage-history.js';
|
|
20
|
+
import { OwnKeyUsage, UsageHistoryView } from './usage-history.js';
|
|
21
21
|
const EFFORTS = [
|
|
22
22
|
{ value: 'default', label: 'Model default' },
|
|
23
23
|
{ value: 'low', label: 'Low' },
|
|
@@ -168,7 +168,7 @@ function Providers({ client }) {
|
|
|
168
168
|
return (_jsxs("div", { className: "flex flex-col", children: [_jsx(LumenExpandList, { children: rows.map((p) => (_jsx(OwnProviderKey, { client: client, p: p }, p.id))) }), ownSet && (_jsx(Row, { label: "Answers run on", info: "Your own key or plan first, with the shared credits behind it; or the shared credits first.", children: _jsx(LumenSelector, { label: "Answers run on", size: "sm", className: "w-44", value: s.pay, options: [
|
|
169
169
|
{ value: 'own', label: 'Your own first' },
|
|
170
170
|
{ value: 'app', label: 'Shared credits first' },
|
|
171
|
-
], onChange: (pay) => void apply('pay', () => client.settings({ pay: pay })) }) })), ownSet && (_jsx(Row, { label: "Your keys may spend", info: "On your keys, every provider together.", children: _jsx(CapInput, { label: "Your monthly cap", value: s.caps.own, onSave: (n) => void apply('own', () => client.ownCap(n)) }) }))] }));
|
|
171
|
+
], onChange: (pay) => void apply('pay', () => client.settings({ pay: pay })) }) })), ownSet && (_jsx(Row, { label: "Your keys may spend", info: "On your keys, every provider together.", children: _jsx(CapInput, { label: "Your monthly cap", value: s.caps.own, onSave: (n) => void apply('own', () => client.ownCap(n)) }) })), _jsx(OwnKeyUsage, { client: client, always: ownSet })] }));
|
|
172
172
|
} }));
|
|
173
173
|
}
|
|
174
174
|
/** One provider's shared key, which an admin sets for everyone. */
|
|
@@ -13,3 +13,12 @@ export declare function UsageHistoryView({ client, className, }: {
|
|
|
13
13
|
client: AssistantAdapter;
|
|
14
14
|
className?: string;
|
|
15
15
|
}): import("react").JSX.Element | null;
|
|
16
|
+
/**
|
|
17
|
+
* Spend on the person's own keys and plans over the last 1, 7 or 30 days: one row a chat or run
|
|
18
|
+
* (Session, Date, Amount), newest first, and a Total of the rows. A session counts in the range its
|
|
19
|
+
* last use falls in. Shown when `always` (an own key or plan is set) or any session was paid on one.
|
|
20
|
+
*/
|
|
21
|
+
export declare function OwnKeyUsage({ client, always }: {
|
|
22
|
+
client: AssistantAdapter;
|
|
23
|
+
always?: boolean;
|
|
24
|
+
}): import("react").JSX.Element | null;
|
|
@@ -2,9 +2,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useQuery } from '@tanstack/react-query';
|
|
3
3
|
import { ChevronLeftIcon, ChevronRightIcon, CpuIcon, MessageSquareIcon } from 'lucide-react';
|
|
4
4
|
import { Fragment, useState } from 'react';
|
|
5
|
+
import { DetailsTable } from '../details-table.js';
|
|
5
6
|
import { IconButton } from '../icon-button.js';
|
|
7
|
+
import { InfoLabel } from '../info-tip.js';
|
|
6
8
|
import { cn } from '../lib/utils.js';
|
|
9
|
+
import { Label } from '../ui/label.js';
|
|
7
10
|
import { Spinner } from '../ui/spinner.js';
|
|
11
|
+
import { ToggleGroup, ToggleGroupItem } from '../ui/toggle-group.js';
|
|
8
12
|
export const usd = (n) => n === 0 ? '$0' : n < 0.01 ? '<$0.01' : `$${n.toFixed(n < 10 ? 2 : 0)}`;
|
|
9
13
|
export const tokens = (n) => n < 1000
|
|
10
14
|
? String(n)
|
|
@@ -86,3 +90,45 @@ export function UsageHistoryView({ client, className, }) {
|
|
|
86
90
|
const models = perModel(h.rows);
|
|
87
91
|
return (_jsxs("div", { className: cn('flex min-w-0 flex-col gap-3', className), children: [_jsxs("div", { className: "flex items-center gap-1", children: [_jsx(IconButton, { icon: ChevronLeftIcon, label: "Earlier month", disabled: !older, onClick: () => setMonth(older) }), _jsx("span", { className: "min-w-0 flex-1 truncate text-center font-medium text-sm", children: monthName(h.month) }), _jsx(IconButton, { icon: ChevronRightIcon, label: "Later month", disabled: !newer, onClick: () => setMonth(newer) })] }), _jsxs("div", { className: "flex items-baseline gap-2", children: [_jsx("span", { className: "num font-semibold text-2xl", children: usd(h.usd) }), _jsx("span", { className: "text-muted-foreground text-xs", children: h.entries.length === 1 ? '1 chat or run' : `${h.entries.length} chats and runs` })] }), models.length > 0 && (_jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_auto_auto_auto_auto] gap-x-3 gap-y-0.5 text-xs", children: [_jsx("span", { className: "text-muted-foreground", children: "Model" }), _jsx("span", { className: "text-right text-muted-foreground", children: "Cost" }), _jsx("span", { className: "text-right text-muted-foreground", children: "In" }), _jsx("span", { className: "text-right text-muted-foreground", children: "Out" }), _jsx("span", { className: "text-right text-muted-foreground", children: "Calls" }), models.map((m) => (_jsxs(Fragment, { children: [_jsx("span", { className: "truncate font-medium", title: m.label, children: m.label }), _jsx("span", { className: "num text-right", children: usd(m.usd) }), _jsx("span", { className: "num text-right", children: tokens(m.in) }), _jsx("span", { className: "num text-right", children: tokens(m.out) }), _jsx("span", { className: "num text-right", children: m.calls })] }, m.label)))] })), h.entries.length ? (_jsx("ul", { className: "-my-1.5 max-h-72 divide-y overflow-y-auto", children: h.entries.map((e) => (_jsx(Entry, { e: e }, e.id))) })) : (_jsx("p", { className: "text-muted-foreground text-sm", children: "Nothing used this month." }))] }));
|
|
88
92
|
}
|
|
93
|
+
/** The ranges the own-key table offers, in days. */
|
|
94
|
+
const OWN_RANGES = [
|
|
95
|
+
{ id: '1d', days: 1 },
|
|
96
|
+
{ id: '7d', days: 7 },
|
|
97
|
+
{ id: '30d', days: 30 },
|
|
98
|
+
];
|
|
99
|
+
/**
|
|
100
|
+
* Spend on the person's own keys and plans over the last 1, 7 or 30 days: one row a chat or run
|
|
101
|
+
* (Session, Date, Amount), newest first, and a Total of the rows. A session counts in the range its
|
|
102
|
+
* last use falls in. Shown when `always` (an own key or plan is set) or any session was paid on one.
|
|
103
|
+
*/
|
|
104
|
+
export function OwnKeyUsage({ client, always }) {
|
|
105
|
+
const [range, setRange] = useState('7d');
|
|
106
|
+
const now = useAssistantUsage(client).data;
|
|
107
|
+
// The month before, for a range that reaches back past this month's start.
|
|
108
|
+
const before = now?.months[now.months.indexOf(now.month) + 1];
|
|
109
|
+
const prev = useAssistantUsage(client, before, !!before && range === '30d').data;
|
|
110
|
+
if (!now)
|
|
111
|
+
return null;
|
|
112
|
+
const all = [...now.entries, ...(range === '30d' ? (prev?.entries ?? []) : [])].filter((e) => (e.own_usd ?? 0) > 0);
|
|
113
|
+
if (!always && !all.length)
|
|
114
|
+
return null;
|
|
115
|
+
const days = OWN_RANGES.find((r) => r.id === range)?.days ?? 7;
|
|
116
|
+
const since = Date.now() - days * 86_400_000;
|
|
117
|
+
const seen = new Set();
|
|
118
|
+
const sessions = all
|
|
119
|
+
.filter((e) => e.at >= since && !seen.has(e.id) && seen.add(e.id))
|
|
120
|
+
.sort((a, b) => b.at - a.at);
|
|
121
|
+
const total = sessions.reduce((a, e) => a + (e.own_usd ?? 0), 0);
|
|
122
|
+
return (_jsxs("div", { "data-slot": "setting-row", className: "flex flex-col gap-2 border-b py-3 last:border-b-0", children: [_jsxs("div", { className: "flex items-center gap-4", children: [_jsx(Label, { className: "min-w-0 flex-1", children: _jsx(InfoLabel, { info: "Each chat and run your own key or plan paid for, by its last use.", children: "Spent on your keys" }) }), _jsx(ToggleGroup, { type: "single", variant: "outline", size: "sm", spacing: 0, value: range, "aria-label": "Range", onValueChange: (v) => v && setRange(v), children: OWN_RANGES.map((r) => (_jsx(ToggleGroupItem, { value: r.id, "aria-label": `Last ${r.id}`, children: r.id }, r.id))) })] }), sessions.length ? (_jsx(DetailsTable, { head: [
|
|
123
|
+
{ label: 'Session', grow: true },
|
|
124
|
+
{ label: 'Date', hideOnPhone: true },
|
|
125
|
+
{ label: 'Amount', right: true },
|
|
126
|
+
], rows: sessions.map((e) => ({
|
|
127
|
+
key: e.id,
|
|
128
|
+
cells: [
|
|
129
|
+
_jsx("span", { className: "block truncate", title: e.title, children: e.title }, "n"),
|
|
130
|
+
_jsx("time", { dateTime: new Date(e.at).toISOString(), title: new Date(e.at).toLocaleString(), children: when(e.at) }, "t"),
|
|
131
|
+
usd(e.own_usd ?? 0),
|
|
132
|
+
],
|
|
133
|
+
})), foot: ['Total', _jsx("span", { className: "max-md:hidden" }, "d"), usd(total)] })) : (_jsxs("p", { className: "text-muted-foreground text-sm", children: ["Nothing spent on your keys in the last ", range, "."] }))] }));
|
|
134
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.235",
|
|
4
4
|
"description": "Lumen: shared React components (frame, views, widgets, charts, drawers).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@codemirror/lang-javascript": "6.2.5",
|
|
50
50
|
"@codemirror/lang-json": "6.0.2",
|
|
51
51
|
"@codemirror/lang-sql": "6.10.0",
|
|
52
|
-
"@columenlabs/lumen-ui-types": "0.1.
|
|
52
|
+
"@columenlabs/lumen-ui-types": "0.1.235",
|
|
53
53
|
"@dnd-kit/core": "6.3.1",
|
|
54
54
|
"@dnd-kit/sortable": "10.0.0",
|
|
55
55
|
"@dnd-kit/utilities": "3.2.2",
|