@brimveyn/aimux 1.4.0 → 1.5.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 (53) hide show
  1. package/README.md +142 -176
  2. package/package.json +7 -3
  3. package/src/app-runtime/use-terminal-resize.ts +112 -32
  4. package/src/app.tsx +20 -3
  5. package/src/config.ts +53 -17
  6. package/src/daemon/session-manager.ts +11 -4
  7. package/src/daemon/session-registry.ts +15 -4
  8. package/src/index.tsx +6 -1
  9. package/src/input/keymap/build-handlers.ts +1 -0
  10. package/src/input/keymap/help-entries.ts +44 -0
  11. package/src/input/keymap/keymap-ref.ts +11 -0
  12. package/src/input/keymap/sequence-resolver.ts +35 -2
  13. package/src/input/keymap/trie.ts +1 -0
  14. package/src/input/modes/bridge.ts +1 -1
  15. package/src/input/modes/handlers/shared.ts +0 -16
  16. package/src/input/modes/transitions.ts +4 -4
  17. package/src/input/modes/types.ts +1 -1
  18. package/src/platform/daemon-control.ts +0 -8
  19. package/src/pty/pty-manager.ts +127 -11
  20. package/src/restart-terminal-manager.ts +44 -0
  21. package/src/session-backend/local-session-backend.ts +15 -4
  22. package/src/session-backend/remote-session-backend.ts +13 -2
  23. package/src/session-backend/types.ts +13 -2
  24. package/src/state/reducers/git-panel-state.ts +35 -8
  25. package/src/state/reducers/modal-state.ts +48 -3
  26. package/src/state/selectors.ts +1 -5
  27. package/src/state/session-persistence.ts +1 -20
  28. package/src/state/store.ts +38 -5
  29. package/src/state/types.ts +27 -13
  30. package/src/state/validation.ts +0 -2
  31. package/src/state/workspace-save.ts +6 -2
  32. package/src/ui/components/create-session-modal.tsx +5 -3
  33. package/src/ui/components/git-commit-modal.tsx +1 -3
  34. package/src/ui/components/git-pane-widget.tsx +46 -0
  35. package/src/ui/components/git-panel.tsx +72 -25
  36. package/src/ui/components/help-modal.tsx +156 -42
  37. package/src/ui/components/modal-keybinds-overlay.tsx +39 -0
  38. package/src/ui/components/modal-shell.tsx +15 -3
  39. package/src/ui/components/new-tab-modal.tsx +9 -10
  40. package/src/ui/components/pending-chord-overlay.tsx +2 -1
  41. package/src/ui/components/session-name-modal.tsx +1 -3
  42. package/src/ui/components/session-picker-modal.tsx +1 -3
  43. package/src/ui/components/sidebar.tsx +24 -50
  44. package/src/ui/components/snippet-editor-modal.tsx +1 -3
  45. package/src/ui/components/snippet-picker-modal.tsx +1 -3
  46. package/src/ui/components/status-bar.tsx +0 -4
  47. package/src/ui/components/terminal-pane.tsx +17 -12
  48. package/src/ui/components/theme-picker-modal.tsx +6 -3
  49. package/src/ui/components/update-available-modal.tsx +7 -4
  50. package/src/ui/keymap-context.ts +1 -6
  51. package/src/ui/root.tsx +29 -1
  52. package/src/ui/status-bar-model.ts +0 -5
  53. package/src/ui/directory-search.ts +0 -1
package/src/config.ts CHANGED
@@ -9,18 +9,43 @@ import { THEME_IDS, type ThemeId } from './ui/themes'
9
9
 
10
10
  export const CONFIG_PATH = `${getProfileConfigDir()}/aimux.json`
11
11
 
12
+ export interface PersistedGitPane {
13
+ visible: boolean
14
+ mode: 'embedded' | 'pane'
15
+ position: 'top' | 'bottom' | 'left' | 'right'
16
+ ratio: number
17
+ }
18
+
12
19
  export interface AimuxConfig {
13
20
  version: 2
14
21
  customCommands: Record<string, string>
15
22
  themeId?: ThemeId
16
- gitPanelVisible?: boolean
17
- gitPanelRatio?: number
23
+ gitPane?: PersistedGitPane
18
24
  sessionBarVisible?: boolean
19
25
  sessionBarPosition?: SessionBarPosition
20
26
  workspaceSnapshot?: WorkspaceSnapshotV1
21
27
  skippedUpdateVersion?: string
22
28
  }
23
29
 
30
+ function isPersistedGitPane(value: unknown): value is PersistedGitPane {
31
+ if (typeof value !== 'object' || value === null) return false
32
+ const v = value as Record<string, unknown>
33
+ const modeOk = v.mode === 'embedded' || v.mode === 'pane'
34
+ const positionOk =
35
+ v.position === 'top' ||
36
+ v.position === 'bottom' ||
37
+ v.position === 'left' ||
38
+ v.position === 'right'
39
+ const ratioOk =
40
+ typeof v.ratio === 'number' && Number.isFinite(v.ratio) && v.ratio > 0 && v.ratio < 1
41
+ const visibleOk = typeof v.visible === 'boolean'
42
+ if (!modeOk || !positionOk || !ratioOk || !visibleOk) return false
43
+ // cross-field coherence: embedded => top|bottom; pane => left|right
44
+ if (v.mode === 'embedded' && v.position !== 'top' && v.position !== 'bottom') return false
45
+ if (v.mode === 'pane' && v.position !== 'left' && v.position !== 'right') return false
46
+ return true
47
+ }
48
+
24
49
  const DEFAULT_CONFIG: AimuxConfig = {
25
50
  customCommands: {},
26
51
  version: 2,
@@ -58,6 +83,7 @@ export function loadConfigResult(): ConfigLoadResult {
58
83
  version?: number
59
84
  customCommands?: unknown
60
85
  themeId?: unknown
86
+ gitPane?: unknown
61
87
  gitPanelVisible?: unknown
62
88
  gitPanelRatio?: unknown
63
89
  sessionBarVisible?: unknown
@@ -80,21 +106,32 @@ export function loadConfigResult(): ConfigLoadResult {
80
106
  issues.push('ignored invalid themeId')
81
107
  }
82
108
 
83
- const validGitPanelVisible =
84
- typeof parsed.gitPanelVisible === 'boolean' ? parsed.gitPanelVisible : undefined
85
- if (parsed.gitPanelVisible !== undefined && validGitPanelVisible === undefined) {
86
- issues.push('ignored invalid gitPanelVisible')
109
+ let validGitPane = isPersistedGitPane(parsed.gitPane) ? parsed.gitPane : undefined
110
+ if (parsed.gitPane !== undefined && validGitPane === undefined) {
111
+ issues.push('ignored invalid gitPane')
87
112
  }
88
113
 
89
- const validGitPanelRatio =
90
- typeof parsed.gitPanelRatio === 'number' &&
91
- Number.isFinite(parsed.gitPanelRatio) &&
92
- parsed.gitPanelRatio > 0 &&
93
- parsed.gitPanelRatio < 1
94
- ? parsed.gitPanelRatio
95
- : undefined
96
- if (parsed.gitPanelRatio !== undefined && validGitPanelRatio === undefined) {
97
- issues.push('ignored invalid gitPanelRatio')
114
+ // Legacy migration: previous schema stored gitPanelVisible/gitPanelRatio at
115
+ // top level. If the new `gitPane` field is absent, synthesize it from legacy
116
+ // keys so users don't lose their toggle/ratio on upgrade.
117
+ if (validGitPane === undefined) {
118
+ const legacyVisible =
119
+ typeof parsed.gitPanelVisible === 'boolean' ? parsed.gitPanelVisible : undefined
120
+ const legacyRatio =
121
+ typeof parsed.gitPanelRatio === 'number' &&
122
+ Number.isFinite(parsed.gitPanelRatio) &&
123
+ parsed.gitPanelRatio > 0 &&
124
+ parsed.gitPanelRatio < 1
125
+ ? parsed.gitPanelRatio
126
+ : undefined
127
+ if (legacyVisible !== undefined || legacyRatio !== undefined) {
128
+ validGitPane = {
129
+ mode: 'embedded',
130
+ position: 'bottom',
131
+ ratio: legacyRatio ?? 0.5,
132
+ visible: legacyVisible ?? true,
133
+ }
134
+ }
98
135
  }
99
136
 
100
137
  const validSessionBarVisible =
@@ -133,8 +170,7 @@ export function loadConfigResult(): ConfigLoadResult {
133
170
  return {
134
171
  config: {
135
172
  customCommands: isCustomCommandsRecord(parsed.customCommands) ? parsed.customCommands : {},
136
- gitPanelRatio: validGitPanelRatio,
137
- gitPanelVisible: validGitPanelVisible,
173
+ gitPane: validGitPane,
138
174
  sessionBarPosition: validSessionBarPosition,
139
175
  sessionBarVisible: validSessionBarVisible,
140
176
  skippedUpdateVersion: validSkippedUpdateVersion,
@@ -67,8 +67,14 @@ export class SessionManager extends EventEmitter<SessionManagerEvents> {
67
67
  this.getOrCreateRegistry(sessionId).write(tabId, data)
68
68
  }
69
69
 
70
- resize(sessionId: string, cols: number, rows: number, intents?: Map<string, ScrollIntent>): void {
71
- this.getOrCreateRegistry(sessionId).resizeAll(cols, rows, intents)
70
+ resize(
71
+ sessionId: string,
72
+ cols: number,
73
+ rows: number,
74
+ intents?: Map<string, ScrollIntent>,
75
+ options?: { sync?: boolean }
76
+ ): void {
77
+ this.getOrCreateRegistry(sessionId).resizeAll(cols, rows, intents, options)
72
78
  }
73
79
 
74
80
  resizeTab(
@@ -76,9 +82,10 @@ export class SessionManager extends EventEmitter<SessionManagerEvents> {
76
82
  tabId: string,
77
83
  cols: number,
78
84
  rows: number,
79
- intent?: ScrollIntent
85
+ intent?: ScrollIntent,
86
+ options?: { sync?: boolean }
80
87
  ): void {
81
- this.getOrCreateRegistry(sessionId).resizeTab(tabId, cols, rows, intent)
88
+ this.getOrCreateRegistry(sessionId).resizeTab(tabId, cols, rows, intent, options)
82
89
  }
83
90
 
84
91
  scroll(sessionId: string, tabId: string, deltaLines: number): void {
@@ -165,12 +165,23 @@ export class SessionRegistry extends EventEmitter<SessionRegistryEvents> {
165
165
  this.ptyManager.write(tabId, data)
166
166
  }
167
167
 
168
- resizeAll(cols: number, rows: number, intents?: Map<string, ScrollIntent>): void {
169
- this.ptyManager.resizeAll(cols, rows, intents)
168
+ resizeAll(
169
+ cols: number,
170
+ rows: number,
171
+ intents?: Map<string, ScrollIntent>,
172
+ options?: { sync?: boolean }
173
+ ): void {
174
+ this.ptyManager.resizeAll(cols, rows, intents, options)
170
175
  }
171
176
 
172
- resizeTab(tabId: string, cols: number, rows: number, intent?: ScrollIntent): void {
173
- this.ptyManager.resizeSession(tabId, cols, rows, intent)
177
+ resizeTab(
178
+ tabId: string,
179
+ cols: number,
180
+ rows: number,
181
+ intent?: ScrollIntent,
182
+ options?: { sync?: boolean }
183
+ ): void {
184
+ this.ptyManager.resizeSession(tabId, cols, rows, intent, options)
174
185
  }
175
186
 
176
187
  scrollViewport(tabId: string, deltaLines: number): void {
package/src/index.tsx CHANGED
@@ -9,6 +9,7 @@ import { getRuntimeProfile } from './daemon/runtime-paths'
9
9
  import { logDebug } from './debug/input-log'
10
10
  import { runDoctor } from './doctor'
11
11
  import { runRestartDaemon } from './restart-daemon'
12
+ import { runRestartTerminalManager } from './restart-terminal-manager'
12
13
  import { createSessionBackend } from './session-backend/bootstrap'
13
14
  import { runTerminalManager } from './terminal-manager/terminal-manager'
14
15
  import { runUpdate } from './update'
@@ -30,6 +31,10 @@ if (command === 'restart-daemon') {
30
31
  process.exit(await runRestartDaemon())
31
32
  }
32
33
 
34
+ if (command === 'restart-terminal-manager') {
35
+ process.exit(await runRestartTerminalManager())
36
+ }
37
+
33
38
  if (command === 'update') {
34
39
  process.exit(await runUpdate())
35
40
  }
@@ -46,7 +51,7 @@ if (command === 'terminal-manager') {
46
51
 
47
52
  if (command === '--help' || command === '-h') {
48
53
  process.stdout.write(
49
- 'aimux -- terminal multiplexer for AI CLIs\n\nUsage:\n aimux Start aimux\n aimux update Update to latest version\n aimux doctor Diagnose setup issues\n aimux restart-daemon Restart IPC daemon\n\n'
54
+ 'aimux -- terminal multiplexer for AI CLIs\n\nUsage:\n aimux Start aimux\n aimux update Update to latest version\n aimux doctor Diagnose setup issues\n aimux restart-daemon Restart IPC daemon\n aimux restart-terminal-manager Restart terminal-manager (kills live sessions)\n\n'
50
55
  )
51
56
  process.exit(0)
52
57
  }
@@ -18,6 +18,7 @@ export function buildKeymapHandlers(config: ResolvedKeymapConfig): KeymapModeHan
18
18
  const sequence = parseKeyNotation(binding.keys, leaderChord)
19
19
  trie.insert(sequence, {
20
20
  group: binding.group,
21
+ repeatable: binding.repeatable,
21
22
  result: binding.result,
22
23
  })
23
24
  }
@@ -0,0 +1,44 @@
1
+ import type { ModeId, ResolvedKeymapConfig } from '@brimveyn/aimux-config'
2
+
3
+ import { describeBindings, type DescribedBinding } from './describe-bindings'
4
+
5
+ export interface HelpEntry extends DescribedBinding {
6
+ mode: ModeId
7
+ modeLabel: string
8
+ }
9
+
10
+ export const HELP_MODE_LABELS: { modeId: ModeId; label: string }[] = [
11
+ { label: 'Navigation', modeId: 'navigation' },
12
+ { label: 'Terminal input', modeId: 'terminal-input' },
13
+ { label: 'Git mode', modeId: 'git-mode' },
14
+ { label: 'Git commit', modeId: 'modal.git-commit' },
15
+ { label: 'New tab', modeId: 'modal.new-tab' },
16
+ { label: 'New tab — command', modeId: 'modal.new-tab.command-edit' },
17
+ { label: 'Session picker', modeId: 'modal.session-picker' },
18
+ { label: 'Session picker — filter', modeId: 'modal.session-picker.filtering' },
19
+ { label: 'Session name', modeId: 'modal.session-name' },
20
+ { label: 'Create session', modeId: 'modal.create-session' },
21
+ { label: 'Rename tab', modeId: 'modal.rename-tab' },
22
+ { label: 'Snippet picker', modeId: 'modal.snippet-picker' },
23
+ { label: 'Snippet picker — filter', modeId: 'modal.snippet-picker.filtering' },
24
+ { label: 'Snippet editor', modeId: 'modal.snippet-editor' },
25
+ { label: 'Theme picker', modeId: 'modal.theme-picker' },
26
+ { label: 'Split picker', modeId: 'modal.split-picker' },
27
+ { label: 'Help', modeId: 'modal.help' },
28
+ { label: 'Help — filter', modeId: 'modal.help.filtering' },
29
+ { label: 'Update available', modeId: 'modal.update-available' },
30
+ ]
31
+
32
+ export function collectHelpEntries(config: ResolvedKeymapConfig): HelpEntry[] {
33
+ const entries: HelpEntry[] = []
34
+ for (const { label, modeId } of HELP_MODE_LABELS) {
35
+ const bindings = describeBindings(config, modeId, {
36
+ dedupeByDescription: true,
37
+ withDescriptionOnly: true,
38
+ })
39
+ for (const binding of bindings) {
40
+ entries.push({ ...binding, mode: modeId, modeLabel: label })
41
+ }
42
+ }
43
+ return entries
44
+ }
@@ -0,0 +1,11 @@
1
+ import type { ResolvedKeymapConfig } from '@brimveyn/aimux-config'
2
+
3
+ let activeKeymap: ResolvedKeymapConfig | null = null
4
+
5
+ export function setActiveKeymap(config: ResolvedKeymapConfig | null): void {
6
+ activeKeymap = config
7
+ }
8
+
9
+ export function getActiveKeymap(): ResolvedKeymapConfig | null {
10
+ return activeKeymap
11
+ }
@@ -17,6 +17,8 @@ export class SequenceResolver {
17
17
  private timeoutHandle: ReturnType<typeof setTimeout> | null = null
18
18
  private onTimeout: ((binding: TrieBinding) => void) | null = null
19
19
  private onPendingChange: ((chords: KeyChord[] | null) => void) | null = null
20
+ private repeatTerminal: KeyChord | null = null
21
+ private repeatBinding: TrieBinding | null = null
20
22
 
21
23
  constructor(
22
24
  private readonly trie: KeyTrie,
@@ -37,16 +39,29 @@ export class SequenceResolver {
37
39
  feed(chord: KeyChord): ResolveResult {
38
40
  this.clearTimeout()
39
41
 
42
+ // Repeat: when not mid-sequence and the chord matches the last repeatable
43
+ // sequence's terminal key, re-fire it.
44
+ if (
45
+ this.currentNode === null &&
46
+ this.repeatTerminal !== null &&
47
+ this.repeatBinding !== null &&
48
+ chord === this.repeatTerminal
49
+ ) {
50
+ return { binding: this.repeatBinding, type: 'resolved' }
51
+ }
52
+
40
53
  const fromNode = this.currentNode ?? this.trie.root
41
54
  const match = this.trie.lookup(chord, fromNode)
42
55
 
43
56
  switch (match.type) {
44
57
  case 'exact': {
45
58
  this.resetState()
59
+ this.updateRepeatOnResolve(chord, match.binding)
46
60
  return { binding: match.binding, type: 'resolved' }
47
61
  }
48
62
 
49
63
  case 'prefix': {
64
+ this.clearRepeat()
50
65
  this.currentNode = match.node
51
66
  this.pendingBinding = null
52
67
  this.pendingChords.push(chord)
@@ -55,11 +70,12 @@ export class SequenceResolver {
55
70
  }
56
71
 
57
72
  case 'exact+prefix': {
73
+ this.clearRepeat()
58
74
  this.currentNode = match.node
59
75
  this.pendingBinding = match.binding
60
76
  this.pendingChords.push(chord)
61
77
  this.emitPendingChange()
62
- this.startTimeout(match.binding)
78
+ this.startTimeout(chord, match.binding)
63
79
  return { type: 'pending' }
64
80
  }
65
81
 
@@ -69,6 +85,7 @@ export class SequenceResolver {
69
85
  this.resetState()
70
86
  return this.feed(chord)
71
87
  }
88
+ this.clearRepeat()
72
89
  return { type: 'passthrough' }
73
90
  }
74
91
  }
@@ -77,6 +94,7 @@ export class SequenceResolver {
77
94
  reset(): void {
78
95
  this.clearTimeout()
79
96
  this.resetState()
97
+ this.clearRepeat()
80
98
  }
81
99
 
82
100
  setTimeoutCallback(cb: (binding: TrieBinding) => void): void {
@@ -107,11 +125,26 @@ export class SequenceResolver {
107
125
  }
108
126
  }
109
127
 
110
- private startTimeout(binding: TrieBinding): void {
128
+ private startTimeout(chord: KeyChord, binding: TrieBinding): void {
111
129
  this.timeoutHandle = setTimeout(() => {
112
130
  this.timeoutHandle = null
113
131
  this.resetState()
132
+ this.updateRepeatOnResolve(chord, binding)
114
133
  this.onTimeout?.(binding)
115
134
  }, this.config.timeoutMs)
116
135
  }
136
+
137
+ private updateRepeatOnResolve(chord: KeyChord, binding: TrieBinding): void {
138
+ if (binding.repeatable) {
139
+ this.repeatTerminal = chord
140
+ this.repeatBinding = binding
141
+ } else {
142
+ this.clearRepeat()
143
+ }
144
+ }
145
+
146
+ private clearRepeat(): void {
147
+ this.repeatTerminal = null
148
+ this.repeatBinding = null
149
+ }
117
150
  }
@@ -6,6 +6,7 @@ export type ActionFn = (ctx: ModeContext) => KeyResult | null
6
6
  export interface TrieBinding {
7
7
  result: KeyResult | ActionFn
8
8
  group?: string
9
+ repeatable?: boolean
9
10
  }
10
11
 
11
12
  export interface TrieNode {
@@ -5,7 +5,6 @@ type SupportedModalType = Exclude<ModalType, null>
5
5
 
6
6
  const DIRECT_FOCUS_MODE_IDS: Partial<Record<FocusMode, ModeId>> = {
7
7
  'git': 'git-mode',
8
- 'layout': 'layout',
9
8
  'navigation': 'navigation',
10
9
  'terminal-input': 'terminal-input',
11
10
  }
@@ -13,6 +12,7 @@ const DIRECT_FOCUS_MODE_IDS: Partial<Record<FocusMode, ModeId>> = {
13
12
  const COMMAND_EDIT_MODE_IDS: Partial<Record<SupportedModalType, ModeId>> = {
14
13
  'create-session': 'modal.create-session',
15
14
  'git-commit': 'modal.git-commit',
15
+ 'help': 'modal.help.filtering',
16
16
  'new-tab': 'modal.new-tab.command-edit',
17
17
  'rename-tab': 'modal.rename-tab',
18
18
  'session-name': 'modal.session-name',
@@ -68,19 +68,3 @@ export function handleCtrlNavigation(key: KeyInput): KeyResult | null {
68
68
 
69
69
  return null
70
70
  }
71
-
72
- export function handleCursorNavigation(key: KeyInput): KeyResult | null {
73
- if (key.name === 'left' && !key.ctrl && !key.meta) {
74
- return result([{ delta: -1, type: 'move-modal-cursor' }])
75
- }
76
- if (key.name === 'right' && !key.ctrl && !key.meta) {
77
- return result([{ delta: 1, type: 'move-modal-cursor' }])
78
- }
79
- if (key.name === 'home' || (key.ctrl && key.name === 'a')) {
80
- return result([{ to: 'home', type: 'move-modal-cursor' }])
81
- }
82
- if (key.name === 'end' || (key.ctrl && key.name === 'e')) {
83
- return result([{ to: 'end', type: 'move-modal-cursor' }])
84
- }
85
- return null
86
- }
@@ -2,10 +2,10 @@ import type { ModeId } from './types'
2
2
 
3
3
  const TRANSITIONS: Record<ModeId, readonly ModeId[]> = {
4
4
  'git-mode': ['navigation', 'modal.git-commit'],
5
- 'layout': ['terminal-input', 'navigation', 'modal.split-picker'],
6
5
  'modal.create-session': ['navigation', 'modal.session-picker'],
7
6
  'modal.git-commit': ['git-mode'],
8
- 'modal.help': ['navigation'],
7
+ 'modal.help': ['navigation', 'modal.help.filtering'],
8
+ 'modal.help.filtering': ['modal.help'],
9
9
  'modal.new-tab': ['navigation', 'modal.new-tab.command-edit'],
10
10
  'modal.new-tab.command-edit': ['modal.new-tab'],
11
11
  'modal.rename-tab': ['navigation'],
@@ -20,7 +20,7 @@ const TRANSITIONS: Record<ModeId, readonly ModeId[]> = {
20
20
  'modal.snippet-editor': ['navigation', 'modal.snippet-picker'],
21
21
  'modal.snippet-picker': ['navigation', 'modal.snippet-picker.filtering', 'modal.snippet-editor'],
22
22
  'modal.snippet-picker.filtering': ['modal.snippet-picker'],
23
- 'modal.split-picker': ['navigation'],
23
+ 'modal.split-picker': ['navigation', 'terminal-input'],
24
24
  'modal.theme-picker': ['navigation'],
25
25
  'modal.update-available': ['navigation'],
26
26
  'navigation': [
@@ -34,7 +34,7 @@ const TRANSITIONS: Record<ModeId, readonly ModeId[]> = {
34
34
  'modal.update-available',
35
35
  'git-mode',
36
36
  ],
37
- 'terminal-input': ['navigation', 'layout'],
37
+ 'terminal-input': ['navigation', 'modal.split-picker'],
38
38
  }
39
39
 
40
40
  export function isValidTransition(from: ModeId, to: ModeId): boolean {
@@ -5,7 +5,6 @@ import type { AppAction, AppState, TabSession } from '../../state/types'
5
5
  export type ModeId =
6
6
  | 'navigation'
7
7
  | 'terminal-input'
8
- | 'layout'
9
8
  | 'git-mode'
10
9
  | 'modal.new-tab'
11
10
  | 'modal.new-tab.command-edit'
@@ -19,6 +18,7 @@ export type ModeId =
19
18
  | 'modal.snippet-editor'
20
19
  | 'modal.theme-picker'
21
20
  | 'modal.help'
21
+ | 'modal.help.filtering'
22
22
  | 'modal.split-picker'
23
23
  | 'modal.git-commit'
24
24
  | 'modal.update-available'
@@ -21,10 +21,6 @@ export async function findSocketProcessPid(socketPath: string): Promise<number |
21
21
  }
22
22
  }
23
23
 
24
- export async function findDaemonPid(socketPath: string): Promise<number | null> {
25
- return findSocketProcessPid(socketPath)
26
- }
27
-
28
24
  export async function findIpcDaemonPid(): Promise<number | null> {
29
25
  return findSocketProcessPid(getIpcDaemonSocketPath())
30
26
  }
@@ -53,10 +49,6 @@ export async function killProcess(pid: number): Promise<void> {
53
49
  }
54
50
  }
55
51
 
56
- export async function killDaemon(pid: number): Promise<void> {
57
- await killProcess(pid)
58
- }
59
-
60
52
  async function waitForSocket(socketPath: string): Promise<boolean> {
61
53
  const deadline = Date.now() + 2_000
62
54
  while (Date.now() < deadline) {