@brimveyn/aimux 1.6.1 → 1.7.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.
Files changed (71) hide show
  1. package/README.md +3 -0
  2. package/package.json +2 -2
  3. package/src/app-runtime/backend-attach-runtime.ts +6 -0
  4. package/src/app-runtime/backend-runtime-events.ts +21 -21
  5. package/src/app-runtime/side-effects.ts +43 -12
  6. package/src/app-runtime/use-backend-runtime.ts +2 -20
  7. package/src/app-runtime/use-directory-search.ts +6 -1
  8. package/src/app.tsx +6 -1
  9. package/src/config.ts +28 -1
  10. package/src/daemon/daemon.ts +197 -15
  11. package/src/daemon/session-manager.ts +9 -0
  12. package/src/daemon/session-registry.ts +5 -5
  13. package/src/git/diff-hash.ts +10 -0
  14. package/src/index.tsx +10 -2
  15. package/src/input/keymap/help-entries.ts +5 -5
  16. package/src/input/modes/bridge.ts +5 -8
  17. package/src/input/modes/transitions.ts +15 -23
  18. package/src/input/modes/types.ts +3 -5
  19. package/src/ipc/protocol.ts +49 -5
  20. package/src/platform/project-search.ts +45 -12
  21. package/src/pty/assistant-status-detection-loop.ts +192 -0
  22. package/src/pty/assistant-status-detector.ts +226 -0
  23. package/src/pty/pty-manager.ts +3 -37
  24. package/src/session-backend/bootstrap.ts +4 -1
  25. package/src/session-backend/local-session-backend.ts +43 -56
  26. package/src/session-backend/remote-session-backend.ts +15 -0
  27. package/src/session-backend/types.ts +10 -1
  28. package/src/state/git-tree.ts +42 -16
  29. package/src/state/reducers/diff-cache.ts +64 -0
  30. package/src/state/reducers/git-mode-state.ts +91 -33
  31. package/src/state/reducers/git-panel-state.ts +33 -2
  32. package/src/state/reducers/modal-state.ts +91 -134
  33. package/src/state/reducers/session-state.ts +13 -6
  34. package/src/state/reducers/tab-state.ts +0 -10
  35. package/src/state/selectors.ts +12 -0
  36. package/src/state/session-persistence.ts +20 -15
  37. package/src/state/store.ts +13 -3
  38. package/src/state/types.ts +87 -14
  39. package/src/ui/breaking-update-screen.tsx +31 -0
  40. package/src/ui/components/bare-input.tsx +44 -0
  41. package/src/ui/components/create-session-modal.tsx +16 -8
  42. package/src/ui/components/diff-renderer/fold-strip.tsx +5 -13
  43. package/src/ui/components/diff-renderer/pierre-diff.tsx +9 -31
  44. package/src/ui/components/diff-renderer/prepare-diff.ts +66 -0
  45. package/src/ui/components/diff-renderer/split-view.tsx +35 -16
  46. package/src/ui/components/diff-renderer/stacked-view.tsx +30 -12
  47. package/src/ui/components/diff-renderer/use-diff-prefetch.ts +191 -0
  48. package/src/ui/components/diff-renderer/use-diff-preparation.ts +106 -0
  49. package/src/ui/components/git-pane-widget.tsx +2 -0
  50. package/src/ui/components/git-panel.tsx +27 -10
  51. package/src/ui/components/git-view.tsx +23 -9
  52. package/src/ui/components/help-modal.tsx +45 -160
  53. package/src/ui/components/input-field.tsx +6 -2
  54. package/src/ui/components/list-item.tsx +36 -28
  55. package/src/ui/components/modal-shell.tsx +51 -13
  56. package/src/ui/components/new-tab-modal.tsx +78 -45
  57. package/src/ui/components/picker.tsx +179 -0
  58. package/src/ui/components/session-bar.tsx +47 -21
  59. package/src/ui/components/session-picker-modal.tsx +58 -56
  60. package/src/ui/components/sidebar.tsx +49 -22
  61. package/src/ui/components/snippet-picker-modal.tsx +43 -34
  62. package/src/ui/components/status-bar.tsx +3 -2
  63. package/src/ui/components/surface.tsx +11 -8
  64. package/src/ui/components/tab-item.tsx +38 -22
  65. package/src/ui/components/terminal-pane.tsx +8 -8
  66. package/src/ui/components/theme-picker-modal.tsx +51 -91
  67. package/src/ui/root.tsx +14 -23
  68. package/src/ui/status-bar-model.ts +5 -5
  69. package/src/ui/theme-store.ts +26 -2
  70. package/src/ui/theme.ts +9 -1
  71. package/src/ui/components/modal-filter-bar.tsx +0 -19
package/src/ui/root.tsx CHANGED
@@ -24,7 +24,7 @@ import { StatusBar } from './components/status-bar'
24
24
  import { TerminalPane } from './components/terminal-pane'
25
25
  import { ThemePickerModal } from './components/theme-picker-modal'
26
26
  import { UpdateAvailableModal } from './components/update-available-modal'
27
- import { useTheme } from './theme'
27
+ import { useBg } from './theme'
28
28
 
29
29
  function getCreateSessionFields(modal: ModalState) {
30
30
  if (modal.type !== 'create-session') {
@@ -82,7 +82,10 @@ function renderModal(
82
82
  <NewTabModal
83
83
  selectedIndex={modal.selectedIndex}
84
84
  customCommands={options.customCommands}
85
- editBuffer={modal.editBuffer}
85
+ filter={modal.editBuffer}
86
+ cursorPos={modal.cursorPos}
87
+ editingCommand={modal.type === 'new-tab' ? modal.editingCommand : null}
88
+ editBuffer={modal.editBuffer ?? ''}
86
89
  />
87
90
  )
88
91
  case 'session-picker':
@@ -93,6 +96,7 @@ function renderModal(
93
96
  currentSessionId={options.currentSessionId}
94
97
  currentTabCount={options.currentTabCount}
95
98
  filter={modal.editBuffer}
99
+ cursorPos={modal.cursorPos}
96
100
  />
97
101
  )
98
102
  case 'session-name':
@@ -121,6 +125,7 @@ function renderModal(
121
125
  snippets={options.snippets}
122
126
  selectedIndex={modal.selectedIndex}
123
127
  filter={modal.editBuffer}
128
+ cursorPos={modal.cursorPos}
124
129
  />
125
130
  )
126
131
  case 'snippet-editor':
@@ -138,6 +143,7 @@ function renderModal(
138
143
  selectedIndex={modal.selectedIndex}
139
144
  currentThemeId={options.themeId}
140
145
  filter={modal.editBuffer}
146
+ cursorPos={modal.cursorPos}
141
147
  />
142
148
  )
143
149
  case 'update-available':
@@ -154,6 +160,7 @@ function renderModal(
154
160
  filter={modal.editBuffer}
155
161
  selectedIndex={modal.selectedIndex}
156
162
  scope={modal.scope}
163
+ cursorPos={modal.cursorPos}
157
164
  />
158
165
  )
159
166
  case 'git-commit': {
@@ -215,7 +222,7 @@ export function RootView({
215
222
  terminalRows,
216
223
  themeId,
217
224
  }: RootViewProps) {
218
- const theme = useTheme()
225
+ const editorBg = useBg('editor.background')
219
226
  const tabs = useAppStore((s) => s.tabs)
220
227
  const activeTabId = useAppStore((s) => s.activeTabId)
221
228
  const layoutTrees = useAppStore((s) => s.layoutTrees)
@@ -241,12 +248,7 @@ export function RootView({
241
248
  const inGitMode = focusMode === 'git' || modal.type === 'git-commit'
242
249
  if (inGitMode) {
243
250
  return (
244
- <box
245
- flexDirection="column"
246
- width="100%"
247
- height="100%"
248
- backgroundColor={theme.colors['editor.background']}
249
- >
251
+ <box flexDirection="column" width="100%" height="100%" backgroundColor={editorBg}>
250
252
  <GitView themeId={themeId} />
251
253
  <StatusBar />
252
254
  <PendingChordOverlay />
@@ -265,12 +267,7 @@ export function RootView({
265
267
  }
266
268
 
267
269
  return (
268
- <box
269
- flexDirection="column"
270
- width="100%"
271
- height="100%"
272
- backgroundColor={theme.colors['editor.background']}
273
- >
270
+ <box flexDirection="column" width="100%" height="100%" backgroundColor={editorBg}>
274
271
  {sessionBarPosition === 'top' && <SessionBar />}
275
272
  <box flexDirection="row" gap={0} padding={0} flexGrow={1}>
276
273
  <Sidebar onTabActivate={onPaneActivate} />
@@ -343,18 +340,12 @@ export function RootView({
343
340
  }
344
341
 
345
342
  function GitPaneInPaneMode({ ratio }: { ratio: number }) {
346
- const theme = useTheme()
343
+ const bg = useBg('sideBar.background')
347
344
  // Ratio maps to a fixed column count (20..80), mirroring the reservation in
348
345
  // use-terminal-resize so the terminal-content area stays in sync.
349
346
  const width = Math.max(20, Math.min(80, Math.round(ratio * 80)))
350
347
  return (
351
- <box
352
- flexDirection="column"
353
- width={width}
354
- flexShrink={0}
355
- backgroundColor={theme.colors['sideBar.background']}
356
- overflow="hidden"
357
- >
348
+ <box flexDirection="column" width={width} flexShrink={0} backgroundColor={bg} overflow="hidden">
358
349
  <GitPaneWidget pollingEnabled />
359
350
  </box>
360
351
  )
@@ -114,17 +114,17 @@ export function getStatusBarModel(
114
114
  function deriveModalModeId(modalType: AppState['modal']['type']): ModeId | null {
115
115
  switch (modalType) {
116
116
  case 'help':
117
- return 'modal.help'
117
+ return 'modal.help.filtering'
118
118
  case 'new-tab':
119
- return 'modal.new-tab'
119
+ return 'modal.new-tab.command-edit'
120
120
  case 'session-picker':
121
- return 'modal.session-picker'
121
+ return 'modal.session-picker.filtering'
122
122
  case 'snippet-picker':
123
- return 'modal.snippet-picker'
123
+ return 'modal.snippet-picker.filtering'
124
124
  case 'split-picker':
125
125
  return 'modal.split-picker'
126
126
  case 'theme-picker':
127
- return 'modal.theme-picker'
127
+ return 'modal.theme-picker.filtering'
128
128
  case 'update-available':
129
129
  return 'modal.update-available'
130
130
  default:
@@ -1,16 +1,17 @@
1
1
  import { useStore } from 'zustand'
2
2
  import { createStore } from 'zustand/vanilla'
3
3
 
4
- import { type Theme, type ThemeId, THEMES } from './themes'
4
+ import { type Theme, type ThemeColorMap, type ThemeId, THEMES } from './themes'
5
5
 
6
6
  interface ThemeStore {
7
7
  theme: Theme
8
+ transparent: boolean
8
9
  }
9
10
 
10
11
  const DEFAULT = THEMES['aimux']
11
12
  if (!DEFAULT) throw new Error('default theme missing')
12
13
 
13
- const themeStore = createStore<ThemeStore>(() => ({ theme: DEFAULT }))
14
+ const themeStore = createStore<ThemeStore>(() => ({ theme: DEFAULT, transparent: false }))
14
15
 
15
16
  /**
16
17
  * Subscribe to the active theme. Pass a selector to subscribe to a narrower
@@ -34,3 +35,26 @@ export function applyTheme(id: ThemeId): void {
34
35
  if (!entry) return
35
36
  themeStore.setState({ theme: entry })
36
37
  }
38
+
39
+ /** Subscribe to the transparent-mode flag. */
40
+ export function useTransparent(): boolean {
41
+ return useStore(themeStore, (s) => s.transparent)
42
+ }
43
+
44
+ export function getTransparent(): boolean {
45
+ return themeStore.getState().transparent
46
+ }
47
+
48
+ export function setTransparent(value: boolean): void {
49
+ if (themeStore.getState().transparent === value) return
50
+ themeStore.setState({ transparent: value })
51
+ }
52
+
53
+ /**
54
+ * Resolve a background color through the transparent-mode flag. Returns
55
+ * `undefined` when transparent mode is on, letting the terminal emulator's
56
+ * own background show through.
57
+ */
58
+ export function useBg(key: keyof ThemeColorMap): string | undefined {
59
+ return useStore(themeStore, (s) => (s.transparent ? undefined : s.theme.colors[key]))
60
+ }
package/src/ui/theme.ts CHANGED
@@ -2,4 +2,12 @@
2
2
  // React components should import `useTheme` from `./theme-store`; non-React
3
3
  // callers use `getCurrentTheme()`. `applyTheme` moved to the store module.
4
4
 
5
- export { applyTheme, getCurrentTheme, useTheme } from './theme-store'
5
+ export {
6
+ applyTheme,
7
+ getCurrentTheme,
8
+ getTransparent,
9
+ setTransparent,
10
+ useBg,
11
+ useTheme,
12
+ useTransparent,
13
+ } from './theme-store'
@@ -1,19 +0,0 @@
1
- import { useTheme } from '../theme'
2
- import { Surface } from './surface'
3
-
4
- interface ModalFilterBarProps {
5
- filter: string | null
6
- }
7
-
8
- export function ModalFilterBar({ filter }: ModalFilterBarProps) {
9
- const theme = useTheme()
10
- if (filter === null) {
11
- return null
12
- }
13
-
14
- return (
15
- <Surface tone="input" paddingLeft={1} paddingRight={1} paddingTop={1} paddingBottom={1}>
16
- <text fg={theme.colors['editor.foreground']}>/{filter}_</text>
17
- </Surface>
18
- )
19
- }