@cortexkit/opencode-openai-auth 1.0.5 → 1.2.0
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/bin.js +9 -8
- package/dist/{pool-lifecycle-C_6YRmsh.d.ts → codex-request-CjXETpTA.d.ts} +190 -27
- package/dist/index-03em8hv1.js +69 -0
- package/dist/index-6n4pnfkg.js +2 -0
- package/dist/{index-pg305s90.js → index-bc89akak.js} +1 -1
- package/dist/{index-y4gxyxqd.js → index-ehjj89rx.js} +2 -2
- package/dist/index-f21addzm.js +90 -0
- package/dist/{index-fsky1rsh.js → index-ffg0sgg5.js} +2 -2
- package/dist/{index-nx2qh047.js → index-ftkhhr6d.js} +1 -1
- package/dist/{index-826s1yxa.js → index-htvcmtcx.js} +2 -2
- package/dist/{index-fsxbncpw.js → index-qp5hdpw8.js} +1 -1
- package/dist/index-qxbchh2d.js +8 -0
- package/dist/{index-116q849r.js → index-r2s51ac1.js} +2 -2
- package/dist/index-rwbrhkse.js +65 -0
- package/dist/{index-66asrje2.js → index-xwvze96g.js} +1 -1
- package/dist/index.d.ts +18 -8
- package/dist/index.js +1 -1
- package/dist/{protocol-DctqemRI.d.ts → model-CQcw10oW.d.ts} +67 -25
- package/dist/{port-file-ZPlxXB4G.d.ts → port-file-BDJnzgHH.d.ts} +1 -1
- package/dist/protocol-C-kagE6O.d.ts +29 -0
- package/dist/rpc/port-file.d.ts +1 -1
- package/dist/rpc/port-file.js +1 -1
- package/dist/rpc/protocol.d.ts +1 -1
- package/dist/rpc/protocol.js +1 -1
- package/dist/rpc/rpc-client.d.ts +3 -3
- package/dist/rpc/rpc-client.js +1 -1
- package/dist/rpc/rpc-dir.js +1 -1
- package/dist/{sidebar-state-z_M7Trnd.d.ts → sidebar-state-BfQ4mpZO.d.ts} +109 -10
- package/dist/sidebar-state.d.ts +2 -2
- package/dist/sidebar-state.js +1 -1
- package/dist/token-util-cf0nyh7n.js +1 -0
- package/dist/{token-bzhkgc29.js → token-z6qq7a1d.js} +1 -1
- package/dist/tui-preferences.js +1 -1
- package/dist/tui.d.ts +20 -2
- package/dist/v2/server.d.ts +180 -1
- package/dist/v2/server.js +3 -3
- package/package.json +3 -3
- package/src/tui-compiled/raw/shared/0332701351b3eeec-format.js +148 -26
- package/src/tui-compiled/raw/shared/0f77ebc3c914c9c6-custody.js +371 -0
- package/src/tui-compiled/raw/shared/134b008900698fe0-backoff.js +92 -0
- package/src/tui-compiled/raw/shared/169b2b4bf30909bc-consumer.js +430 -0
- package/src/tui-compiled/raw/shared/2577ec69f9973ae9-quota-normalize.js +154 -0
- package/src/tui-compiled/raw/shared/2dce6e9613993329-quota-manager.js +473 -0
- package/src/tui-compiled/raw/shared/30f5bc480f31f51c-roster.js +566 -0
- package/src/tui-compiled/raw/shared/43fc9e6b994519c7-refresh-lock.js +0 -1
- package/src/tui-compiled/raw/shared/4593a4d71edf69fd-tombstone.js +25 -0
- package/src/tui-compiled/raw/shared/4d05c2d7a531aece-oauth.js +500 -0
- package/src/tui-compiled/raw/shared/6371b24a0573d79e-any-signal.js +42 -0
- package/src/tui-compiled/raw/shared/7c140680fc81be92-interlock.js +29 -0
- package/src/tui-compiled/raw/shared/85512cc5263ba259-provider.js +87 -0
- package/src/tui-compiled/raw/shared/abd062d633e29fd2-pool-routing.js +192 -0
- package/src/tui-compiled/raw/shared/b9588ad4725c1d10-enrollment.js +806 -0
- package/src/tui-compiled/raw/shared/bfbdd0f9aae56b47-pool-quota.js +85 -0
- package/src/tui-compiled/raw/shared/c852a15cfe489d12-pool.js +0 -1
- package/src/tui-compiled/raw/shared/ca0fccaba1d87af4-errors.js +8 -0
- package/src/tui-compiled/raw/shared/d0f0b6be200311af-insula.js +152 -0
- package/src/tui-compiled/raw/shared/d5a8f1061ee2f114-index.js +1 -1
- package/src/tui-compiled/raw/shared/d9d2892a4c371301-host-slot.js +72 -0
- package/src/tui-compiled/raw/shared/dbc61cd405941828-accounts.js +1470 -0
- package/src/tui-compiled/raw/shared/e8cd4929507508d8-refresh-file-lock.js +26 -12
- package/src/tui-compiled/raw/shared/e8d3c8da776ef9cd-index.js +24 -0
- package/src/tui-compiled/raw/sidebar-state.js +103 -14
- package/src/tui-compiled/raw/tui/command-dialogs.tsx +3 -34
- package/src/tui-compiled/raw/tui/section-text.js +21 -0
- package/src/tui-compiled/raw/tui/v2-dialog.js +137 -0
- package/src/tui-compiled/raw/tui/v2.tsx +133 -0
- package/src/tui-compiled/raw/tui.tsx +228 -70
- package/src/tui-compiled/runtime/shared/0332701351b3eeec-format.js +148 -26
- package/src/tui-compiled/runtime/shared/0f77ebc3c914c9c6-custody.js +371 -0
- package/src/tui-compiled/runtime/shared/134b008900698fe0-backoff.js +92 -0
- package/src/tui-compiled/runtime/shared/169b2b4bf30909bc-consumer.js +430 -0
- package/src/tui-compiled/runtime/shared/2577ec69f9973ae9-quota-normalize.js +154 -0
- package/src/tui-compiled/runtime/shared/2dce6e9613993329-quota-manager.js +473 -0
- package/src/tui-compiled/runtime/shared/30f5bc480f31f51c-roster.js +566 -0
- package/src/tui-compiled/runtime/shared/43fc9e6b994519c7-refresh-lock.js +0 -1
- package/src/tui-compiled/runtime/shared/4593a4d71edf69fd-tombstone.js +25 -0
- package/src/tui-compiled/runtime/shared/4d05c2d7a531aece-oauth.js +500 -0
- package/src/tui-compiled/runtime/shared/6371b24a0573d79e-any-signal.js +42 -0
- package/src/tui-compiled/runtime/shared/7c140680fc81be92-interlock.js +29 -0
- package/src/tui-compiled/runtime/shared/85512cc5263ba259-provider.js +87 -0
- package/src/tui-compiled/runtime/shared/abd062d633e29fd2-pool-routing.js +192 -0
- package/src/tui-compiled/runtime/shared/b9588ad4725c1d10-enrollment.js +806 -0
- package/src/tui-compiled/runtime/shared/bfbdd0f9aae56b47-pool-quota.js +85 -0
- package/src/tui-compiled/runtime/shared/c852a15cfe489d12-pool.js +0 -1
- package/src/tui-compiled/runtime/shared/ca0fccaba1d87af4-errors.js +8 -0
- package/src/tui-compiled/runtime/shared/d0f0b6be200311af-insula.js +152 -0
- package/src/tui-compiled/runtime/shared/d5a8f1061ee2f114-index.js +1 -1
- package/src/tui-compiled/runtime/shared/d9d2892a4c371301-host-slot.js +72 -0
- package/src/tui-compiled/runtime/shared/dbc61cd405941828-accounts.js +1470 -0
- package/src/tui-compiled/runtime/shared/e8cd4929507508d8-refresh-file-lock.js +26 -12
- package/src/tui-compiled/runtime/shared/e8d3c8da776ef9cd-index.js +24 -0
- package/src/tui-compiled/runtime/sidebar-state.js +103 -14
- package/src/tui-compiled/runtime/tui/command-dialogs.js +3 -15
- package/src/tui-compiled/runtime/tui/section-text.js +21 -0
- package/src/tui-compiled/runtime/tui/v2-dialog.js +137 -0
- package/src/tui-compiled/runtime/tui/v2.js +95 -0
- package/src/tui-compiled/runtime/tui.js +351 -222
- package/dist/index-4fnghj9e.js +0 -65
- package/dist/index-a69gr76b.js +0 -2
- package/dist/index-h263aftt.js +0 -157
- package/dist/index-ssj7m2rd.js +0 -8
- package/dist/index-ydz3hbhc.js +0 -2
- package/dist/map-m6f5a_IA.d.ts +0 -56
- package/dist/token-util-4a2xxnpg.js +0 -1
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
import { readFileSync } from "node:fs"
|
|
4
4
|
import { dirname, join } from "node:path"
|
|
5
5
|
import { fileURLToPath } from "node:url"
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
formatQuota,
|
|
8
|
+
quotaTextParts,
|
|
9
|
+
quotaWindowParts,
|
|
10
|
+
} from "./shared/d5a8f1061ee2f114-index.js"
|
|
11
|
+
import type { Plugin } from "@opencode/plugin/tui"
|
|
7
12
|
import type {
|
|
8
13
|
TuiPlugin,
|
|
9
14
|
TuiPluginApi,
|
|
@@ -13,7 +18,7 @@ import {
|
|
|
13
18
|
createEffect,
|
|
14
19
|
createSignal,
|
|
15
20
|
For,
|
|
16
|
-
|
|
21
|
+
Index,
|
|
17
22
|
onCleanup,
|
|
18
23
|
Show,
|
|
19
24
|
} from "solid-js"
|
|
@@ -23,8 +28,12 @@ import { createRpcClient } from "./rpc/rpc-client.js"
|
|
|
23
28
|
import { resolveRpcDir } from "./rpc/rpc-dir.js"
|
|
24
29
|
import {
|
|
25
30
|
type AccountQuota,
|
|
31
|
+
type CollapsedAccountLine,
|
|
26
32
|
computeQuotaPacing,
|
|
27
33
|
DEFAULT_SIDEBAR_STATE,
|
|
34
|
+
displayWidth,
|
|
35
|
+
fitCollapsedLabel,
|
|
36
|
+
getCollapsedAccountLines,
|
|
28
37
|
getCollapsedQuotaSummary,
|
|
29
38
|
getPresentQuotaWindows,
|
|
30
39
|
getSidebarState,
|
|
@@ -38,6 +47,7 @@ import {
|
|
|
38
47
|
sidebarQuotaProjection,
|
|
39
48
|
} from "./sidebar-state.js"
|
|
40
49
|
import { openCommandDialog } from "./tui/command-dialogs.tsx"
|
|
50
|
+
import { setupTui, type TuiTransportOptions } from "./tui/v2.tsx"
|
|
41
51
|
import {
|
|
42
52
|
type AppearancePrefs,
|
|
43
53
|
computeEffectiveOrder,
|
|
@@ -95,7 +105,17 @@ const PLUGIN_VERSION: string = (() => {
|
|
|
95
105
|
const SINGLE_BORDER = { type: 'single' } as any
|
|
96
106
|
|
|
97
107
|
type Tone = 'ok' | 'warn' | 'err' | 'muted' | 'accent' | 'text'
|
|
98
|
-
type ThemeCurrent =
|
|
108
|
+
type ThemeCurrent = Pick<
|
|
109
|
+
TuiPluginApi['theme']['current'],
|
|
110
|
+
| 'text'
|
|
111
|
+
| 'textMuted'
|
|
112
|
+
| 'accent'
|
|
113
|
+
| 'background'
|
|
114
|
+
| 'borderActive'
|
|
115
|
+
| 'success'
|
|
116
|
+
| 'warning'
|
|
117
|
+
| 'error'
|
|
118
|
+
>
|
|
99
119
|
type ThemeColor = ThemeCurrent['text']
|
|
100
120
|
|
|
101
121
|
// Tone -> theme token. Theme tokens only — never hardcoded colors. Fallbacks
|
|
@@ -234,17 +254,72 @@ function StatRow(props: {
|
|
|
234
254
|
)
|
|
235
255
|
}
|
|
236
256
|
|
|
237
|
-
//
|
|
238
|
-
// right.
|
|
239
|
-
|
|
257
|
+
// One account in the collapsed view: label left; narrow quota text and the
|
|
258
|
+
// status dot right (red ⊘ when killed). The session's account keeps the
|
|
259
|
+
// usage tone; other accounts, and any account whose reading is stale, are
|
|
260
|
+
// drawn muted. The row measures its own width so only the label is cut (with
|
|
261
|
+
// …) when the line does not fit; the quota text is never cut.
|
|
262
|
+
function CollapsedAccountRow(props: {
|
|
240
263
|
theme: ThemeCurrent
|
|
241
|
-
|
|
242
|
-
|
|
264
|
+
line: CollapsedAccountLine
|
|
265
|
+
tone: Tone
|
|
243
266
|
}) {
|
|
267
|
+
const [width, setWidth] = createSignal(0)
|
|
268
|
+
let row: { width: number } | undefined
|
|
269
|
+
const dim = () => props.line.stale || !props.line.active
|
|
270
|
+
const label = () => {
|
|
271
|
+
const columns = width()
|
|
272
|
+
if (columns <= 0) return props.line.name
|
|
273
|
+
// The value side is the text plus ` ●`, or a lone `—`; one column
|
|
274
|
+
// separates it from the label.
|
|
275
|
+
const value =
|
|
276
|
+
props.line.text === null ? 1 : displayWidth(props.line.text) + 2
|
|
277
|
+
return fitCollapsedLabel(props.line.name, columns - value - 1)
|
|
278
|
+
}
|
|
244
279
|
return (
|
|
245
|
-
<box
|
|
246
|
-
|
|
247
|
-
|
|
280
|
+
<box
|
|
281
|
+
ref={(element: { width: number }) => {
|
|
282
|
+
row = element
|
|
283
|
+
}}
|
|
284
|
+
onSizeChange={() => setWidth(row?.width ?? 0)}
|
|
285
|
+
width='100%'
|
|
286
|
+
flexDirection='row'
|
|
287
|
+
justifyContent='space-between'
|
|
288
|
+
>
|
|
289
|
+
<text
|
|
290
|
+
fg={toneColor(props.theme, dim() ? 'muted' : 'text')}
|
|
291
|
+
wrapMode='none'
|
|
292
|
+
flexShrink={1}
|
|
293
|
+
>
|
|
294
|
+
{label()}
|
|
295
|
+
</text>
|
|
296
|
+
<Show
|
|
297
|
+
when={props.line.text !== null}
|
|
298
|
+
fallback={<text fg={props.theme.textMuted}>{'\u2014'}</text>}
|
|
299
|
+
>
|
|
300
|
+
<box flexDirection='row' flexShrink={0}>
|
|
301
|
+
<Show
|
|
302
|
+
when={!dim()}
|
|
303
|
+
fallback={
|
|
304
|
+
<text fg={toneColor(props.theme, 'muted')}>
|
|
305
|
+
{props.line.text}
|
|
306
|
+
</text>
|
|
307
|
+
}
|
|
308
|
+
>
|
|
309
|
+
<text fg={toneColor(props.theme, props.tone)}>
|
|
310
|
+
<b>{props.line.text}</b>
|
|
311
|
+
</text>
|
|
312
|
+
</Show>
|
|
313
|
+
<text
|
|
314
|
+
fg={toneColor(
|
|
315
|
+
props.theme,
|
|
316
|
+
props.line.killed ? 'err' : dim() ? 'muted' : props.tone,
|
|
317
|
+
)}
|
|
318
|
+
>
|
|
319
|
+
{props.line.killed ? ' \u2298' : ' \u25cf'}
|
|
320
|
+
</text>
|
|
321
|
+
</box>
|
|
322
|
+
</Show>
|
|
248
323
|
</box>
|
|
249
324
|
)
|
|
250
325
|
}
|
|
@@ -254,6 +329,7 @@ export interface QuotaDisplayRow {
|
|
|
254
329
|
label: string
|
|
255
330
|
labelWidth: number
|
|
256
331
|
text: string
|
|
332
|
+
resetText?: string
|
|
257
333
|
window: QuotaWindow
|
|
258
334
|
pacing: QuotaPacing | null
|
|
259
335
|
}
|
|
@@ -292,9 +368,7 @@ export function renderedQuotas(state: {
|
|
|
292
368
|
}): ReadonlyArray<AccountQuota | null | undefined> {
|
|
293
369
|
// In vault mode only the vault accounts are rendered.
|
|
294
370
|
if (state.vaultAccounts !== undefined)
|
|
295
|
-
return state.vaultAccounts
|
|
296
|
-
.filter((account) => account.enabled)
|
|
297
|
-
.map((account) => account.quota)
|
|
371
|
+
return state.vaultAccounts.map((account) => account.quota)
|
|
298
372
|
return [
|
|
299
373
|
state.main?.quota ?? null,
|
|
300
374
|
...(state.fallbacks ?? [])
|
|
@@ -327,33 +401,50 @@ export function buildQuotaRowsForDisplay(
|
|
|
327
401
|
): QuotaDisplayRow[] {
|
|
328
402
|
const projection = sidebarQuotaProjection(quota, now)
|
|
329
403
|
const rows: Array<Omit<QuotaDisplayRow, 'labelWidth'>> =
|
|
330
|
-
getPresentQuotaWindows(quota).map((row) =>
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
404
|
+
getPresentQuotaWindows(quota).map((row) => {
|
|
405
|
+
const rowProjection = projection && {
|
|
406
|
+
...projection,
|
|
407
|
+
budget: undefined,
|
|
408
|
+
limits: projection.limits.filter((limit) => limit.label === row.key),
|
|
409
|
+
}
|
|
410
|
+
const reset = quotaWindowParts(rowProjection, {
|
|
411
|
+
now,
|
|
412
|
+
staleAfterMs: Number.POSITIVE_INFINITY,
|
|
413
|
+
}).windows[0]
|
|
414
|
+
return {
|
|
415
|
+
key: row.key,
|
|
416
|
+
label: row.label,
|
|
417
|
+
window: row.window,
|
|
418
|
+
text: formatQuota(rowProjection, {
|
|
419
|
+
now,
|
|
420
|
+
form: 'compact',
|
|
421
|
+
staleAfterMs: Number.POSITIVE_INFINITY,
|
|
422
|
+
}),
|
|
423
|
+
resetText:
|
|
424
|
+
reset?.resetIn ?? (reset?.resetSinceReading ? 'reset' : undefined),
|
|
425
|
+
pacing:
|
|
426
|
+
pacingEnabled && row.windowMs !== null
|
|
427
|
+
? computeQuotaPacing(row.window, row.windowMs, now)
|
|
428
|
+
: null,
|
|
429
|
+
}
|
|
430
|
+
})
|
|
347
431
|
const spendControl = quota?.spendControl
|
|
348
432
|
if (spendControl) {
|
|
433
|
+
const rowProjection = projection && { ...projection, limits: [] }
|
|
434
|
+
const reset = quotaWindowParts(rowProjection, {
|
|
435
|
+
now,
|
|
436
|
+
staleAfterMs: Number.POSITIVE_INFINITY,
|
|
437
|
+
}).windows[0]
|
|
349
438
|
rows.push({
|
|
350
439
|
key: 'spendControl',
|
|
351
440
|
label: SPEND_CONTROL_LABEL,
|
|
352
|
-
text: formatQuota(
|
|
441
|
+
text: formatQuota(rowProjection, {
|
|
353
442
|
now,
|
|
354
443
|
form: 'compact',
|
|
355
444
|
staleAfterMs: Number.POSITIVE_INFINITY,
|
|
356
445
|
}),
|
|
446
|
+
resetText:
|
|
447
|
+
reset?.resetIn ?? (reset?.resetSinceReading ? 'reset' : undefined),
|
|
357
448
|
window: {
|
|
358
449
|
usedPercent: spendControl.usedPercent,
|
|
359
450
|
remainingPercent: spendControl.remainingPercent,
|
|
@@ -435,6 +526,7 @@ function QuotaRow(props: {
|
|
|
435
526
|
label: string
|
|
436
527
|
labelWidth: number
|
|
437
528
|
text: string
|
|
529
|
+
resetText?: string
|
|
438
530
|
window: { usedPercent: number; resetsAt?: string } | undefined
|
|
439
531
|
pacing: QuotaPacing | null
|
|
440
532
|
}) {
|
|
@@ -479,6 +571,9 @@ function QuotaRow(props: {
|
|
|
479
571
|
{` ${props.text.slice(props.label.length + 1)}`}
|
|
480
572
|
</text>
|
|
481
573
|
</box>
|
|
574
|
+
<Show when={props.resetText}>
|
|
575
|
+
<text fg={props.theme.textMuted}>{props.resetText}</text>
|
|
576
|
+
</Show>
|
|
482
577
|
</box>
|
|
483
578
|
<Show when={paceLine()}>
|
|
484
579
|
<box width='100%' flexDirection='row'>
|
|
@@ -506,6 +601,8 @@ function AccountBlock(props: {
|
|
|
506
601
|
name: string
|
|
507
602
|
quota: AccountQuota | null
|
|
508
603
|
killed: boolean
|
|
604
|
+
vaultState?: string
|
|
605
|
+
hostDisabled?: boolean
|
|
509
606
|
active: boolean
|
|
510
607
|
pacingEnabled: boolean
|
|
511
608
|
labelWidth: number
|
|
@@ -533,6 +630,12 @@ function AccountBlock(props: {
|
|
|
533
630
|
<b>{statusWord()}</b>
|
|
534
631
|
</text>
|
|
535
632
|
</box>
|
|
633
|
+
<Show when={props.vaultState}>
|
|
634
|
+
<text fg={props.theme.warning}>{props.vaultState}</text>
|
|
635
|
+
</Show>
|
|
636
|
+
<Show when={props.hostDisabled}>
|
|
637
|
+
<text fg={props.theme.textMuted}>off in /openai</text>
|
|
638
|
+
</Show>
|
|
536
639
|
<Show
|
|
537
640
|
when={isQuotaLoaded(props.quota)}
|
|
538
641
|
fallback={<text fg={props.theme.textMuted}>{'checking\u2026'}</text>}
|
|
@@ -549,6 +652,7 @@ function AccountBlock(props: {
|
|
|
549
652
|
label={row.label}
|
|
550
653
|
labelWidth={row.labelWidth}
|
|
551
654
|
text={row.text}
|
|
655
|
+
resetText={row.resetText}
|
|
552
656
|
window={row.window}
|
|
553
657
|
pacing={row.pacing}
|
|
554
658
|
/>
|
|
@@ -629,6 +733,7 @@ interface SidebarController {
|
|
|
629
733
|
prefs: () => OpenaiAuthTuiPrefs
|
|
630
734
|
collapsed: () => boolean
|
|
631
735
|
toggleCollapsed: () => void
|
|
736
|
+
dispose: () => void
|
|
632
737
|
}
|
|
633
738
|
|
|
634
739
|
// The TUI may unmount and remount sidebar_content when the user switches
|
|
@@ -651,14 +756,13 @@ function createSidebarController(
|
|
|
651
756
|
let lastPersistedCollapsed: boolean | null = initialPrefs.collapsed
|
|
652
757
|
let lastApplied = JSON.stringify(initialPrefs)
|
|
653
758
|
|
|
654
|
-
|
|
655
|
-
//
|
|
656
|
-
//
|
|
657
|
-
|
|
658
|
-
// `!==` check and cannot revert a user click.
|
|
659
|
-
watchTuiPreferences(() => {
|
|
759
|
+
let disposed = false
|
|
760
|
+
// Remember the last value written to disk, not an unpersisted click. A watcher
|
|
761
|
+
// echo of the previous disk value must not undo a click whose write is pending.
|
|
762
|
+
const unwatch = watchTuiPreferences(() => {
|
|
660
763
|
void (async () => {
|
|
661
764
|
const next = resolveOpenaiAuthPrefs(await readTuiPreferencesFile())
|
|
765
|
+
if (disposed) return
|
|
662
766
|
const serialized = JSON.stringify(next)
|
|
663
767
|
if (serialized === lastApplied) return
|
|
664
768
|
lastApplied = serialized
|
|
@@ -686,11 +790,27 @@ function createSidebarController(
|
|
|
686
790
|
}
|
|
687
791
|
}
|
|
688
792
|
|
|
689
|
-
return {
|
|
793
|
+
return {
|
|
794
|
+
prefs,
|
|
795
|
+
collapsed,
|
|
796
|
+
toggleCollapsed,
|
|
797
|
+
dispose() {
|
|
798
|
+
disposed = true
|
|
799
|
+
unwatch()
|
|
800
|
+
},
|
|
801
|
+
}
|
|
690
802
|
}
|
|
691
803
|
|
|
692
804
|
function QuotaSidebar(props: {
|
|
693
|
-
api:
|
|
805
|
+
api: {
|
|
806
|
+
theme: { readonly current: ThemeCurrent }
|
|
807
|
+
event: {
|
|
808
|
+
on(
|
|
809
|
+
type: 'session.updated' | 'message.updated',
|
|
810
|
+
listener: () => void,
|
|
811
|
+
): () => void
|
|
812
|
+
}
|
|
813
|
+
}
|
|
694
814
|
controller: SidebarController
|
|
695
815
|
sessionId: string
|
|
696
816
|
}) {
|
|
@@ -699,10 +819,12 @@ function QuotaSidebar(props: {
|
|
|
699
819
|
const [state, setState] = createSignal<SidebarState>(DEFAULT_SIDEBAR_STATE)
|
|
700
820
|
let lastUpdated = 0
|
|
701
821
|
let debounce: ReturnType<typeof setTimeout> | null = null
|
|
822
|
+
let disposed = false
|
|
702
823
|
|
|
703
824
|
async function refresh() {
|
|
825
|
+
if (disposed) return
|
|
704
826
|
const next = await readStateFromFile()
|
|
705
|
-
if (next.lastUpdated !== lastUpdated) {
|
|
827
|
+
if (!disposed && next.lastUpdated !== lastUpdated) {
|
|
706
828
|
lastUpdated = next.lastUpdated
|
|
707
829
|
setState(next)
|
|
708
830
|
}
|
|
@@ -727,9 +849,11 @@ function QuotaSidebar(props: {
|
|
|
727
849
|
props.api.event.on('session.updated', scheduleRefresh),
|
|
728
850
|
props.api.event.on('message.updated', scheduleRefresh),
|
|
729
851
|
]
|
|
730
|
-
setTimeout(refresh, 300)
|
|
852
|
+
const initialRefresh = setTimeout(refresh, 300)
|
|
731
853
|
|
|
732
854
|
onCleanup(() => {
|
|
855
|
+
disposed = true
|
|
856
|
+
clearTimeout(initialRefresh)
|
|
733
857
|
if (debounce) clearTimeout(debounce)
|
|
734
858
|
for (const u of unsubs) u()
|
|
735
859
|
})
|
|
@@ -740,11 +864,10 @@ function QuotaSidebar(props: {
|
|
|
740
864
|
// Vault mode: the host uses only the vault's accounts, which the file lists
|
|
741
865
|
// in `vaultAccounts`; main and the local fallbacks are not shown.
|
|
742
866
|
const vaultMode = () => state().vaultAccounts !== undefined
|
|
743
|
-
const
|
|
744
|
-
(state().vaultAccounts ?? []).filter((account) => account.enabled)
|
|
867
|
+
const vaultAccounts = () => state().vaultAccounts ?? []
|
|
745
868
|
const hasData = () =>
|
|
746
869
|
vaultMode()
|
|
747
|
-
?
|
|
870
|
+
? vaultAccounts().length > 0
|
|
748
871
|
: state().main?.quota != null || enabledFallbacks().length > 0
|
|
749
872
|
|
|
750
873
|
const headerLabel = () => {
|
|
@@ -759,6 +882,10 @@ function QuotaSidebar(props: {
|
|
|
759
882
|
route: sessionRouting().route,
|
|
760
883
|
})
|
|
761
884
|
const activeAccount = () => resolveActiveAccount(sessionState())
|
|
885
|
+
const collapsedLines = () =>
|
|
886
|
+
getCollapsedAccountLines(sessionState(), {
|
|
887
|
+
showFallbacks: prefs().sections.fallbackAccounts,
|
|
888
|
+
})
|
|
762
889
|
const quotaLabelWidth = () => computeQuotaLabelWidth(renderedQuotas(state()))
|
|
763
890
|
const activeQuotaSummary = () =>
|
|
764
891
|
getCollapsedQuotaSummary(activeAccount().quota)
|
|
@@ -788,8 +915,8 @@ function QuotaSidebar(props: {
|
|
|
788
915
|
}
|
|
789
916
|
const killedNames = () =>
|
|
790
917
|
[
|
|
791
|
-
state().main?.killed ? 'main' : '',
|
|
792
|
-
...enabledFallbacks()
|
|
918
|
+
!vaultMode() && state().main?.killed ? 'main' : '',
|
|
919
|
+
...(vaultMode() ? vaultAccounts() : enabledFallbacks())
|
|
793
920
|
.filter((f) => f.killed)
|
|
794
921
|
.map((f) => f.label ?? f.id),
|
|
795
922
|
].filter(Boolean)
|
|
@@ -846,28 +973,17 @@ function QuotaSidebar(props: {
|
|
|
846
973
|
</Show>
|
|
847
974
|
</box>
|
|
848
975
|
|
|
849
|
-
{/* Collapsed:
|
|
976
|
+
{/* Collapsed: one line per account, narrow quota text + dot (red ⊘ when killed) */}
|
|
850
977
|
<Show when={collapsed() && hasData()}>
|
|
851
|
-
<
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
<text
|
|
861
|
-
fg={toneColor(
|
|
862
|
-
theme(),
|
|
863
|
-
activeAccount().killed ? 'err' : activeQuotaTone(),
|
|
864
|
-
)}
|
|
865
|
-
>
|
|
866
|
-
{activeAccount().killed ? ' \u2298' : ' \u25cf'}
|
|
867
|
-
</text>
|
|
868
|
-
</box>
|
|
869
|
-
</Show>
|
|
870
|
-
</CollapsedRow>
|
|
978
|
+
<Index each={collapsedLines()}>
|
|
979
|
+
{(line) => (
|
|
980
|
+
<CollapsedAccountRow
|
|
981
|
+
theme={theme()}
|
|
982
|
+
line={line()}
|
|
983
|
+
tone={activeQuotaTone()}
|
|
984
|
+
/>
|
|
985
|
+
)}
|
|
986
|
+
</Index>
|
|
871
987
|
</Show>
|
|
872
988
|
|
|
873
989
|
{/* Expanded: full sections. Also render when there's no data so the
|
|
@@ -887,7 +1003,7 @@ function QuotaSidebar(props: {
|
|
|
887
1003
|
<Show
|
|
888
1004
|
when={!vaultMode()}
|
|
889
1005
|
fallback={
|
|
890
|
-
<For each={
|
|
1006
|
+
<For each={vaultAccounts()}>
|
|
891
1007
|
{(account, index) => (
|
|
892
1008
|
<AccountBlock
|
|
893
1009
|
theme={theme()}
|
|
@@ -895,6 +1011,8 @@ function QuotaSidebar(props: {
|
|
|
895
1011
|
name={account.label ?? account.id}
|
|
896
1012
|
quota={account.quota}
|
|
897
1013
|
killed={account.killed}
|
|
1014
|
+
vaultState={account.vaultState}
|
|
1015
|
+
hostDisabled={!account.enabled}
|
|
898
1016
|
active={sessionRouting().activeId === account.id}
|
|
899
1017
|
pacingEnabled={prefs().sections.pacing}
|
|
900
1018
|
labelWidth={quotaLabelWidth()}
|
|
@@ -1064,8 +1182,48 @@ const tui: TuiPlugin = async (api) => {
|
|
|
1064
1182
|
}
|
|
1065
1183
|
}
|
|
1066
1184
|
|
|
1067
|
-
|
|
1185
|
+
async function setup(
|
|
1186
|
+
context: Plugin.Context,
|
|
1187
|
+
options: TuiTransportOptions = {},
|
|
1188
|
+
) {
|
|
1189
|
+
if (options.sidebarText !== undefined || options.sidebar)
|
|
1190
|
+
return setupTui(context, options)
|
|
1191
|
+
const root = await readTuiPreferencesFile()
|
|
1192
|
+
const controller = createSidebarController(resolveOpenaiAuthPrefs(root))
|
|
1193
|
+
const api = {
|
|
1194
|
+
theme: {
|
|
1195
|
+
get current() {
|
|
1196
|
+
return context.theme
|
|
1197
|
+
},
|
|
1198
|
+
},
|
|
1199
|
+
event: {
|
|
1200
|
+
on: (type: 'session.updated' | 'message.updated', listener: () => void) =>
|
|
1201
|
+
context.data.on(
|
|
1202
|
+
type === 'session.updated'
|
|
1203
|
+
? 'session.metadata.updated'
|
|
1204
|
+
: 'session.usage.updated',
|
|
1205
|
+
listener,
|
|
1206
|
+
),
|
|
1207
|
+
},
|
|
1208
|
+
}
|
|
1209
|
+
return setupTui(context, {
|
|
1210
|
+
...options,
|
|
1211
|
+
sidebar: {
|
|
1212
|
+
render: (input) => (
|
|
1213
|
+
<QuotaSidebar
|
|
1214
|
+
api={api}
|
|
1215
|
+
controller={controller}
|
|
1216
|
+
sessionId={input.sessionID}
|
|
1217
|
+
/>
|
|
1218
|
+
),
|
|
1219
|
+
dispose: controller.dispose,
|
|
1220
|
+
},
|
|
1221
|
+
})
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
const plugin: TuiPluginModule & { id: string; setup: typeof setup } = {
|
|
1068
1225
|
id: ID,
|
|
1226
|
+
setup,
|
|
1069
1227
|
tui,
|
|
1070
1228
|
}
|
|
1071
1229
|
|