@aiwayds/dsh-tui-pi 0.1.0 → 0.3.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 (67) hide show
  1. package/README.md +205 -68
  2. package/lib/agent-manager.d.ts +125 -0
  3. package/lib/agent-manager.js +298 -0
  4. package/lib/agent-manager.js.map +1 -0
  5. package/lib/agents.d.ts +30 -0
  6. package/lib/agents.js +468 -0
  7. package/lib/agents.js.map +1 -0
  8. package/lib/append-system.d.ts +2 -0
  9. package/lib/append-system.js +1 -1
  10. package/lib/append-system.js.map +1 -1
  11. package/lib/dsh-events.d.ts +12 -0
  12. package/lib/editor.d.ts +58 -0
  13. package/lib/editor.js +92 -0
  14. package/lib/editor.js.map +1 -1
  15. package/lib/footer.d.ts +8 -0
  16. package/lib/footer.js +8 -0
  17. package/lib/footer.js.map +1 -1
  18. package/lib/hotkeys.d.ts +93 -0
  19. package/lib/hotkeys.js +305 -0
  20. package/lib/hotkeys.js.map +1 -0
  21. package/lib/index.js +342 -38
  22. package/lib/index.js.map +1 -1
  23. package/lib/keymap.d.ts +177 -0
  24. package/lib/keymap.js +189 -0
  25. package/lib/keymap.js.map +1 -0
  26. package/lib/live-widgets.d.ts +82 -29
  27. package/lib/live-widgets.js +222 -92
  28. package/lib/live-widgets.js.map +1 -1
  29. package/lib/messages.d.ts +4 -2
  30. package/lib/messages.js +8 -3
  31. package/lib/messages.js.map +1 -1
  32. package/lib/panels.d.ts +177 -0
  33. package/lib/panels.js +331 -0
  34. package/lib/panels.js.map +1 -0
  35. package/lib/provider-catalog.d.ts +31 -8
  36. package/lib/provider-catalog.js +63 -8
  37. package/lib/provider-catalog.js.map +1 -1
  38. package/lib/selectors.d.ts +12 -1
  39. package/lib/selectors.js +5 -2
  40. package/lib/selectors.js.map +1 -1
  41. package/lib/session.d.ts +36 -0
  42. package/lib/session.js +171 -10
  43. package/lib/session.js.map +1 -1
  44. package/lib/settings.d.ts +1 -2
  45. package/lib/settings.js +29 -2
  46. package/lib/settings.js.map +1 -1
  47. package/lib/subagent-policy.d.ts +58 -0
  48. package/lib/subagent-policy.js +137 -0
  49. package/lib/subagent-policy.js.map +1 -0
  50. package/lib/subagent-viewer.d.ts +49 -0
  51. package/lib/subagent-viewer.js +523 -0
  52. package/lib/subagent-viewer.js.map +1 -0
  53. package/lib/theme/index.js +4 -0
  54. package/lib/theme/index.js.map +1 -1
  55. package/lib/theme/palette.d.ts +21 -3
  56. package/lib/theme/palette.js +27 -6
  57. package/lib/theme/palette.js.map +1 -1
  58. package/lib/theme-settings.d.ts +39 -4
  59. package/lib/theme-settings.js +69 -12
  60. package/lib/theme-settings.js.map +1 -1
  61. package/lib/tui.d.ts +32 -12
  62. package/lib/tui.js +109 -36
  63. package/lib/tui.js.map +1 -1
  64. package/package.json +3 -4
  65. package/patches/@earendil-works__pi-tui.patch +206 -2
  66. package/scripts/dev-install.mjs +87 -0
  67. package/scripts/link-dsh-closure.mjs +85 -0
package/lib/editor.js CHANGED
@@ -14,6 +14,8 @@ export function formatCwd(cwd) {
14
14
  }
15
15
  return cwd;
16
16
  }
17
+ /** History cap for the submitted-message browse (shell-style Up/Down recall). */
18
+ export const HISTORY_LIMIT = 500;
17
19
  export class CwdBorderEditor extends Editor {
18
20
  sessionCwd;
19
21
  infoColor;
@@ -37,6 +39,96 @@ export class CwdBorderEditor extends Editor {
37
39
  setPermissionProvider(provider) {
38
40
  this.permissionProvider = provider;
39
41
  }
42
+ /**
43
+ * Record a submitted message for Up/Down browsing. Same semantics as the
44
+ * pi-tui base `addToHistory` (trim, skip empty, skip consecutive duplicates,
45
+ * index 0 = most recent) but caps the list at `HISTORY_LIMIT` instead of the
46
+ * base's 100 — the chat editor wants a 500-entry recall, dropping the oldest.
47
+ * Note: the base (0.84.2) declares `history` private in its .d.ts but keeps
48
+ * it as a plain runtime field; we reach it via a type cast. The `override`
49
+ * keyword is fine under this tsconfig.
50
+ */
51
+ addToHistory(text) {
52
+ const trimmed = text.trim();
53
+ if (trimmed === '')
54
+ return;
55
+ const history = this.history;
56
+ // A bad pi-tui bump must degrade, not throw on every Enter: if the base
57
+ // ever stops exposing `history` as a plain array, fall back to the base
58
+ // implementation (its own 100-cap path) and return.
59
+ if (!Array.isArray(history)) {
60
+ super.addToHistory(text);
61
+ return;
62
+ }
63
+ // Don't add consecutive duplicates.
64
+ if (history.length > 0 && history[0] === trimmed)
65
+ return;
66
+ history.unshift(trimmed);
67
+ // Drop the oldest beyond the cap (base caps at 100).
68
+ if (history.length > HISTORY_LIMIT)
69
+ history.length = HISTORY_LIMIT;
70
+ }
71
+ /**
72
+ * Snapshot of the browse history, newest first (index 0). Returns a copy so
73
+ * callers can reseed another instance (theme-swap rebuild) without mutating
74
+ * this editor's internal list. Returns `[]` when the base no longer exposes
75
+ * the runtime list (a bad pi-tui bump) rather than throwing.
76
+ */
77
+ getHistory() {
78
+ const history = this.history;
79
+ if (!Array.isArray(history))
80
+ return [];
81
+ return [...history];
82
+ }
83
+ /**
84
+ * Reseed this editor's browse history from `entries` (newest first, index 0
85
+ * = most recent, matching the base's addToHistory ordering). Adds oldest →
86
+ * newest so the list lands in the same order on a fresh instance. Pinned to
87
+ * HISTORY_LIMIT like any other add.
88
+ */
89
+ reseedHistory(entries) {
90
+ for (let i = entries.length - 1; i >= 0; i--) {
91
+ this.addToHistory(entries[i]);
92
+ }
93
+ }
94
+ /**
95
+ * Snapshot the base's mid-browse state for a rebuild restore. `draft` is
96
+ * `null` when not browsing (historyIndex -1) — `structuredClone`d so the
97
+ * caller can reseed another instance without aliasing this editor's object.
98
+ * Treats a missing/invalid base field as not browsing (a bad pi-tui bump
99
+ * must degrade, not throw).
100
+ */
101
+ getBrowseState() {
102
+ const base = this;
103
+ const index = typeof base.historyIndex === 'number' ? base.historyIndex : -1;
104
+ const rawDraft = base.historyDraft;
105
+ const draft = rawDraft !== null && rawDraft !== undefined && Array.isArray(rawDraft.lines)
106
+ ? {
107
+ lines: structuredClone(rawDraft.lines),
108
+ cursorLine: rawDraft.cursorLine ?? 0,
109
+ cursorCol: rawDraft.cursorCol ?? 0,
110
+ }
111
+ : null;
112
+ return { index, draft };
113
+ }
114
+ /**
115
+ * Restore a previously-captured browse state (see getBrowseState) onto a
116
+ * fresh editor after a rebuild. `index` is clamped to the reseeded list so a
117
+ * stale snapshot can never read out of bounds; a snapshot whose history was
118
+ * truncated to nothing degrades to not browsing. `draft` is `null` → null,
119
+ * else `structuredClone`d. Skips writes entirely when the base no longer
120
+ * exposes the runtime fields (a bad pi-tui bump degrades silently).
121
+ */
122
+ restoreBrowseState(state) {
123
+ const base = this;
124
+ if (!Array.isArray(base.history))
125
+ return;
126
+ const maxIndex = base.history.length - 1;
127
+ const index = maxIndex < 0 ? -1 : Math.max(-1, Math.min(state.index, maxIndex));
128
+ base.historyIndex = index;
129
+ base.historyDraft =
130
+ state.draft === null ? null : structuredClone(state.draft);
131
+ }
40
132
  render(width) {
41
133
  const lines = super.render(width);
42
134
  if (lines.length < 2 || width < 3)
package/lib/editor.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"editor.js","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"editor.js","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"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"}
package/lib/footer.d.ts CHANGED
@@ -13,6 +13,14 @@
13
13
  */
14
14
  import { type Component } from '@earendil-works/pi-tui';
15
15
  import type { BridgeStats } from './session.ts';
16
+ /**
17
+ * The footer keybinding hint — plain text (no ANSI), exactly 103 visible
18
+ * columns. This is the pre-feature README-documented width; the ANSI wrapping
19
+ * lives in `paintFooterHint` (index.ts). The unit test in test/history.test.mjs
20
+ * guards it against future length regressions (a longer hint word-wraps on
21
+ * 105–118-column terminals and hides its suffix on ≤104).
22
+ */
23
+ export declare const FOOTER_HINT = "\u2328 Enter: send \u00B7 Esc \u00D72: stop \u00B7 Ctrl+C \u00D72: quit \u00B7 Ctrl+D: quit (empty) \u00B7 Ctrl+G: subagents \u00B7 \u2191\u2193: history";
16
24
  export interface FooterDataSource {
17
25
  /** O(1) incremental counters. */
18
26
  getStats(): BridgeStats;
package/lib/footer.js CHANGED
@@ -14,6 +14,14 @@
14
14
  import { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';
15
15
  import { ansiBg, ansiFg, BOLD, POWERLINE, RESET } from "./theme/index.js";
16
16
  import { clipToWidth } from "./text.js";
17
+ /**
18
+ * The footer keybinding hint — plain text (no ANSI), exactly 103 visible
19
+ * columns. This is the pre-feature README-documented width; the ANSI wrapping
20
+ * lives in `paintFooterHint` (index.ts). The unit test in test/history.test.mjs
21
+ * guards it against future length regressions (a longer hint word-wraps on
22
+ * 105–118-column terminals and hides its suffix on ≤104).
23
+ */
24
+ export const FOOTER_HINT = '⌨ Enter: send · Esc ×2: stop · Ctrl+C ×2: quit · Ctrl+D: quit (empty) · Ctrl+G: subagents · ↑↓: history';
17
25
  const ARROW_RIGHT = '\uE0B0';
18
26
  const WHITE = ansiFg('#FFFFFF');
19
27
  export function fmtNum(n) {
package/lib/footer.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"footer.js","sourceRoot":"","sources":["../src/footer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"footer.js","sourceRoot":"","sources":["../src/footer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,eAAe,EAAE,YAAY,EAAkB,MAAM,wBAAwB,CAAA;AAEtF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAEvC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB,yGAAyG,CAAA;AAE3G,MAAM,WAAW,GAAG,QAAQ,CAAA;AAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;AAkB/B,MAAM,UAAU,MAAM,CAAC,CAAS;IAC9B,IAAI,CAAC,IAAI,SAAS;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAA;IAC3D,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAA;IACjD,OAAO,GAAG,CAAC,EAAE,CAAA;AACf,CAAC;AAED,SAAS,aAAa,CAAC,IAAwB;IAC7C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAChC,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAA;QAClB,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,KAAK,GAAG,CAAA;QACtD,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACxB,GAAG,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,WAAW,EAAE,CAAA;QACxE,CAAC;aAAM,CAAC;YACN,GAAG,IAAI,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,WAAW,GAAG,KAAK,CAAA;QACtD,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,yEAAyE;AACzE,SAAS,UAAU,CAAC,KAAyB;IAC3C,MAAM,GAAG,GAAG,CAAC,KAAK,IAAI,KAAK,CAAoC,CAAA;IAC/D,OAAO,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAA;AAC1D,CAAC;AAED,SAAS,YAAY,CAAC,KAAyB;IAC7C,QAAQ,KAAK,IAAI,KAAK,EAAE,CAAC;QACvB,KAAK,SAAS,CAAC,CAAC,OAAO,GAAG,CAAA;QAC1B,KAAK,KAAK,CAAC,CAAC,OAAO,GAAG,CAAA;QACtB,KAAK,QAAQ,CAAC,CAAC,OAAO,GAAG,CAAA;QACzB,KAAK,MAAM,CAAC,CAAC,OAAO,GAAG,CAAA;QACvB,KAAK,OAAO,CAAC,CAAC,OAAO,GAAG,CAAA;QACxB,KAAK,KAAK,CAAC,CAAC,OAAO,GAAG,CAAA;QACtB,OAAO,CAAC,CAAC,OAAO,GAAG,CAAA;IACrB,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,OAAe;IAChC,IAAI,OAAO,IAAI,EAAE;QAAE,OAAO,SAAS,CAAC,aAAa,CAAA;IACjD,IAAI,OAAO,IAAI,EAAE;QAAE,OAAO,SAAS,CAAC,aAAa,CAAA;IACjD,IAAI,OAAO,IAAI,EAAE;QAAE,OAAO,SAAS,CAAC,WAAW,CAAA;IAC/C,OAAO,SAAS,CAAC,SAAS,CAAA;AAC5B,CAAC;AAED,MAAM,OAAO,eAAe;IACT,MAAM,CAAkB;IAEzC,YAAY,MAAwB;QAClC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;IAED,UAAU,KAA2C,CAAC;IAEtD,MAAM,CAAC,KAAa;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAA;QACpC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAA;QAE5C,MAAM,IAAI,GAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAA;QAClE,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAA;YAC3E,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAG,EAAE,EAAE,CAAC,CAAA;YAChE,MAAM,MAAM,GAAG,SAAS,CAAC,eAAe,IAAI,KAAK,CAAA;YACjD,IAAI,CAAC,IAAI,CAAC;gBACR,KAAK,EAAE,MAAM,KAAK,IAAI,YAAY,CAAC,MAAM,CAAC,IAAI,MAAM,EAAE;gBACtD,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC;aAC1B,CAAC,CAAA;QACJ,CAAC;QAED,uEAAuE;QACvE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAA;QAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAAA;QAC9B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,GAAG,GAAG,CAAA;YACrC,IAAI,CAAC,IAAI,CAAC;gBACR,KAAK,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;gBACrE,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC;aAC1B,CAAC,CAAA;QACJ,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC,CAAA;QACxE,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,CAAC,IAAI,KAAK,CAAC,gBAAgB,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YAClG,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAA;QACvF,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC,QAAQ,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC5E,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC,aAAa,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAA;QAE/E,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;QAChC,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;QAEpC,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,kBAAkB,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;QACvE,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,UAAU,CAAC,CAAA;QAEvD,OAAO,CAAC,eAAe,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;IACjE,CAAC;CACF"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * `/hotkeys` — view and customize the app-level keybindings, in the /agents
3
+ * select-panel style (src/panels.ts).
4
+ *
5
+ * pi's convention is a `/hotkeys` command plus a user-editable
6
+ * `~/.pi/agent/keybindings.json`. dsh side: `$DSH_HOME/keybindings.json`
7
+ * (default `~/.dsh/keybindings.json`). The file is a PARTIAL map of the four
8
+ * app keys ({@link APP_KEY_FIELDS}) to pi-tui key ids; anything missing falls
9
+ * back to the defaults (`src/keymap.ts`).
10
+ *
11
+ * UI (mirrors `/agents`): a FieldPanel lists the app keys — binding, custom
12
+ * star, action, file path + warnings; Enter opens an EditField to type a new
13
+ * key id (empty input resets the key to its default). A commit writes the
14
+ * file AND live-applies the new bindings to the running TUI (no /reload
15
+ * needed). Invalid entries never block: they warn and keep the default.
16
+ *
17
+ * The decision logic stays in `keymap.ts` (pure); this module owns the file
18
+ * contract, the validation, the display table and the interactive flow.
19
+ */
20
+ import type { KeyId, TUI } from '@earendil-works/pi-tui';
21
+ import { type KeyBindings } from './keymap.ts';
22
+ import { type ParseOutcome } from './settings.ts';
23
+ import { type TuiTheme } from './theme/index.ts';
24
+ /** The user-editable keybindings file name inside the dsh home. */
25
+ export declare const KEYBINDINGS_FILE = "keybindings.json";
26
+ /** Absolute path of the keybindings file under a dsh home directory. */
27
+ export declare function keybindingsPath(home: string): string;
28
+ /** The five app-level bindings the file may remap (order = display order). */
29
+ export declare const APP_KEY_FIELDS: readonly (keyof KeyBindings)[];
30
+ /**
31
+ * Conservative check of one pi-tui key id as a user might type it:
32
+ * `modifier+key` where every modifier is ctrl/shift/alt/super and the key is
33
+ * a named key (`escape`, `pageUp`, `f5`, …) or a single printable character.
34
+ * pi-tui's own `parseKeyId` is lenient (unknown ids just never match), so we
35
+ * reject obvious typos up front and let a warning surface them.
36
+ */
37
+ export declare function isValidKeyId(value: unknown): value is KeyId;
38
+ /** Human display of a key id: `escape`→`Esc`, `ctrl+shift+p`→`Ctrl+Shift+P`. */
39
+ export declare function displayKey(id: KeyId): string;
40
+ /** Result of reading the user keybindings file. */
41
+ export interface LoadedKeyBindings {
42
+ /** Valid entries only; may be empty when the file is absent or broken. */
43
+ bindings: Partial<KeyBindings>;
44
+ /** Human-readable problems (invalid entries, bad JSON) — shown as notices. */
45
+ warnings: string[];
46
+ /** Whether the file existed and parsed (a JSON object). */
47
+ exists: boolean;
48
+ }
49
+ /** Read + validate `$DSH_HOME/keybindings.json`. Never throws. */
50
+ export declare function loadKeyBindings(path: string): LoadedKeyBindings;
51
+ /**
52
+ * Merge-write the keybindings file: each `[field, value]` sets a binding,
53
+ * `null` removes it (reset to default). Unknown fields already in the file
54
+ * are preserved (the user's other keys survive). Missing file → fresh object;
55
+ * an unreadable/broken EXISTING file is an error — never clobbered silently.
56
+ * Returns an error message, or `undefined` on success.
57
+ */
58
+ export declare function updateKeyBindingsFile(path: string, updates: ReadonlyArray<readonly [keyof KeyBindings, KeyId | null]>): string | undefined;
59
+ /** The `/hotkeys` EditField parse: empty = reset, else a validated key id. */
60
+ export declare function parseKeyInput(text: string): ParseOutcome;
61
+ /** One row of the `/hotkeys` table. */
62
+ export interface HotkeyRow {
63
+ /** The app-key field this row edits. */
64
+ field: keyof KeyBindings;
65
+ /** Display key text (custom override reflected). */
66
+ key: string;
67
+ /** What the key does. */
68
+ action: string;
69
+ /** True when the key comes from the user's keybindings file. */
70
+ custom: boolean;
71
+ }
72
+ /**
73
+ * Build the app-key rows from the effective bindings — defaults, with any
74
+ * file override replacing the key display and flagging the row as custom.
75
+ * Pure, so the table content is unit-testable without a terminal.
76
+ */
77
+ export declare function appHotkeyRows(custom: Partial<KeyBindings>): HotkeyRow[];
78
+ /** Options for the `/hotkeys` interactive flow. */
79
+ export interface HotkeysManagerOptions {
80
+ /** Absolute path of the user keybindings file. */
81
+ filePath: string;
82
+ /** Live-apply new bindings to the running TUI (called after every write). */
83
+ apply: (bindings: Partial<KeyBindings>) => void;
84
+ /** Re-focus the CURRENT editor instance on close. */
85
+ restoreFocus: () => void;
86
+ }
87
+ /**
88
+ * Open the `/hotkeys` manager: a FieldPanel of the five app keys (binding,
89
+ * custom star, action, file status + warnings), Enter opens an EditField that
90
+ * writes the file and live-applies the change. Resolves with a summary when
91
+ * the user changed something and closed, or `undefined` when nothing changed.
92
+ */
93
+ export declare function openHotkeysManager(tui: TUI, theme: TuiTheme, options: HotkeysManagerOptions): Promise<string | undefined>;
package/lib/hotkeys.js ADDED
@@ -0,0 +1,305 @@
1
+ /**
2
+ * `/hotkeys` — view and customize the app-level keybindings, in the /agents
3
+ * select-panel style (src/panels.ts).
4
+ *
5
+ * pi's convention is a `/hotkeys` command plus a user-editable
6
+ * `~/.pi/agent/keybindings.json`. dsh side: `$DSH_HOME/keybindings.json`
7
+ * (default `~/.dsh/keybindings.json`). The file is a PARTIAL map of the four
8
+ * app keys ({@link APP_KEY_FIELDS}) to pi-tui key ids; anything missing falls
9
+ * back to the defaults (`src/keymap.ts`).
10
+ *
11
+ * UI (mirrors `/agents`): a FieldPanel lists the app keys — binding, custom
12
+ * star, action, file path + warnings; Enter opens an EditField to type a new
13
+ * key id (empty input resets the key to its default). A commit writes the
14
+ * file AND live-applies the new bindings to the running TUI (no /reload
15
+ * needed). Invalid entries never block: they warn and keep the default.
16
+ *
17
+ * The decision logic stays in `keymap.ts` (pure); this module owns the file
18
+ * contract, the validation, the display table and the interactive flow.
19
+ */
20
+ import { readFileSync, writeFileSync } from 'node:fs';
21
+ import { basename, join } from 'node:path';
22
+ import { DEFAULT_KEYBINDINGS } from "./keymap.js";
23
+ import { FieldPanel, PanelHost } from "./panels.js";
24
+ import { EditField } from "./settings.js";
25
+ import { ansiFg, BOLD, RESET } from "./theme/index.js";
26
+ /** The user-editable keybindings file name inside the dsh home. */
27
+ export const KEYBINDINGS_FILE = 'keybindings.json';
28
+ /** Absolute path of the keybindings file under a dsh home directory. */
29
+ export function keybindingsPath(home) {
30
+ return join(home, KEYBINDINGS_FILE);
31
+ }
32
+ /** The five app-level bindings the file may remap (order = display order). */
33
+ export const APP_KEY_FIELDS = ['escape', 'ctrlC', 'ctrlD', 'modelPicker', 'subagentViewer'];
34
+ /** Action descriptions for the `/hotkeys` table. */
35
+ const KEY_ACTIONS = {
36
+ escape: 'stop the current task — requires two presses (1st arms, 2nd within 500ms fires)',
37
+ ctrlC: 'running: cancel turn · idle: clear editor · second press quits',
38
+ ctrlD: 'quit — only on an empty editor',
39
+ modelPicker: 'open the model / think picker',
40
+ subagentViewer: 'open the subagent picker / viewer',
41
+ };
42
+ // ------------------------------------------------------------- validation --
43
+ const MODIFIERS = new Set(['ctrl', 'shift', 'alt', 'super']);
44
+ const NAMED_KEYS = new Set([
45
+ 'escape', 'esc', 'enter', 'return', 'tab', 'space', 'backspace', 'delete',
46
+ 'insert', 'home', 'end', 'pageup', 'pagedown', 'up', 'down', 'left',
47
+ 'right', 'clear',
48
+ ]);
49
+ /**
50
+ * Conservative check of one pi-tui key id as a user might type it:
51
+ * `modifier+key` where every modifier is ctrl/shift/alt/super and the key is
52
+ * a named key (`escape`, `pageUp`, `f5`, …) or a single printable character.
53
+ * pi-tui's own `parseKeyId` is lenient (unknown ids just never match), so we
54
+ * reject obvious typos up front and let a warning surface them.
55
+ */
56
+ export function isValidKeyId(value) {
57
+ if (typeof value !== 'string' || value === '' || value !== value.trim())
58
+ return false;
59
+ const parts = value.toLowerCase().split('+');
60
+ const key = parts[parts.length - 1];
61
+ if (key === '')
62
+ return false;
63
+ for (const modifier of parts.slice(0, -1)) {
64
+ if (!MODIFIERS.has(modifier))
65
+ return false;
66
+ }
67
+ if (/^f([1-9]|1[0-9]|2[0-4])$/.test(key))
68
+ return true;
69
+ if (NAMED_KEYS.has(key))
70
+ return true;
71
+ return [...key].length === 1;
72
+ }
73
+ /** Human display of a key id: `escape`→`Esc`, `ctrl+shift+p`→`Ctrl+Shift+P`. */
74
+ export function displayKey(id) {
75
+ const parts = id.split('+');
76
+ const modifiers = parts.slice(0, -1).map(m => m[0].toUpperCase() + m.slice(1));
77
+ const last = parts[parts.length - 1];
78
+ const key = last === 'escape' || last === 'esc'
79
+ ? 'Esc'
80
+ : last.length === 1
81
+ ? last.toUpperCase()
82
+ : last.charAt(0).toUpperCase() + last.slice(1);
83
+ return [...modifiers, key].join('+');
84
+ }
85
+ const EMPTY = { bindings: {}, warnings: [], exists: false };
86
+ /** Read + validate `$DSH_HOME/keybindings.json`. Never throws. */
87
+ export function loadKeyBindings(path) {
88
+ let text;
89
+ try {
90
+ text = readFileSync(path, 'utf8');
91
+ }
92
+ catch {
93
+ return EMPTY;
94
+ }
95
+ const label = basename(path);
96
+ let raw;
97
+ try {
98
+ raw = JSON.parse(text);
99
+ }
100
+ catch (error) {
101
+ return { bindings: {}, warnings: [`${label}: invalid JSON — ${error.message}`], exists: true };
102
+ }
103
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
104
+ return { bindings: {}, warnings: [`${label}: expected a JSON object of app-key → key id`], exists: true };
105
+ }
106
+ const record = raw;
107
+ const bindings = {};
108
+ const warnings = [];
109
+ for (const field of APP_KEY_FIELDS) {
110
+ const value = record[field];
111
+ if (value === undefined)
112
+ continue;
113
+ if (!isValidKeyId(value)) {
114
+ warnings.push(`${label}: "${field}" = ${JSON.stringify(value)} is not a valid key id — keeping the default`);
115
+ }
116
+ else {
117
+ bindings[field] = value;
118
+ }
119
+ }
120
+ for (const field of Object.keys(record)) {
121
+ if (!APP_KEY_FIELDS.includes(field)) {
122
+ warnings.push(`${label}: unknown field "${field}" — ignored`);
123
+ }
124
+ }
125
+ return { bindings, warnings, exists: true };
126
+ }
127
+ /**
128
+ * Merge-write the keybindings file: each `[field, value]` sets a binding,
129
+ * `null` removes it (reset to default). Unknown fields already in the file
130
+ * are preserved (the user's other keys survive). Missing file → fresh object;
131
+ * an unreadable/broken EXISTING file is an error — never clobbered silently.
132
+ * Returns an error message, or `undefined` on success.
133
+ */
134
+ export function updateKeyBindingsFile(path, updates) {
135
+ const label = basename(path);
136
+ const existing = {};
137
+ let fileExisted = false;
138
+ try {
139
+ const text = readFileSync(path, 'utf8');
140
+ fileExisted = true;
141
+ const parsed = JSON.parse(text);
142
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
143
+ return `${label}: expected a JSON object — fix or delete the file, then retry`;
144
+ }
145
+ Object.assign(existing, parsed);
146
+ }
147
+ catch (error) {
148
+ if (fileExisted)
149
+ return `${label}: ${error.message} — fix or delete the file, then retry`;
150
+ // Absent file: start fresh.
151
+ }
152
+ for (const [field, value] of updates) {
153
+ if (value === null)
154
+ delete existing[field];
155
+ else
156
+ existing[field] = value;
157
+ }
158
+ try {
159
+ writeFileSync(path, JSON.stringify(existing, null, 2) + '\n');
160
+ }
161
+ catch (error) {
162
+ return `${label}: cannot write — ${error.message}`;
163
+ }
164
+ return undefined;
165
+ }
166
+ /** The `/hotkeys` EditField parse: empty = reset, else a validated key id. */
167
+ export function parseKeyInput(text) {
168
+ const trimmed = text.trim();
169
+ if (trimmed === '')
170
+ return { kind: 'unset' };
171
+ if (!isValidKeyId(trimmed)) {
172
+ return { kind: 'error', error: `not a key id — ctrl/shift/alt/super + key (e.g. ctrl+x, f5, escape)` };
173
+ }
174
+ return { kind: 'value', value: trimmed };
175
+ }
176
+ /**
177
+ * Build the app-key rows from the effective bindings — defaults, with any
178
+ * file override replacing the key display and flagging the row as custom.
179
+ * Pure, so the table content is unit-testable without a terminal.
180
+ */
181
+ export function appHotkeyRows(custom) {
182
+ return APP_KEY_FIELDS.map(field => {
183
+ const override = custom[field];
184
+ return {
185
+ field,
186
+ key: displayKey(override ?? DEFAULT_KEYBINDINGS[field]),
187
+ action: KEY_ACTIONS[field],
188
+ custom: override !== undefined,
189
+ };
190
+ });
191
+ }
192
+ /**
193
+ * Open the `/hotkeys` manager: a FieldPanel of the five app keys (binding,
194
+ * custom star, action, file status + warnings), Enter opens an EditField that
195
+ * writes the file and live-applies the change. Resolves with a summary when
196
+ * the user changed something and closed, or `undefined` when nothing changed.
197
+ */
198
+ export async function openHotkeysManager(tui, theme, options) {
199
+ let changed = false;
200
+ /** Live status line of the FieldPanel (last commit result). */
201
+ let status;
202
+ /** Settles the manager promise (assigned inside the executor below). */
203
+ let settle;
204
+ const host = new PanelHost(tui, theme, message => {
205
+ options.restoreFocus();
206
+ settle?.(`✘ failed to open the hotkeys view: ${message}`);
207
+ });
208
+ /** Re-read the file after a write and push the change into the running TUI. */
209
+ const applyBindings = () => {
210
+ const loaded = loadKeyBindings(options.filePath);
211
+ options.apply(loaded.bindings);
212
+ };
213
+ /** Rebuild the field panel from the current file state. */
214
+ const show = () => {
215
+ const loaded = loadKeyBindings(options.filePath);
216
+ const fields = appHotkeyRows(loaded.bindings).map(row => ({
217
+ key: row.field,
218
+ value: `${row.key}${row.custom ? '*' : ''} — ${row.action}`,
219
+ editable: true,
220
+ }));
221
+ const customCount = Object.keys(loaded.bindings).length;
222
+ const content = [
223
+ loaded.exists
224
+ ? `custom: ${options.filePath} (${customCount} override${customCount === 1 ? '' : 's'})`
225
+ : `custom: ${options.filePath} (not found — defaults in use)`,
226
+ 'format: ctrl/shift/alt/super+key · Enter edits · empty input resets to the default',
227
+ 'editor: pi-tui defaults — arrows · Ctrl+B/F · Alt+←→ word · Home/End · Ctrl+W/U/K delete · Ctrl+- undo',
228
+ ...loaded.warnings.map(warning => `! ${warning}`),
229
+ ];
230
+ const panel = new FieldPanel(theme, {
231
+ title: ansiFg(theme.palette.accent) + BOLD + '⚙ hotkeys' + RESET,
232
+ content,
233
+ fields,
234
+ status: () => status,
235
+ footer: '↑↓ key · Enter change · Esc close',
236
+ onEdit: index => edit(fields[index].key),
237
+ onCancel: () => {
238
+ host.close();
239
+ options.restoreFocus();
240
+ resolve(changed ? 'Keybindings updated.' : undefined);
241
+ },
242
+ });
243
+ host.open(panel);
244
+ };
245
+ const resolve = (value) => {
246
+ settle?.(value);
247
+ };
248
+ /** EditField for one app key: type a key id, empty = reset to default. */
249
+ const edit = (field) => {
250
+ const loaded = loadKeyBindings(options.filePath);
251
+ const current = loaded.bindings[field];
252
+ const editor = new EditField(tui, {
253
+ title: `Key for ${field} — default ${displayKey(DEFAULT_KEYBINDINGS[field])}`
254
+ + (current !== undefined ? ` · custom ${displayKey(current)}` : ''),
255
+ subtitle: 'ctrl/shift/alt/super + key · empty resets to the default',
256
+ initial: current ?? '',
257
+ parse: parseKeyInput,
258
+ onCommit: async (outcome) => {
259
+ if (outcome.kind === 'value') {
260
+ const id = outcome.value;
261
+ // Writing the default is a reset: keep the file minimal.
262
+ const reset = id === DEFAULT_KEYBINDINGS[field];
263
+ const fresh = loadKeyBindings(options.filePath);
264
+ if (reset && fresh.bindings[field] === undefined)
265
+ return undefined; // already default — no write
266
+ const error = updateKeyBindingsFile(options.filePath, [[field, reset ? null : id]]);
267
+ if (error !== undefined)
268
+ return { error };
269
+ changed = true;
270
+ applyBindings();
271
+ status = reset
272
+ ? `${field} → default (${displayKey(DEFAULT_KEYBINDINGS[field])}) — applied`
273
+ : `${field} → ${id} — applied`;
274
+ return undefined;
275
+ }
276
+ if (outcome.kind === 'unset') {
277
+ const fresh = loadKeyBindings(options.filePath);
278
+ if (fresh.bindings[field] === undefined)
279
+ return undefined; // nothing custom to reset
280
+ const error = updateKeyBindingsFile(options.filePath, [[field, null]]);
281
+ if (error !== undefined)
282
+ return { error };
283
+ changed = true;
284
+ applyBindings();
285
+ status = `${field} → default (${displayKey(DEFAULT_KEYBINDINGS[field])}) — applied`;
286
+ return undefined;
287
+ }
288
+ return undefined;
289
+ },
290
+ onDone: () => show(),
291
+ onError: message => {
292
+ status = `✘ ${message}`;
293
+ show();
294
+ },
295
+ }, theme);
296
+ host.open(editor);
297
+ };
298
+ return new Promise(resolve => {
299
+ settle = resolve;
300
+ // First render inside the executor: a synchronous showOverlay failure in
301
+ // the initial show() must be able to settle the promise through settle.
302
+ show();
303
+ });
304
+ }
305
+ //# sourceMappingURL=hotkeys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hotkeys.js","sourceRoot":"","sources":["../src/hotkeys.ts"],"names":[],"mappings":"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"}