@gigaflow/gmux 0.15.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 (229) hide show
  1. package/CHANGELOG.md +654 -0
  2. package/LICENSE +21 -0
  3. package/README.md +351 -0
  4. package/dist/adapters/claude-code.d.ts +52 -0
  5. package/dist/adapters/claude-code.js +315 -0
  6. package/dist/adapters/claude-code.js.map +1 -0
  7. package/dist/adapters/codex.d.ts +39 -0
  8. package/dist/adapters/codex.js +233 -0
  9. package/dist/adapters/codex.js.map +1 -0
  10. package/dist/adapters/jsonl.d.ts +40 -0
  11. package/dist/adapters/jsonl.js +92 -0
  12. package/dist/adapters/jsonl.js.map +1 -0
  13. package/dist/adapters/registry.d.ts +11 -0
  14. package/dist/adapters/registry.js +21 -0
  15. package/dist/adapters/registry.js.map +1 -0
  16. package/dist/adapters/types.d.ts +43 -0
  17. package/dist/adapters/types.js +2 -0
  18. package/dist/adapters/types.js.map +1 -0
  19. package/dist/cli/border-client.d.ts +8 -0
  20. package/dist/cli/border-client.js +11 -0
  21. package/dist/cli/border-client.js.map +1 -0
  22. package/dist/cli/commands/__ask-cancel.d.ts +35 -0
  23. package/dist/cli/commands/__ask-cancel.js +91 -0
  24. package/dist/cli/commands/__ask-cancel.js.map +1 -0
  25. package/dist/cli/commands/__ask-refresh.d.ts +40 -0
  26. package/dist/cli/commands/__ask-refresh.js +54 -0
  27. package/dist/cli/commands/__ask-refresh.js.map +1 -0
  28. package/dist/cli/commands/__ask-run.d.ts +43 -0
  29. package/dist/cli/commands/__ask-run.js +126 -0
  30. package/dist/cli/commands/__ask-run.js.map +1 -0
  31. package/dist/cli/commands/__ask-send.d.ts +50 -0
  32. package/dist/cli/commands/__ask-send.js +138 -0
  33. package/dist/cli/commands/__ask-send.js.map +1 -0
  34. package/dist/cli/commands/__preview-card.d.ts +31 -0
  35. package/dist/cli/commands/__preview-card.js +72 -0
  36. package/dist/cli/commands/__preview-card.js.map +1 -0
  37. package/dist/cli/commands/ask.d.ts +50 -0
  38. package/dist/cli/commands/ask.js +240 -0
  39. package/dist/cli/commands/ask.js.map +1 -0
  40. package/dist/cli/commands/auto.d.ts +12 -0
  41. package/dist/cli/commands/auto.js +28 -0
  42. package/dist/cli/commands/auto.js.map +1 -0
  43. package/dist/cli/commands/cockpit.d.ts +14 -0
  44. package/dist/cli/commands/cockpit.js +52 -0
  45. package/dist/cli/commands/cockpit.js.map +1 -0
  46. package/dist/cli/commands/daemon.d.ts +75 -0
  47. package/dist/cli/commands/daemon.js +258 -0
  48. package/dist/cli/commands/daemon.js.map +1 -0
  49. package/dist/cli/commands/doctor.d.ts +6 -0
  50. package/dist/cli/commands/doctor.js +159 -0
  51. package/dist/cli/commands/doctor.js.map +1 -0
  52. package/dist/cli/commands/grep.d.ts +2 -0
  53. package/dist/cli/commands/grep.js +52 -0
  54. package/dist/cli/commands/grep.js.map +1 -0
  55. package/dist/cli/commands/index-cmd.d.ts +2 -0
  56. package/dist/cli/commands/index-cmd.js +29 -0
  57. package/dist/cli/commands/index-cmd.js.map +1 -0
  58. package/dist/cli/commands/ls.d.ts +30 -0
  59. package/dist/cli/commands/ls.js +95 -0
  60. package/dist/cli/commands/ls.js.map +1 -0
  61. package/dist/cli/commands/overlay.d.ts +26 -0
  62. package/dist/cli/commands/overlay.js +216 -0
  63. package/dist/cli/commands/overlay.js.map +1 -0
  64. package/dist/cli/commands/pick.d.ts +59 -0
  65. package/dist/cli/commands/pick.js +254 -0
  66. package/dist/cli/commands/pick.js.map +1 -0
  67. package/dist/cli/commands/picker-rows.d.ts +17 -0
  68. package/dist/cli/commands/picker-rows.js +47 -0
  69. package/dist/cli/commands/picker-rows.js.map +1 -0
  70. package/dist/cli/commands/resume.d.ts +25 -0
  71. package/dist/cli/commands/resume.js +88 -0
  72. package/dist/cli/commands/resume.js.map +1 -0
  73. package/dist/cli/commands/run.d.ts +13 -0
  74. package/dist/cli/commands/run.js +78 -0
  75. package/dist/cli/commands/run.js.map +1 -0
  76. package/dist/cli/commands/setup.d.ts +37 -0
  77. package/dist/cli/commands/setup.js +200 -0
  78. package/dist/cli/commands/setup.js.map +1 -0
  79. package/dist/cli/commands/show.d.ts +2 -0
  80. package/dist/cli/commands/show.js +24 -0
  81. package/dist/cli/commands/show.js.map +1 -0
  82. package/dist/cli/commands/summarize.d.ts +2 -0
  83. package/dist/cli/commands/summarize.js +59 -0
  84. package/dist/cli/commands/summarize.js.map +1 -0
  85. package/dist/cli/commands/tmux.d.ts +11 -0
  86. package/dist/cli/commands/tmux.js +90 -0
  87. package/dist/cli/commands/tmux.js.map +1 -0
  88. package/dist/cli/commands/watch.d.ts +2 -0
  89. package/dist/cli/commands/watch.js +76 -0
  90. package/dist/cli/commands/watch.js.map +1 -0
  91. package/dist/cli/format.d.ts +74 -0
  92. package/dist/cli/format.js +242 -0
  93. package/dist/cli/format.js.map +1 -0
  94. package/dist/cli/gmux-render.d.ts +11 -0
  95. package/dist/cli/gmux-render.js +60 -0
  96. package/dist/cli/gmux-render.js.map +1 -0
  97. package/dist/cli/main.d.ts +8 -0
  98. package/dist/cli/main.js +145 -0
  99. package/dist/cli/main.js.map +1 -0
  100. package/dist/cli/overlay-ask.d.ts +13 -0
  101. package/dist/cli/overlay-ask.js +32 -0
  102. package/dist/cli/overlay-ask.js.map +1 -0
  103. package/dist/cli/overlay.d.ts +26 -0
  104. package/dist/cli/overlay.js +149 -0
  105. package/dist/cli/overlay.js.map +1 -0
  106. package/dist/cli/picker.d.ts +308 -0
  107. package/dist/cli/picker.js +642 -0
  108. package/dist/cli/picker.js.map +1 -0
  109. package/dist/cli/preview.d.ts +87 -0
  110. package/dist/cli/preview.js +292 -0
  111. package/dist/cli/preview.js.map +1 -0
  112. package/dist/cli/tmux-label.d.ts +50 -0
  113. package/dist/cli/tmux-label.js +146 -0
  114. package/dist/cli/tmux-label.js.map +1 -0
  115. package/dist/core/errors.d.ts +54 -0
  116. package/dist/core/errors.js +91 -0
  117. package/dist/core/errors.js.map +1 -0
  118. package/dist/core/fingerprint.d.ts +21 -0
  119. package/dist/core/fingerprint.js +59 -0
  120. package/dist/core/fingerprint.js.map +1 -0
  121. package/dist/core/gmux-types.d.ts +102 -0
  122. package/dist/core/gmux-types.js +13 -0
  123. package/dist/core/gmux-types.js.map +1 -0
  124. package/dist/core/pane-state.d.ts +5 -0
  125. package/dist/core/pane-state.js +15 -0
  126. package/dist/core/pane-state.js.map +1 -0
  127. package/dist/core/paths.d.ts +68 -0
  128. package/dist/core/paths.js +106 -0
  129. package/dist/core/paths.js.map +1 -0
  130. package/dist/core/proc-tree.d.ts +9 -0
  131. package/dist/core/proc-tree.js +33 -0
  132. package/dist/core/proc-tree.js.map +1 -0
  133. package/dist/core/text.d.ts +34 -0
  134. package/dist/core/text.js +126 -0
  135. package/dist/core/text.js.map +1 -0
  136. package/dist/core/types.d.ts +322 -0
  137. package/dist/core/types.js +10 -0
  138. package/dist/core/types.js.map +1 -0
  139. package/dist/services/ask-transcript.d.ts +256 -0
  140. package/dist/services/ask-transcript.js +544 -0
  141. package/dist/services/ask-transcript.js.map +1 -0
  142. package/dist/services/ask.d.ts +54 -0
  143. package/dist/services/ask.js +161 -0
  144. package/dist/services/ask.js.map +1 -0
  145. package/dist/services/auto-summarize.d.ts +188 -0
  146. package/dist/services/auto-summarize.js +415 -0
  147. package/dist/services/auto-summarize.js.map +1 -0
  148. package/dist/services/concurrency.d.ts +2 -0
  149. package/dist/services/concurrency.js +16 -0
  150. package/dist/services/concurrency.js.map +1 -0
  151. package/dist/services/config.d.ts +131 -0
  152. package/dist/services/config.js +325 -0
  153. package/dist/services/config.js.map +1 -0
  154. package/dist/services/daemon-client.d.ts +9 -0
  155. package/dist/services/daemon-client.js +34 -0
  156. package/dist/services/daemon-client.js.map +1 -0
  157. package/dist/services/daemon-socket.d.ts +30 -0
  158. package/dist/services/daemon-socket.js +76 -0
  159. package/dist/services/daemon-socket.js.map +1 -0
  160. package/dist/services/daemon.d.ts +43 -0
  161. package/dist/services/daemon.js +106 -0
  162. package/dist/services/daemon.js.map +1 -0
  163. package/dist/services/distill.d.ts +39 -0
  164. package/dist/services/distill.js +93 -0
  165. package/dist/services/distill.js.map +1 -0
  166. package/dist/services/guardian.d.ts +26 -0
  167. package/dist/services/guardian.js +71 -0
  168. package/dist/services/guardian.js.map +1 -0
  169. package/dist/services/index-store.d.ts +36 -0
  170. package/dist/services/index-store.js +125 -0
  171. package/dist/services/index-store.js.map +1 -0
  172. package/dist/services/log-rotation.d.ts +3 -0
  173. package/dist/services/log-rotation.js +28 -0
  174. package/dist/services/log-rotation.js.map +1 -0
  175. package/dist/services/pane-links.d.ts +10 -0
  176. package/dist/services/pane-links.js +47 -0
  177. package/dist/services/pane-links.js.map +1 -0
  178. package/dist/services/pane-process.d.ts +95 -0
  179. package/dist/services/pane-process.js +183 -0
  180. package/dist/services/pane-process.js.map +1 -0
  181. package/dist/services/pane-registry.d.ts +24 -0
  182. package/dist/services/pane-registry.js +40 -0
  183. package/dist/services/pane-registry.js.map +1 -0
  184. package/dist/services/provider-process.d.ts +37 -0
  185. package/dist/services/provider-process.js +105 -0
  186. package/dist/services/provider-process.js.map +1 -0
  187. package/dist/services/providers.d.ts +76 -0
  188. package/dist/services/providers.js +104 -0
  189. package/dist/services/providers.js.map +1 -0
  190. package/dist/services/resolve.d.ts +3 -0
  191. package/dist/services/resolve.js +18 -0
  192. package/dist/services/resolve.js.map +1 -0
  193. package/dist/services/resources.d.ts +17 -0
  194. package/dist/services/resources.js +113 -0
  195. package/dist/services/resources.js.map +1 -0
  196. package/dist/services/search.d.ts +29 -0
  197. package/dist/services/search.js +135 -0
  198. package/dist/services/search.js.map +1 -0
  199. package/dist/services/semantic-gate.d.ts +13 -0
  200. package/dist/services/semantic-gate.js +23 -0
  201. package/dist/services/semantic-gate.js.map +1 -0
  202. package/dist/services/semantic.d.ts +113 -0
  203. package/dist/services/semantic.js +216 -0
  204. package/dist/services/semantic.js.map +1 -0
  205. package/dist/services/sensors.d.ts +92 -0
  206. package/dist/services/sensors.js +246 -0
  207. package/dist/services/sensors.js.map +1 -0
  208. package/dist/services/summarize.d.ts +84 -0
  209. package/dist/services/summarize.js +230 -0
  210. package/dist/services/summarize.js.map +1 -0
  211. package/dist/services/tmux-gateway.d.ts +17 -0
  212. package/dist/services/tmux-gateway.js +10 -0
  213. package/dist/services/tmux-gateway.js.map +1 -0
  214. package/dist/services/tmux-resolve.d.ts +54 -0
  215. package/dist/services/tmux-resolve.js +0 -0
  216. package/dist/services/tmux-resolve.js.map +1 -0
  217. package/dist/services/tmux.d.ts +32 -0
  218. package/dist/services/tmux.js +107 -0
  219. package/dist/services/tmux.js.map +1 -0
  220. package/dist/services/views.d.ts +7 -0
  221. package/dist/services/views.js +18 -0
  222. package/dist/services/views.js.map +1 -0
  223. package/dist/services/watch.d.ts +36 -0
  224. package/dist/services/watch.js +98 -0
  225. package/dist/services/watch.js.map +1 -0
  226. package/dist/services/workspace.d.ts +19 -0
  227. package/dist/services/workspace.js +88 -0
  228. package/dist/services/workspace.js.map +1 -0
  229. package/package.json +64 -0
@@ -0,0 +1,642 @@
1
+ /**
2
+ * Session picker.
3
+ *
4
+ * fzf is used when installed — it gives fuzzy matching and a live preview pane
5
+ * for free. When it is absent we fall back to a numbered prompt rather than
6
+ * failing: gmux must work on a machine with nothing but Node.
7
+ *
8
+ * Rows WRAP rather than being chopped at the right edge, in both modes. In fzf
9
+ * that needs multi-line items: records are NUL-delimited (`--read0`) so a single
10
+ * session can span several display lines and still be selected as one thing.
11
+ * fzf gained multi-line display in 0.46, so older versions fall back to
12
+ * single-line rows rather than rendering one session as several bogus entries.
13
+ */
14
+ import { spawn, spawnSync } from "node:child_process";
15
+ import { randomBytes } from "node:crypto";
16
+ import { createInterface } from "node:readline/promises";
17
+ import { shellQuote } from "../core/text.js";
18
+ import { formatMarkerKey, formatRow, formatRowLines, terminalWidth, } from "./format.js";
19
+ /** Fraction of the terminal the list occupies; the rest is the preview pane. */
20
+ const LIST_FRACTION = 0.45;
21
+ /** fzf's own chrome: pointer, marker, border, padding. */
22
+ const FZF_CHROME = 6;
23
+ /** First fzf release with multi-line item display. */
24
+ const MULTILINE_FZF = [0, 46, 0];
25
+ /**
26
+ * First fzf release exporting `$FZF_INPUT_STATE`, the split chat's mode oracle.
27
+ *
28
+ * Its own constant rather than `MULTILINE_FZF`: every other action the chat
29
+ * bindings use is at or below 0.46, so the oracle alone sets this floor, and
30
+ * riding on the multi-line gate would be accidental. `MULTILINE_FZF` is wrong
31
+ * anyway — multi-line landed in 0.53 — and the day someone corrects it the chat
32
+ * must not silently change tiers with it.
33
+ */
34
+ const SPLIT_CHAT_FZF = [0, 59, 0];
35
+ export function hasFzf() {
36
+ return spawnSync("which", ["fzf"], { stdio: "ignore" }).status === 0;
37
+ }
38
+ /** fzf's version as [major, minor, patch], or null if it cannot be determined. */
39
+ export function fzfVersion() {
40
+ const probe = spawnSync("fzf", ["--version"], { encoding: "utf8" });
41
+ if (probe.status !== 0 || typeof probe.stdout !== "string")
42
+ return null;
43
+ const match = /(\d+)\.(\d+)\.(\d+)/.exec(probe.stdout);
44
+ return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
45
+ }
46
+ /**
47
+ * Is `version` at least `want`, comparing component by component?
48
+ *
49
+ * A null version — `fzf --version` unreadable — is NOT enough. Every caller
50
+ * gates a feature on this, and assuming a feature we cannot see makes fzf exit
51
+ * non-zero at startup for exactly the people we could not probe.
52
+ *
53
+ * Missing components read as 0, so a want longer than the version still
54
+ * decides: [0, 46] is not [0, 46, 1].
55
+ */
56
+ export function atLeast(version, want) {
57
+ if (!version)
58
+ return false;
59
+ for (let i = 0; i < want.length; i++) {
60
+ const part = version[i] ?? 0;
61
+ const need = want[i] ?? 0;
62
+ if (part > need)
63
+ return true;
64
+ if (part < need)
65
+ return false;
66
+ }
67
+ return true;
68
+ }
69
+ /** True when this fzf can display one item across several lines. */
70
+ export function supportsMultiline(version) {
71
+ return atLeast(version, MULTILINE_FZF);
72
+ }
73
+ /** True when this fzf can tell a binding which input mode it is in. */
74
+ export function supportsSplitChat(version) {
75
+ return atLeast(version, SPLIT_CHAT_FZF);
76
+ }
77
+ export function askTier(input) {
78
+ // Nothing to ask with. A key that opens a chat which dies instantly is worse
79
+ // than a key that isn't there.
80
+ if (!input.askAvailable)
81
+ return "none";
82
+ // The numbered fallback calls back into this process, so it needs no way to
83
+ // address this build — which is the whole reason it can be offered when
84
+ // `selfCommand` is null.
85
+ if (!input.hasFzf)
86
+ return "prompt";
87
+ // Every fzf tier runs `gmux` through a shell, so an unaddressable build has no
88
+ // command to bind.
89
+ if (!input.selfCommand)
90
+ return "none";
91
+ // An unreadable version lands here too, because `atLeast(null, …)` is false:
92
+ // degrading to the older UI is a worse UI, degrading to `split` is a broken
93
+ // one.
94
+ return supportsSplitChat(input.fzfVersion) ? "split" : "execute";
95
+ }
96
+ /** How wide the list column is inside fzf, once the preview pane is taken out. */
97
+ export function listWidth(width = terminalWidth()) {
98
+ return Math.max(32, Math.floor(width * LIST_FRACTION) - FZF_CHROME);
99
+ }
100
+ /**
101
+ * The records fed to fzf, NUL-delimited.
102
+ *
103
+ * Each record is `<session-id>\t<display>`, where `<display>` may contain
104
+ * newlines. fzf shows fields 2.. and hands field 1 to the preview command and
105
+ * back to us on selection, so the id never appears on screen twice and the
106
+ * mapping back to a session survives wrapping.
107
+ */
108
+ export function buildFzfRecords(views, multiline, width = listWidth(), now = new Date(), inProgress = new Set()) {
109
+ return views
110
+ .map((view) => {
111
+ const display = multiline
112
+ ? formatRowLines(view, now, width, inProgress).join("\n")
113
+ : formatRow(view, now, inProgress);
114
+ return `${view.record.sessionId}\t${display}`;
115
+ })
116
+ .join("\0");
117
+ }
118
+ /**
119
+ * The session behind the id fzf handed back.
120
+ *
121
+ * Checks the list we opened with first, then falls back to a fresh lookup. That
122
+ * fallback is what makes ctrl-r work: selecting a session that appeared *during*
123
+ * the refresh would otherwise miss the map built at open and report "Nothing
124
+ * selected" — refusing to resume the very session you refreshed to find.
125
+ */
126
+ export async function resolvePicked(id, views, resolve) {
127
+ const known = views.find((v) => v.record.sessionId === id);
128
+ if (known)
129
+ return known;
130
+ return resolve ? await resolve(id) : null;
131
+ }
132
+ /** Returns the chosen session, or null if the user cancelled. */
133
+ export async function pickSession(views, options = {}) {
134
+ if (views.length === 0)
135
+ return null;
136
+ return hasFzf() ? pickWithFzf(views, options) : pickWithPrompt(views, options);
137
+ }
138
+ /**
139
+ * How to re-invoke *this* build, as a shell command string.
140
+ *
141
+ * fzf runs the preview and reload commands through a shell, and they must hit
142
+ * this build — not whatever `gmux` happens to be on PATH. During development
143
+ * there may be no `gmux` on PATH at all, and both would silently render nothing.
144
+ *
145
+ * `execArgv` MUST be forwarded, for the same reason `spawnWorker` forwards it:
146
+ * under `npm run dev` the entry point is `src/cli/main.ts` and execArgv carries
147
+ * tsx's loader flags. Drop them and the command becomes `node src/cli/main.ts`,
148
+ * which Node 20 cannot run — so the preview pane and ctrl-r both die in
149
+ * development while working perfectly from `dist/`. (Node 22 strips types
150
+ * natively and hides this, which is exactly what makes it worth a comment.)
151
+ *
152
+ * Returns null when the entry point is unavailable, leaving callers to decide
153
+ * on a fallback.
154
+ */
155
+ export function selfCommand(execPath, execArgv, entry) {
156
+ if (!entry)
157
+ return null;
158
+ return [execPath, ...execArgv, entry].map(shellQuote).join(" ");
159
+ }
160
+ /** `selfCommand` for the running process. */
161
+ export function selfCommandHere() {
162
+ return selfCommand(process.execPath, process.execArgv, process.argv[1]);
163
+ }
164
+ /**
165
+ * The command fzf runs to fill its preview pane.
166
+ *
167
+ * **Constant for the whole picker run.** Every mutable thing lives in the
168
+ * transcript file, which is what makes `refresh-preview` sufficient and
169
+ * `change-preview` unnecessary — and why there is no reflow and therefore no
170
+ * flicker.
171
+ *
172
+ * `${FZF_PREVIEW_LINES:-0}` — the `:-0` is load-bearing, and not because the
173
+ * variable is plausibly unset (fzf has exported it to the preview process since
174
+ * 0.18.0). The value is environment-controlled text and the parse must not
175
+ * silently shift arguments: a bare `$FZF_PREVIEW_LINES` expanding to nothing
176
+ * makes commander read the NEXT FLAG NAME as the pane height. `0` then means
177
+ * "guess" to `splitPreview`, which is the honest answer.
178
+ *
179
+ * `__preview-card` is spelled literally for the same reason `show` is: picker.ts
180
+ * imports no command module, and that is what keeps it knowing nothing about
181
+ * providers (picker.ts:126-132 — the invariant holds by the import list, not by
182
+ * the layer checker, which would pass `import { defaultAskProvider }` in
183
+ * silence). tests/picker.test.ts pins the spelling against the real constant.
184
+ */
185
+ function previewCommand(transcript) {
186
+ const self = selfCommandHere() ?? "gmux";
187
+ if (!transcript)
188
+ return `${self} show {1} --no-color`;
189
+ return `${self} __preview-card {1} --chat ${shellQuote(transcript)} --pane-lines \${FZF_PREVIEW_LINES:-0}`;
190
+ }
191
+ /**
192
+ * The shell command behind ctrl-r, or null when we cannot address this build.
193
+ *
194
+ * Without one the key is simply not bound and the header does not advertise it —
195
+ * a key that does nothing is worse than a key that isn't there.
196
+ */
197
+ function reloadCommand(reloadArgs) {
198
+ const self = selfCommandHere();
199
+ if (!self || !reloadArgs || reloadArgs.length === 0)
200
+ return null;
201
+ return `${self} ${reloadArgs.map(shellQuote).join(" ")}`;
202
+ }
203
+ /**
204
+ * The command behind ctrl-o: open `gmux ask` about the highlighted session.
205
+ *
206
+ * `askArgs` MUST carry the picker's filters and limit, for the same reason
207
+ * `reloadArgs` does. Without them the child re-derives its own window from
208
+ * defaults — the 20 most recent sessions across every project — and the session
209
+ * you are highlighting is often not in it. `--focus` then silently resolves to
210
+ * null and the chat answers about a list you never asked about, looking normal
211
+ * the whole time.
212
+ *
213
+ * `{1}` is appended unquoted because fzf substitutes it: it is the session id
214
+ * field, and quoting it would hand the child the literal string `{1}`.
215
+ *
216
+ * Null when this build cannot address itself, or when the caller says ask is
217
+ * unavailable — and then the key is not bound and not advertised.
218
+ */
219
+ function askCommand(askArgs) {
220
+ const self = selfCommandHere();
221
+ if (!self || !askArgs || askArgs.length === 0)
222
+ return null;
223
+ return `${self} ${askArgs.map(shellQuote).join(" ")} --focus {1}`;
224
+ }
225
+ /** The browse prompt. Swapping it is not cosmetic — see `sendActions`. */
226
+ const BROWSE_PROMPT = "session > ";
227
+ const ASK_PROMPT = "ask > ";
228
+ /**
229
+ * The ask header lists exactly the two keys ask mode rebinds, and `ctrl-r` is
230
+ * absent because ask mode `unbind`s it rather than leaving it live and
231
+ * unadvertised. Both headers keep the marker legend on line 2 — it must survive
232
+ * both modes.
233
+ */
234
+ const ASK_KEYS = ["enter: send", "esc: back"];
235
+ /** Two lines: what the keys do, then what the row markers mean. fzf renders an
236
+ * embedded newline as a second header line, and processes the key's colours
237
+ * regardless of --ansi (see `man fzf` on --header). */
238
+ function headerFor(keys) {
239
+ return `${keys.filter((k) => k !== "").join(" ")}\n${formatMarkerKey()}`;
240
+ }
241
+ /**
242
+ * Where the browse query is parked while ask mode owns the query line.
243
+ *
244
+ * A sibling of the transcript, not a state directory: it inherits the
245
+ * transcript's `<pid>-<rand8>` uniqueness for free, so two concurrent pickers
246
+ * cannot collide, and it lands in the cleanup and sweep paths that already exist
247
+ * with no new concept.
248
+ *
249
+ * The suffix is spelled here AND in `askBrowseQueryPath` (services/ask-transcript.ts),
250
+ * which is what deletes and sweeps it — the picker may not import a service. A
251
+ * drift between the two is silent (esc restores nothing), so tests/picker.test.ts
252
+ * pins them equal.
253
+ */
254
+ function browseQueryPath(transcript) {
255
+ return `${transcript}.browseq`;
256
+ }
257
+ /**
258
+ * The ctrl-o transform body: browse → ask.
259
+ *
260
+ * **POSIX `[ … ]` and `if … fi`, no `[[ ]]` and no braces.** fzf runs child
261
+ * commands with `$SHELL -c`, not `sh -c` (`man fzf` says so twice, lines
262
+ * 1400-1402 and 2133-2135). Reproduced: `/bin/dash -c '[[ x = x ]]'` is
263
+ * `[[: not found`, which makes ctrl-o a DEAD KEY with no error anywhere. The
264
+ * `--with-shell 'sh -c'` on the arg list and these bodies are one fix, not two —
265
+ * csh cannot parse `if …; then` either, so the bodies alone are not sufficient
266
+ * and `--with-shell` alone leaves a bash-ism that is simply wrong.
267
+ *
268
+ * **`!= disabled`, never `= enabled`.** The oracle is TERNARY — `man fzf`:1462,
269
+ * *"Current input state (enabled, disabled, hidden)"* — and `--no-input` yields
270
+ * `hidden`. A ctrl-o guarded on `= enabled` is silently inert under `--no-input`.
271
+ * Every spelling here treats `hidden` as browse, which is the fail-safe
272
+ * direction.
273
+ *
274
+ * **No `else`, because a transform that emits nothing is a no-op** — verified:
275
+ * ctrl-o twice does not double-enter or crash.
276
+ */
277
+ export function enterAskActions(spec) {
278
+ const actions = [
279
+ "disable-search",
280
+ "clear-query",
281
+ // ctrl-r `reload`s the FULL list while `disable-search` is active, so the
282
+ // frozen browse filter — the thing we keep on purpose, so the rows under the
283
+ // cursor do not move when you press ctrl-o — evaporates mid-thread and cannot
284
+ // be restored until esc. Unadvertised AND destructive is exactly what
285
+ // `unbind` is for.
286
+ "unbind(ctrl-r)",
287
+ `change-prompt(${ASK_PROMPT})`,
288
+ `change-header(${spec.askHeader})`,
289
+ ].join("+");
290
+ return [
291
+ `if [ "$FZF_INPUT_STATE" != disabled ]; then`,
292
+ // The browse query is parked in a file because ask mode needs the query line
293
+ // back. `disable-search` freezes the list where the browse query left it, and
294
+ // it must stay there.
295
+ `printf '%s' "$FZF_QUERY" > ${shellQuote(browseQueryPath(spec.transcript))}`,
296
+ `echo "${actions}"`,
297
+ "fi",
298
+ ].join("\n");
299
+ }
300
+ /**
301
+ * The esc transform body: ask → browse, and abort in browse mode.
302
+ *
303
+ * The exact inverse of `enterAskActions`, which is why the two are split: for
304
+ * every stateful action there, the undo is here. Two independent
305
+ * `askModeBindings`/`browseModeBindings` could not be tested for that, and the
306
+ * bug they invite is asymmetry — ask fires `disable-search`, browse forgets
307
+ * `enable-search`, and the filter is dead with no error anywhere.
308
+ */
309
+ export function exitAskActions(spec) {
310
+ const actions = [
311
+ // BEFORE `transform-query`, or the restored query never re-triggers the
312
+ // search and the list stays frozen behind a filter you can see.
313
+ "enable-search",
314
+ "rebind(ctrl-r)",
315
+ // `transform-query(cat file)`, not `change-query($(cat …))`: the browse query
316
+ // is text a human typed and sidestepping the quoting is free here.
317
+ `transform-query(cat ${shellQuote(browseQueryPath(spec.transcript))})`,
318
+ `change-prompt(${BROWSE_PROMPT})`,
319
+ `change-header(${spec.browseHeader})`,
320
+ ].join("+");
321
+ return [
322
+ `if [ "$FZF_INPUT_STATE" = disabled ]; then`,
323
+ // `>/dev/null 2>&1` is not tidiness. Verified: a child that inherits fzf's
324
+ // stdout blocks fzf until EOF EVEN WHEN BACKGROUNDED with `&` —
325
+ // `transform(sleep 3 & echo …)` froze fzf for 3s, the redirected form was
326
+ // instantly responsive.
327
+ `${spec.cancelCmd} --port "$FZF_PORT" >/dev/null 2>&1`,
328
+ `echo "${actions}"`,
329
+ "else",
330
+ "echo abort",
331
+ "fi",
332
+ ].join("\n");
333
+ }
334
+ /**
335
+ * The enter transform body.
336
+ *
337
+ * **Enter means two things, and that is the sharpest edge in this design.** In
338
+ * browse mode it resumes a session, replacing your terminal. In ask mode it
339
+ * sends. A misfire is not cosmetic: enter that resumes when you meant send drops
340
+ * you into someone else's harness and the picker is gone. That is why the prompt
341
+ * changes, why the header changes, and why the oracle is fzf's own state rather
342
+ * than a file that can go stale.
343
+ *
344
+ * **`rebind` cannot give enter a new meaning** — it only restores a binding after
345
+ * `unbind` — so enter is bound ONCE, to a transform that branches.
346
+ *
347
+ * `--port "$FZF_PORT"`, `--focus {1}` and `--question "$FZF_QUERY"` are appended
348
+ * HERE rather than built into `sendCmd`, and never routed through `shellQuote`:
349
+ * its allowed class is `/^[A-Za-z0-9_./:@-]+$/`, so `$FZF_PORT` would be
350
+ * single-quoted and the child would receive the literal string — every
351
+ * `refresh-preview` would then silently miss.
352
+ *
353
+ * `{1}`, not `$FZF_CURRENT_ITEM`: the latter is 0.73.0, and on that exact version
354
+ * a NUL-containing item does not degrade gracefully — it breaks the preview and
355
+ * every other child command outright (fixed in 0.73.1). We use `--read0`.
356
+ * `{1}` is also what makes the focus model free: fzf re-substitutes it every time
357
+ * the binding fires, so this is already "the focus at send time", with no state
358
+ * and no race.
359
+ */
360
+ export function sendActions(spec) {
361
+ return [
362
+ `if [ "$FZF_INPUT_STATE" = disabled ]; then`,
363
+ // Otherwise enter on an empty ask line sends a blank question.
364
+ `if [ -n "$FZF_QUERY" ]; then`,
365
+ `${spec.sendCmd} --port "$FZF_PORT" --focus {1} --question "$FZF_QUERY" >/dev/null 2>&1`,
366
+ "fi",
367
+ `echo "clear-query"`,
368
+ "else",
369
+ "echo accept",
370
+ "fi",
371
+ ].join("\n");
372
+ }
373
+ /**
374
+ * The three bindings the mode toggle is made of.
375
+ *
376
+ * `transform:` and not `transform(…)`: the colon form takes the rest of the
377
+ * argument, and every body below contains parentheses.
378
+ *
379
+ * **Mode is not stored anywhere.** fzf already tracks it, and a mode file would
380
+ * be a second source of truth that can disagree with the first.
381
+ */
382
+ export function chatBindings(spec) {
383
+ return [
384
+ `--bind=ctrl-o:transform:${enterAskActions(spec)}`,
385
+ `--bind=enter:transform:${sendActions(spec)}`,
386
+ `--bind=esc:transform:${exitAskActions(spec)}`,
387
+ ];
388
+ }
389
+ /**
390
+ * fzf's environment.
391
+ *
392
+ * **`FZF_DEFAULT_OPTS` is stripped, and that is a correctness fix rather than
393
+ * hygiene.** fzf reads it from the environment, and picker.ts used to spawn with
394
+ * no `env` at all — so a user with `FZF_DEFAULT_OPTS=--disabled` handed us a
395
+ * picker whose `$FZF_INPUT_STATE` is `disabled` at the very first frame: the
396
+ * bindings believe they are already in ask mode, enter never resumes, and ctrl-o
397
+ * cannot get you back. gmux builds its full arg set anyway, and a user `--bind`
398
+ * colliding with ours is the same class of problem.
399
+ *
400
+ * **The api key rides here and NOWHERE else.** `--listen` is an
401
+ * arbitrary-command-execution surface — verified against a plain localhost
402
+ * `--listen` on 0.74, `POST execute-silent(touch pwned)` returned HTTP 200 and
403
+ * created the file — and `FZF_API_KEY` turns an unauthenticated POST into a 401.
404
+ * It must never reach an argv: measured, `ps -ww -o args=` prints another user's
405
+ * argv, while `ps e` on their environment needs their uid. So argv is strictly
406
+ * worse than the env here, which is the opposite of the usual instinct. Honestly:
407
+ * this raises the bar against a different-user or non-local attacker and does
408
+ * NOT stop a same-uid one, who can read fzf's environment and POST as us. The
409
+ * only real boundary there is a unix socket, whose 0.66.0 floor is out of reach
410
+ * under a 0.59 gate. Known and accepted.
411
+ */
412
+ export function fzfSpawnEnv(env = process.env, apiKey = null) {
413
+ const clean = { ...env };
414
+ delete clean["FZF_DEFAULT_OPTS"];
415
+ delete clean["FZF_DEFAULT_OPTS_FILE"];
416
+ if (apiKey)
417
+ clean["FZF_API_KEY"] = apiKey;
418
+ return clean;
419
+ }
420
+ /** 32 random bytes, minted per picker run. Never on an argv — see `fzfSpawnEnv`. */
421
+ function newApiKey() {
422
+ return randomBytes(32).toString("base64");
423
+ }
424
+ /**
425
+ * Everything we hand fzf on the command line.
426
+ *
427
+ * Split out from the spawn so it is testable: pressing a key needs a terminal,
428
+ * but the args that decide what the key *does* are just data.
429
+ */
430
+ export function fzfArgs(spec) {
431
+ const { multiline, preview, reloadCmd, tier } = spec;
432
+ // **A half-bound ask mode must never ship.** `split` with no `chat` has no
433
+ // transcript to write and no commands to run, so enter would send into the void
434
+ // and esc could not get you out — strictly worse than the REPL it replaced.
435
+ // Fall back to the whole browse-only arg set instead, the same null-guard
436
+ // `reloadCommand` takes.
437
+ const chat = tier === "split" ? spec.chat : undefined;
438
+ // The tiers with no ctrl-o inside fzf must not get one however `askCmd` was
439
+ // built. Half a binding is not a degraded picker, it is a broken one.
440
+ const askCmd = tier === "execute" ? spec.askCmd : null;
441
+ // A key that does nothing is worse than a key that isn't there, so the header
442
+ // advertises exactly what got bound.
443
+ const keys = [
444
+ "enter: resume",
445
+ reloadCmd ? "ctrl-r: refresh" : "",
446
+ chat || askCmd ? "ctrl-o: ask" : "",
447
+ "ctrl-c: cancel",
448
+ ]
449
+ .filter((k) => k !== "")
450
+ .join(" ");
451
+ const browseHeader = headerFor([keys]);
452
+ const args = [
453
+ "--ansi",
454
+ "--delimiter=\t",
455
+ "--with-nth=2..",
456
+ "--height=90%",
457
+ "--layout=reverse",
458
+ "--border",
459
+ "--prompt=session > ",
460
+ "--preview",
461
+ preview,
462
+ "--preview-window=right,55%,wrap",
463
+ "--header",
464
+ browseHeader,
465
+ ];
466
+ // ctrl-r replaces the list with a fresh one, and kicks off summaries for
467
+ // whatever needs them. `reload` feeds on the command's stdout, so the binding
468
+ // is just "print the records again" — see commands/picker-rows.ts.
469
+ if (reloadCmd)
470
+ args.push(`--bind=ctrl-r:reload(${reloadCmd})`);
471
+ // ctrl-o, not shift-f: fzf's query line eats plain letters, so `F` types an F
472
+ // rather than firing a binding. alt-a — the obvious "ask" mnemonic — is worse
473
+ // than useless on macOS, where Terminal and iTerm2 both send an accented
474
+ // character on Option by default. ctrl-s/ctrl-q are flow control. ctrl-o is
475
+ // unbound in fzf and safe everywhere.
476
+ //
477
+ // `execute` suspends fzf and hands the child the terminal, restoring the list
478
+ // when it exits — so you can ask, read, and be back in the picker with your
479
+ // query and position intact.
480
+ if (askCmd)
481
+ args.push(`--bind=ctrl-o:execute(${askCmd})`);
482
+ // The split tier: ctrl-o becomes a MODE, not a launch. The list stays, and the
483
+ // answer arrives under the card while you keep arrowing around.
484
+ if (chat) {
485
+ args.push(
486
+ // fzf runs children with `$SHELL -c`. Under `SHELL=/bin/dash` a bash-only
487
+ // body makes ctrl-o a dead key; under `SHELL=/bin/tcsh` the enter transform
488
+ // emits nothing, a transform that emits nothing is a no-op, and enter stops
489
+ // resuming sessions AT ALL — the picker is bricked for csh users, by a
490
+ // regression we would have introduced. `--with-shell` is the only fix that
491
+ // covers every login shell, and at 0.51.0 it is free under a 0.59 floor.
492
+ "--with-shell", "sh -c",
493
+ // The answer arrives with no keypress, and `refresh-preview` over the listen
494
+ // port is the only thing that can deliver it. No argument: fzf picks the
495
+ // port and exports `$FZF_PORT` to its children, so nothing in gmux needs to
496
+ // know it. It is also an ACE surface — see `fzfSpawnEnv` for the key.
497
+ "--listen", ...chatBindings({ ...chat, browseHeader, askHeader: headerFor(ASK_KEYS) }));
498
+ }
499
+ if (multiline) {
500
+ // Items are NUL-delimited, so a record may contain newlines; --print0 keeps
501
+ // the selection unambiguous on the way back out.
502
+ args.push("--read0", "--print0", "--highlight-line");
503
+ }
504
+ return args;
505
+ }
506
+ async function pickWithFzf(views, options = {}) {
507
+ const version = fzfVersion();
508
+ const multiline = supportsMultiline(version);
509
+ const records = buildFzfRecords(views, multiline, listWidth(), new Date(), options.inProgress);
510
+ // `askArgs` is the picker's only word on whether ask would answer — it is set
511
+ // exactly when the caller found a provider — which is what keeps this file
512
+ // knowing nothing about providers.
513
+ const tier = askTier({
514
+ hasFzf: true,
515
+ fzfVersion: version,
516
+ askAvailable: (options.askArgs?.length ?? 0) > 0,
517
+ selfCommand: selfCommandHere(),
518
+ });
519
+ // The caller may hand us a chat at any version; only this tier can render one.
520
+ const chat = tier === "split" ? options.chat : undefined;
521
+ const args = fzfArgs({
522
+ multiline,
523
+ preview: previewCommand(chat?.transcript),
524
+ reloadCmd: reloadCommand(options.reloadArgs),
525
+ askCmd: askCommand(options.askArgs),
526
+ tier,
527
+ ...(chat ? { chat } : {}),
528
+ });
529
+ // Only the chat tier opens a port, so only it mints a key.
530
+ const apiKey = chat ? newApiKey() : null;
531
+ // `finally` covers every way the picker ends on its own, INCLUDING ctrl-c
532
+ // inside fzf: fzf exits, the promise resolves, we clean up. The signal handlers
533
+ // cover the other case — the shell killing `gmux` — and are registered only when
534
+ // there is something to close, so a picker with no chat keeps today's exact
535
+ // signal behaviour (no handler, no survival, no change).
536
+ let closed = false;
537
+ const cleanup = async () => {
538
+ if (closed)
539
+ return; // `finally` and a signal can both get here.
540
+ closed = true;
541
+ await options.onClose?.();
542
+ };
543
+ const onSignal = () => {
544
+ void cleanup().finally(() => process.exit(130));
545
+ };
546
+ const signals = ["SIGINT", "SIGTERM", "SIGHUP"];
547
+ if (options.onClose)
548
+ for (const signal of signals)
549
+ process.on(signal, onSignal);
550
+ try {
551
+ const selected = await new Promise((resolve) => {
552
+ const child = spawn("fzf", args, {
553
+ stdio: ["pipe", "pipe", "inherit"],
554
+ // NOT the inherited environment: a user's `FZF_DEFAULT_OPTS=--disabled`
555
+ // would brick the mode oracle before the first frame. See `fzfSpawnEnv`.
556
+ env: fzfSpawnEnv(process.env, apiKey),
557
+ });
558
+ let stdout = "";
559
+ child.stdout.on("data", (chunk) => (stdout += String(chunk)));
560
+ child.on("error", () => resolve(null));
561
+ child.on("close", () => {
562
+ const picked = stdout.replace(/\0+$/, "").trim();
563
+ resolve(picked === "" ? null : picked);
564
+ });
565
+ child.stdin.write(records);
566
+ child.stdin.end();
567
+ });
568
+ if (!selected)
569
+ return null;
570
+ const id = selected.split("\t")[0].trim();
571
+ // NOT a map built at open: ctrl-r may have introduced this session since.
572
+ return await resolvePicked(id, views, options.resolve);
573
+ }
574
+ finally {
575
+ if (options.onClose)
576
+ for (const signal of signals)
577
+ process.off(signal, onSignal);
578
+ await cleanup();
579
+ }
580
+ }
581
+ /**
582
+ * The no-fzf fallback: a numbered list at a readline prompt.
583
+ *
584
+ * Control keys are not interceptable here, so the bindings are spelled as
585
+ * letters — `r` for refresh, `a` for ask — the way a numbered prompt can
586
+ * express them.
587
+ */
588
+ async function pickWithPrompt(views, options = {}) {
589
+ // Wrap here too: the numbered fallback is a list you have to read, so chopping
590
+ // the description defeats the point just as badly as it does in fzf.
591
+ const width = Math.max(40, terminalWidth() - 5);
592
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
593
+ const { reload, ask } = options;
594
+ let current = views;
595
+ let inProgress = options.inProgress;
596
+ try {
597
+ for (;;) {
598
+ const shown = current.slice(0, 30);
599
+ for (const [i, view] of shown.entries()) {
600
+ const [first = "", ...rest] = formatRowLines(view, new Date(), width, inProgress);
601
+ process.stdout.write(`${String(i + 1).padStart(3)}. ${first}\n`);
602
+ for (const line of rest)
603
+ process.stdout.write(` ${line}\n`);
604
+ }
605
+ // The same static key fzf gets. This path re-renders on `r` and could
606
+ // afford `formatLegend`'s counts, but "the picker's key" should not read
607
+ // differently depending on what happens to be on your PATH.
608
+ process.stdout.write(`\n${formatMarkerKey()}\n`);
609
+ process.stdout.write("\n(install fzf for fuzzy search and previews: brew install fzf)\n");
610
+ const hint = [
611
+ "number",
612
+ reload ? "r to refresh" : "",
613
+ ask ? "a to ask" : "",
614
+ "or blank to cancel",
615
+ ]
616
+ .filter((part) => part !== "")
617
+ .join(", ");
618
+ const answer = (await rl.question(`\nresume which? [${hint}] `)).trim();
619
+ if (reload && answer.toLowerCase() === "r") {
620
+ ({ views: current, inProgress } = await reload());
621
+ process.stdout.write("\n");
622
+ continue;
623
+ }
624
+ if (ask && answer.toLowerCase() === "a") {
625
+ // The readline interface is ours and holds stdin; the chat layer opens
626
+ // its own. Close first or the two race for every keystroke and the
627
+ // conversation eats the picker's input.
628
+ rl.close();
629
+ await ask();
630
+ return pickWithPrompt(current, { ...options, ...(inProgress ? { inProgress } : {}) });
631
+ }
632
+ const choice = Number.parseInt(answer, 10);
633
+ if (!Number.isFinite(choice) || choice < 1 || choice > shown.length)
634
+ return null;
635
+ return shown[choice - 1] ?? null;
636
+ }
637
+ }
638
+ finally {
639
+ rl.close();
640
+ }
641
+ }
642
+ //# sourceMappingURL=picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picker.js","sourceRoot":"","sources":["../../src/cli/picker.ts"],"names":[],"mappings":"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"}