@brimveyn/aimux-config 0.11.2 → 0.11.4

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.11.2",
3
+ "version": "0.11.4",
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
@@ -187,6 +187,11 @@ export function focusPane(direction: 'left' | 'right' | 'up' | 'down'): KeyResul
187
187
  )
188
188
  }
189
189
 
190
+ /** Exchanges the active pane with its neighbour; the keyboard goes with it. */
191
+ export function swapPane(direction: 'left' | 'right' | 'up' | 'down'): KeyResult {
192
+ return r([{ direction, type: 'swap-pane' }])
193
+ }
194
+
190
195
  export function resizePane(delta: number, axis: 'horizontal' | 'vertical'): ActionFn {
191
196
  return (ctx: ModeContext) => {
192
197
  const tabId = ctx.state.activeTabId
package/src/app-types.ts CHANGED
@@ -100,6 +100,7 @@ export type ModalType =
100
100
  | 'workspace-delete-confirm'
101
101
  | 'flash-jump'
102
102
  | 'setting-text'
103
+ | 'setting-keybind'
103
104
  | 'settings-search'
104
105
  /**
105
106
  * Every plugin modal, the way `plugin-view` covers every plugin view. Which
@@ -315,6 +316,13 @@ export interface TabSession {
315
316
  * to `TabSessionSummary` if that ever matters.
316
317
  */
317
318
  role?: 'setup'
319
+ /**
320
+ * The qualified id of the plugin command pane this tab is (`<pluginId>.<paneId>`),
321
+ * when a plugin's `panes[]` or `registerCommand` spawned it. Session-scoped
322
+ * like every plugin pane: never persisted, never on the wire, so it comes
323
+ * back from a restart as a plain terminal tab running the same argv.
324
+ */
325
+ pluginPane?: string
318
326
  }
319
327
 
320
328
  export type BarSide = 'left' | 'right'
@@ -527,6 +535,15 @@ export interface ModalSettingText extends ModalBase {
527
535
  settingId: string
528
536
  settingLabel: string
529
537
  }
538
+ export interface ModalSettingKeybind extends ModalBase {
539
+ type: 'setting-keybind'
540
+ settingId: string
541
+ settingLabel: string
542
+ mode: string
543
+ captured: string[]
544
+ conflict: string | null
545
+ returnTo: 'settings'
546
+ }
530
547
 
531
548
  export interface ModalRenameWorkspace extends ModalBase {
532
549
  type: 'rename-workspace'
@@ -738,6 +755,7 @@ export type ModalState =
738
755
  | ModalWorkspaceDeleteConfirm
739
756
  | ModalFlashJump
740
757
  | ModalSettingText
758
+ | ModalSettingKeybind
741
759
  | ModalSettingsSearch
742
760
  | ModalPlugin
743
761
 
@@ -934,6 +952,7 @@ export type BuiltinModeId =
934
952
  | 'modal.rename-tab'
935
953
  | 'modal.rename-workspace'
936
954
  | 'modal.setting-text'
955
+ | 'modal.setting-keybind'
937
956
  | 'modal.settings-search.filtering'
938
957
  | 'modal.snippet-picker.filtering'
939
958
  | 'modal.snippet-editor'
@@ -1064,6 +1083,7 @@ export type SideEffect =
1064
1083
  | { type: 'reset-settings-row' }
1065
1084
  | { type: 'confirm-settings-search' }
1066
1085
  | { type: 'commit-setting-text'; settingId: string; value: string }
1086
+ | { type: 'commit-setting-keybind'; settingId: string; value: string }
1067
1087
  | PluginSideEffect
1068
1088
 
1069
1089
  export interface KeyResult {
@@ -1255,6 +1275,11 @@ export type LayoutAction =
1255
1275
  type: 'focus-pane-direction'
1256
1276
  direction: 'left' | 'right' | 'up' | 'down'
1257
1277
  }
1278
+ /** Exchanges the pane holding the keyboard with its neighbour. Focus follows it. */
1279
+ | {
1280
+ type: 'swap-pane'
1281
+ direction: 'left' | 'right' | 'up' | 'down'
1282
+ }
1258
1283
  | {
1259
1284
  type: 'resize-pane'
1260
1285
  tabId: string
@@ -1313,6 +1338,9 @@ export type SettingsAction =
1313
1338
  | { type: 'settings-select-row'; rowIndex: number }
1314
1339
  | { type: 'open-settings-search' }
1315
1340
  | { type: 'open-setting-text-modal'; settingId: string; label: string; value: string }
1341
+ | { type: 'open-setting-keybind-modal'; settingId: string; label: string; mode: string }
1342
+ | { type: 'keybind-capture-push'; chord: string }
1343
+ | { type: 'keybind-capture-pop' }
1316
1344
 
1317
1345
  export type StatsAction =
1318
1346
  | { type: 'enter-stats' }
package/src/index.ts CHANGED
@@ -35,7 +35,9 @@ export { isAutoCommitEnabled, setAutoCommitEnabled } from './auto-commit-runtime
35
35
  export {
36
36
  clearPluginActions,
37
37
  hasPluginAction,
38
+ listPluginActions,
38
39
  pluginAction,
40
+ type PluginActionInfo,
39
41
  pluginActionNames,
40
42
  registerPluginAction,
41
43
  } from './plugin-actions-runtime'
@@ -15,25 +15,52 @@ import type { ActionFn, KeyResult, ModeContext } from './types'
15
15
  * action factories a config file calls already are.
16
16
  */
17
17
 
18
+ /** What a palette shows for an action. */
19
+ export interface PluginActionInfo {
20
+ /** Qualified `<pluginId>.<verb>`. */
21
+ name: string
22
+ title?: string
23
+ description?: string
24
+ }
25
+
18
26
  /** Qualified `<pluginId>.<verb>` — the id a keymap writes. */
19
27
  const handlers = new Map<string, ActionFn>()
28
+ const meta = new Map<string, Omit<PluginActionInfo, 'name'>>()
20
29
 
21
- export function registerPluginAction(name: string, handler: ActionFn): () => void {
30
+ export function registerPluginAction(
31
+ name: string,
32
+ handler: ActionFn,
33
+ info: Omit<PluginActionInfo, 'name'> = {}
34
+ ): () => void {
22
35
  handlers.set(name, handler)
36
+ meta.set(name, info)
23
37
  return () => {
24
- if (handlers.get(name) === handler) handlers.delete(name)
38
+ if (handlers.get(name) !== handler) return
39
+ handlers.delete(name)
40
+ meta.delete(name)
25
41
  }
26
42
  }
27
43
 
28
44
  /** Test seam. Never called by the app. */
29
45
  export function clearPluginActions(): void {
30
46
  handlers.clear()
47
+ meta.clear()
31
48
  }
32
49
 
33
50
  export function pluginActionNames(): string[] {
34
51
  return [...handlers.keys()]
35
52
  }
36
53
 
54
+ /**
55
+ * Every registered action with whatever it said about itself. The list a
56
+ * palette is built from: an action without a title is still listed, under
57
+ * its verb, because hiding it would make "why is my action not in the
58
+ * palette" a question with no answer.
59
+ */
60
+ export function listPluginActions(): PluginActionInfo[] {
61
+ return [...handlers.keys()].map((name) => ({ name, ...meta.get(name) }))
62
+ }
63
+
37
64
  export function hasPluginAction(name: string): boolean {
38
65
  return handlers.has(name)
39
66
  }
@@ -34,6 +34,7 @@ type SettingKind =
34
34
  | { kind: 'number'; min: number; max: number; step: number }
35
35
  /** Activating it opens a one-field modal. Empty means "unset", not "empty string". */
36
36
  | { kind: 'text'; placeholder?: string }
37
+ | { kind: 'keybind' }
37
38
 
38
39
  interface SettingRowBase {
39
40
  id: string
package/src/types.ts CHANGED
@@ -118,6 +118,8 @@ export interface PluginConfigEntry {
118
118
  enabled?: boolean
119
119
  /** Merged over the manifest defaults and the registry, and wins over both. */
120
120
  config?: Record<string, unknown>
121
+ /** Per-binding overrides keyed by the manifest binding id. `null` unbinds it. */
122
+ keymaps?: Record<string, string | null>
121
123
  }
122
124
 
123
125
  /** A bare string is shorthand for `{ path }`. */
@@ -340,6 +342,12 @@ export interface AimuxThemeConfig {
340
342
  export type AIUsageTool = 'claude' | 'codex' | (string & {})
341
343
 
342
344
  export interface AIUsageToolConfig {
345
+ /**
346
+ * Whether the indicator runs. The same switch as
347
+ * `plugins: [{ id: 'aimux.ai-usage', enabled }]`, kept because it is the key
348
+ * the feature had before it was a plugin. Off by default: the service reads
349
+ * the Claude keychain entry and calls two OAuth endpoints.
350
+ */
343
351
  enabled?: boolean
344
352
  pollSeconds?: number
345
353
  claudePlan?: 'auto' | 'pro' | 'max5' | 'max20'