@brimveyn/aimux-config 0.10.1 → 0.10.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brimveyn/aimux-config",
3
- "version": "0.10.1",
3
+ "version": "0.10.3",
4
4
  "description": "TypeScript configuration API for aimux — keymaps, themes, and backends with a fluent builder.",
5
5
  "keywords": [
6
6
  "aimux",
package/src/actions.ts CHANGED
@@ -61,11 +61,15 @@ export function toggleWidget(widgetId: string): KeyResult {
61
61
  }
62
62
  export const toggleGitPane: KeyResult = toggleWidget('git')
63
63
  export const toggleProjectBar: KeyResult = r([{ type: 'toggle-project-bar' }])
64
- export const toggleAIUsage: ActionFn = (ctx: ModeContext) => {
65
- if (ctx.state.modal.type === 'ai-usage') {
66
- return r([{ type: 'close-modal' }], [], 'navigation')
64
+ /**
65
+ * The stats screen, which replaced the AI-usage popover: the quota windows it
66
+ * showed are now its first page.
67
+ */
68
+ export const toggleStats: ActionFn = (ctx: ModeContext) => {
69
+ if (ctx.state.focusMode === 'stats') {
70
+ return r([{ type: 'exit-stats' }], [], 'navigation')
67
71
  }
68
- return r([{ type: 'open-ai-usage-modal' }], [], 'modal.ai-usage')
72
+ return r([{ type: 'enter-stats' }], [], 'stats')
69
73
  }
70
74
 
71
75
  export const enterGitMode: KeyResult = r([{ type: 'enter-git-mode' }], [], 'git-mode')
@@ -951,23 +955,36 @@ export const gitCommitReturnKey: ActionFn = (ctx: ModeContext) => {
951
955
  export const enterSettings: KeyResult = r([{ type: 'enter-settings' }], [], 'settings')
952
956
  export const exitSettings: KeyResult = r([{ type: 'exit-settings' }], [], 'navigation')
953
957
 
954
- export function focusSettingsPane(pane: 'nav' | 'rows'): KeyResult {
955
- return r([{ pane, type: 'settings-focus-pane' }])
958
+ // ---------------------------------------------------------------------------
959
+ // Stats screen
960
+ // ---------------------------------------------------------------------------
961
+
962
+ export const enterStats: KeyResult = r([{ type: 'enter-stats' }], [], 'stats')
963
+ export const exitStats: KeyResult = r([{ type: 'exit-stats' }], [], 'navigation')
964
+
965
+ export function moveStatsPage(delta: -1 | 1): KeyResult {
966
+ return r([{ delta, type: 'stats-move-page' }])
967
+ }
968
+
969
+ export function scrollStats(delta: number): KeyResult {
970
+ return r([{ delta, type: 'stats-scroll' }])
956
971
  }
957
972
 
958
973
  export function moveSettingsSelection(delta: -1 | 1): KeyResult {
959
974
  return r([{ delta, type: 'settings-move-selection' }])
960
975
  }
961
976
 
977
+ /** To the first row of the next section, the way `}` moves by paragraph. */
978
+ export function jumpSettingsSection(delta: -1 | 1): KeyResult {
979
+ return r([{ delta, type: 'settings-jump-section' }])
980
+ }
981
+
962
982
  /**
963
983
  * One key for every kind of row: it toggles a checkbox, advances an enum, or runs
964
984
  * whatever the row does. Which one is the row's business, not the keymap's — so
965
985
  * there is no per-kind binding to keep in sync with the schema.
966
986
  */
967
- export const activateSettingsRow: ActionFn = (ctx: ModeContext) => {
968
- if (ctx.state.settings.pane !== 'rows') return r([{ pane: 'rows', type: 'settings-focus-pane' }])
969
- return r([], [{ type: 'activate-settings-row' }])
970
- }
987
+ export const activateSettingsRow: KeyResult = r([], [{ type: 'activate-settings-row' }])
971
988
 
972
989
  export function adjustSettingsRow(delta: 1 | -1): KeyResult {
973
990
  return r([], [{ delta, type: 'adjust-settings-row' }])
package/src/defaults.ts CHANGED
@@ -104,7 +104,7 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
104
104
  m
105
105
  .map('<Leader>b', actions.toggleProjectBar, 'Toggle project bar')
106
106
  .map('<Leader>B', actions.toggleBar('right'), 'Toggle right bar')
107
- .map('<Leader>u', actions.toggleAIUsage, 'Toggle AI usage')
107
+ .map('<Leader>u', actions.toggleStats, 'Stats')
108
108
  .map('<Leader>,', actions.enterSettings, 'Settings')
109
109
  .map('<Leader>1', actions.switchTabByIndex(1), 'Tab 1')
110
110
  .map('<Leader>2', actions.switchTabByIndex(2), 'Tab 2')
@@ -159,19 +159,21 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
159
159
  // -----------------------------------------------------------------------
160
160
  // Settings screen
161
161
  //
162
- // `h`/`l` always mean "change column", never "change value": a number row
163
- // would otherwise make them ambiguous. Values move on <Space>/<CR> (toggle,
164
- // next option) and on -/+ (step a number).
162
+ // One list, sections included, so every key here moves a single cursor:
163
+ // `j`/`k` a row, `}`/`{` a section, `/` searches the same list from a
164
+ // picker.
165
+ //
166
+ // The two axes are the whole grammar: across a row changes its value —
167
+ // `h`/`l`, the arrows and -/+ all drag the gauge, step the enum, set the
168
+ // checkbox — and <CR> hands over to a field for the value you would rather
169
+ // type than aim at. Nothing here is a column any more, which is what freed
170
+ // `h`/`l` to mean what they read like.
165
171
  // -----------------------------------------------------------------------
166
172
  .mode('settings', (m) =>
167
173
  m
168
174
  .map('<Esc>', actions.exitSettings, 'Close settings')
169
175
  .map('<Leader>,', actions.exitSettings, 'Close settings')
170
- .map('h', actions.focusSettingsPane('nav'), 'Sections')
171
- .map('<Left>', actions.focusSettingsPane('nav'))
172
- .map('l', actions.activateSettingsRow, 'Settings of the section')
173
- .map('<Right>', actions.activateSettingsRow)
174
- .map('<CR>', actions.activateSettingsRow, 'Change')
176
+ .map('<CR>', actions.activateSettingsRow, 'Change, or type a value')
175
177
  .map('<Space>', actions.activateSettingsRow, 'Change')
176
178
  .map('j', actions.moveSettingsSelection(1), 'Next', { repeatable: true })
177
179
  .map('k', actions.moveSettingsSelection(-1), 'Prev', { repeatable: true })
@@ -179,8 +181,14 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
179
181
  .map('<Up>', actions.moveSettingsSelection(-1), undefined, { repeatable: true })
180
182
  .map('<C-n>', actions.moveSettingsSelection(1))
181
183
  .map('<C-p>', actions.moveSettingsSelection(-1))
182
- .map('+', actions.adjustSettingsRow(1), 'Increase', { repeatable: true })
183
- .map('-', actions.adjustSettingsRow(-1), 'Decrease', { repeatable: true })
184
+ .map('}', actions.jumpSettingsSection(1), 'Next section', { repeatable: true })
185
+ .map('{', actions.jumpSettingsSection(-1), 'Prev section', { repeatable: true })
186
+ .map('l', actions.adjustSettingsRow(1), 'Increase', { repeatable: true })
187
+ .map('<Right>', actions.adjustSettingsRow(1), undefined, { repeatable: true })
188
+ .map('+', actions.adjustSettingsRow(1), undefined, { repeatable: true })
189
+ .map('h', actions.adjustSettingsRow(-1), 'Decrease', { repeatable: true })
190
+ .map('<Left>', actions.adjustSettingsRow(-1), undefined, { repeatable: true })
191
+ .map('-', actions.adjustSettingsRow(-1), undefined, { repeatable: true })
184
192
  .map('r', actions.resetSettingsRow, 'Reset to default')
185
193
  .map('/', actions.openSettingsSearch, 'Search settings')
186
194
  .map('?', actions.helpModal('settings'), 'Help')
@@ -216,18 +224,33 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
216
224
  )
217
225
 
218
226
  // -----------------------------------------------------------------------
219
- // Modal: ai-usage (info-only)
227
+ // Stats screen (read-only)
228
+ //
229
+ // `h`/`l` change page and `j`/`k` scroll it — the same split the settings
230
+ // screen uses, where the horizontal pair never touches content.
220
231
  // -----------------------------------------------------------------------
221
- .mode('modal.ai-usage', (m) =>
232
+ .mode('stats', (m) =>
222
233
  m
223
- .map('<Esc>', actions.closeModal, 'Close')
224
- .map('<Leader>u', actions.toggleAIUsage, 'Close')
225
- .map('l', actions.moveModalSelection(1), 'Next page')
226
- .map('h', actions.moveModalSelection(-1), 'Prev page')
227
- .map('<Right>', actions.moveModalSelection(1))
228
- .map('<Left>', actions.moveModalSelection(-1))
234
+ .map('<Esc>', actions.exitStats, 'Close stats')
235
+ .map('<Leader>u', actions.exitStats, 'Close stats')
236
+ .map('l', actions.moveStatsPage(1), 'Next page')
237
+ .map('h', actions.moveStatsPage(-1), 'Prev page')
238
+ .map('<Right>', actions.moveStatsPage(1))
239
+ .map('<Left>', actions.moveStatsPage(-1))
240
+ .map('j', actions.scrollStats(1), 'Scroll down', { repeatable: true })
241
+ .map('k', actions.scrollStats(-1), 'Scroll up', { repeatable: true })
242
+ .map('<Down>', actions.scrollStats(1), undefined, { repeatable: true })
243
+ .map('<Up>', actions.scrollStats(-1), undefined, { repeatable: true })
244
+ .map('<C-d>', actions.scrollStats(10), 'Page down')
245
+ .map('<C-u>', actions.scrollStats(-10), 'Page up')
246
+ .map('?', actions.helpModal('stats'), 'Help')
229
247
  )
230
248
 
249
+ // -----------------------------------------------------------------------
250
+ // Modal: quotas (read-only — the status bar indicator, expanded)
251
+ // -----------------------------------------------------------------------
252
+ .mode('modal.quotas', (m) => m.map('<Esc>', actions.closeModal, 'Close'))
253
+
231
254
  // -----------------------------------------------------------------------
232
255
  // Modal: update-available
233
256
  // -----------------------------------------------------------------------
package/src/types.ts CHANGED
@@ -34,9 +34,10 @@ export type ModeId =
34
34
  | 'modal.update-available'
35
35
  | 'modal.workspace-move'
36
36
  | 'modal.workspace-move-confirm'
37
- | 'modal.ai-usage'
38
37
  | 'modal.flash-jump'
38
+ | 'modal.quotas'
39
39
  | 'settings'
40
+ | 'stats'
40
41
 
41
42
  // ─── Primitive app types ──────────────────────────────────────────────────────
42
43
 
@@ -73,6 +74,7 @@ export type FocusMode =
73
74
  | 'command-edit'
74
75
  | 'git'
75
76
  | 'settings'
77
+ | 'stats'
76
78
  export type SplitDirection = 'horizontal' | 'vertical'
77
79
 
78
80
  // ─── Terminal data shapes ─────────────────────────────────────────────────────
@@ -441,8 +443,9 @@ export interface ModalUpdateAvailable extends ModalBase {
441
443
  latestVersion: string
442
444
  }
443
445
 
444
- export interface ModalAIUsage extends ModalBase {
445
- type: 'ai-usage'
446
+ /** The status bar's usage indicator, expanded. Carries nothing: it is a readout. */
447
+ export interface ModalQuotas extends ModalBase {
448
+ type: 'quotas'
446
449
  }
447
450
 
448
451
  export interface ModalWorkspaceMove extends ModalBase {
@@ -527,7 +530,7 @@ export type ModalState =
527
530
  | ModalSnippetEditor
528
531
  | ModalGitCommit
529
532
  | ModalUpdateAvailable
530
- | ModalAIUsage
533
+ | ModalQuotas
531
534
  | ModalWorkspaceMove
532
535
  | ModalWorkspaceMoveConfirm
533
536
  | ModalWorkspaceDeleteConfirm
@@ -579,11 +582,15 @@ export interface MultiRepoState {
579
582
 
580
583
  /** Where the cursor is in the settings screen — the cursor only, not the values. */
581
584
  export interface SettingsUIState {
582
- sectionId: string
583
- pane: 'nav' | 'rows'
584
585
  rowIndex: number
585
586
  }
586
587
 
588
+ /** Mirror of the CLI's `StatsUIState`. */
589
+ export interface StatsUIState {
590
+ pageIndex: number
591
+ scrollTop: number
592
+ }
593
+
587
594
  export interface AppState {
588
595
  tabs: TabSession[]
589
596
  activeTabId: string | null
@@ -605,6 +612,7 @@ export interface AppState {
605
612
  autoCommit: AutoCommitState
606
613
  multiRepo: MultiRepoState
607
614
  settings: SettingsUIState
615
+ stats: StatsUIState
608
616
  workspaceDivergence: Record<string, BranchDivergence>
609
617
  workspaceActivity: Record<string, WorkspaceActivity>
610
618
  lastActiveTabByWorkspace: Record<string, string>
@@ -653,8 +661,8 @@ export type ModalAction =
653
661
  | { type: 'set-theme-entry-count'; count: number }
654
662
  | { type: 'open-theme-picker'; returnTo?: FocusMode }
655
663
  | { type: 'open-update-available-modal'; currentVersion: string; latestVersion: string }
664
+ | { type: 'open-quotas-modal' }
656
665
  | { type: 'set-modal-selection-index'; index: number }
657
- | { type: 'open-ai-usage-modal' }
658
666
  | { type: 'open-edit-custom-command'; assistantId: AssistantId }
659
667
  | { type: 'open-workspace-move-modal'; sourceWorkspaceId: string }
660
668
  | { type: 'toggle-workspace-move-delete' }
@@ -775,13 +783,22 @@ export type UIAction =
775
783
  export type SettingsAction =
776
784
  | { type: 'enter-settings' }
777
785
  | { type: 'exit-settings' }
778
- | { type: 'settings-focus-pane'; pane: 'nav' | 'rows' }
779
786
  | { type: 'settings-move-selection'; delta: -1 | 1 }
780
- | { type: 'settings-select-section'; sectionId: string }
787
+ | { type: 'settings-jump-section'; delta: -1 | 1 }
781
788
  | { type: 'settings-select-row'; rowIndex: number }
782
789
  | { type: 'open-settings-search' }
783
790
  | { type: 'open-setting-text-modal'; settingId: string; label: string; value: string }
784
791
 
792
+ export type StatsAction =
793
+ | { type: 'enter-stats' }
794
+ | { type: 'exit-stats' }
795
+ | { type: 'stats-move-page'; delta: -1 | 1 }
796
+ | { type: 'stats-select-page'; pageIndex: number }
797
+ /** Rows, not pixels: the view holds a scroll offset the page applies to its box. */
798
+ | { type: 'stats-scroll'; delta: number }
799
+ /** The offset the scrollbox actually accepted, sent back so the state cannot run past the page. */
800
+ | { type: 'stats-scroll-settled'; scrollTop: number }
801
+
785
802
  export interface GitRefreshPayload {
786
803
  branch: string | null
787
804
  ahead: number
@@ -878,6 +895,7 @@ export type AppAction =
878
895
  | LayoutAction
879
896
  | UIAction
880
897
  | SettingsAction
898
+ | StatsAction
881
899
  | DataAction
882
900
  | GitPanelAction
883
901
  | GitModeAction