opencode-dux 1.1.1 → 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/src/tui.ts CHANGED
@@ -7,6 +7,7 @@ import { createElement, insert, setProp } from '@opentui/solid';
7
7
  import { createSignal } from 'solid-js';
8
8
  import { AGENT_SIDEBAR_DESCRIPTIONS } from './agents/descriptions';
9
9
  import type {
10
+ CodexUsageEntry,
10
11
  NeuralwattUsage,
11
12
  NeuralwattUsageEntry,
12
13
  } from './subscriptions/types';
@@ -577,6 +578,64 @@ function renderNeuralwattUsage(
577
578
  }
578
579
  }
579
580
 
581
+ function renderCodexUsage(
582
+ entry: CodexUsageEntry,
583
+ rows: Child[],
584
+ theme: { text: unknown; textMuted: unknown; accent: unknown },
585
+ ): void {
586
+ // 5H row
587
+ if (entry.primaryWindow) {
588
+ const w = entry.primaryWindow;
589
+ const usageColor = getUsageColor(w.percentRemaining);
590
+ const bar = renderUsageBar(w.percentRemaining);
591
+ const pct = w.percentRemaining.toFixed(0).padStart(3);
592
+ const timeLeft = formatUsageTime(w.resetTimeIso);
593
+
594
+ rows.push(
595
+ box({ width: '100%', flexDirection: 'row', justifyContent: 'space-between' }, [
596
+ box({ flexDirection: 'row' }, [
597
+ text({ fg: theme.accent }, ['5H ']),
598
+ text({ fg: usageColor || theme.text }, [bar]),
599
+ text({ fg: usageColor || theme.textMuted }, [` ${pct}%`]),
600
+ ]),
601
+ text({ fg: theme.textMuted }, [timeLeft]),
602
+ ]),
603
+ );
604
+ }
605
+
606
+ // 7D row
607
+ if (entry.secondaryWindow) {
608
+ const w = entry.secondaryWindow;
609
+ const usageColor = getUsageColor(w.percentRemaining);
610
+ const bar = renderUsageBar(w.percentRemaining);
611
+ const pct = w.percentRemaining.toFixed(0).padStart(3);
612
+ const timeLeft = formatUsageTime(w.resetTimeIso);
613
+
614
+ rows.push(
615
+ box({ width: '100%', flexDirection: 'row', justifyContent: 'space-between' }, [
616
+ box({ flexDirection: 'row' }, [
617
+ text({ fg: theme.accent }, ['7D ']),
618
+ text({ fg: usageColor || theme.text }, [bar]),
619
+ text({ fg: usageColor || theme.textMuted }, [` ${pct}%`]),
620
+ ]),
621
+ text({ fg: theme.textMuted }, [timeLeft]),
622
+ ]),
623
+ );
624
+ }
625
+
626
+ // Credits row
627
+ const balance = entry.credits.balance;
628
+ rows.push(
629
+ box({ width: '100%', flexDirection: 'row' }, [
630
+ text({ fg: theme.text }, [
631
+ entry.credits.unlimited
632
+ ? '💰 Unlimited credits'
633
+ : `💰 $${balance.toFixed(2)} credits`,
634
+ ]),
635
+ ]),
636
+ );
637
+ }
638
+
580
639
  function renderSubscriptionPanel(
581
640
  snapshot: TuiSnapshot,
582
641
  theme: {
@@ -600,7 +659,7 @@ function renderSubscriptionPanel(
600
659
  const name = entry.accountName;
601
660
  const activeName = snapshot.activeSubscriptionByProvider?.[entry.provider];
602
661
  const isActive = activeName === name;
603
- const providerLabel = entry.provider === 'neuralwatt' ? ' [nw]' : ' [go]';
662
+ const providerLabel = entry.provider === 'neuralwatt' ? ' [nw]' : entry.provider === 'codex' ? ' [cx]' : ' [go]';
604
663
 
605
664
  if (!isFirstAccount) {
606
665
  rows.push(box({ width: '100%', height: 1 }));
@@ -641,6 +700,8 @@ function renderSubscriptionPanel(
641
700
  renderOpenCodeGoBars(entry, rows, theme);
642
701
  } else if (entry.provider === 'neuralwatt') {
643
702
  renderNeuralwattUsage(entry, rows, theme);
703
+ } else if (entry.provider === 'codex') {
704
+ renderCodexUsage(entry as CodexUsageEntry, rows, theme);
644
705
  } else {
645
706
  rows.push(
646
707
  text({ fg: '#F39C12' }, [