@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.
- package/CHANGELOG.md +654 -0
- package/LICENSE +21 -0
- package/README.md +351 -0
- package/dist/adapters/claude-code.d.ts +52 -0
- package/dist/adapters/claude-code.js +315 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/codex.d.ts +39 -0
- package/dist/adapters/codex.js +233 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/jsonl.d.ts +40 -0
- package/dist/adapters/jsonl.js +92 -0
- package/dist/adapters/jsonl.js.map +1 -0
- package/dist/adapters/registry.d.ts +11 -0
- package/dist/adapters/registry.js +21 -0
- package/dist/adapters/registry.js.map +1 -0
- package/dist/adapters/types.d.ts +43 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/cli/border-client.d.ts +8 -0
- package/dist/cli/border-client.js +11 -0
- package/dist/cli/border-client.js.map +1 -0
- package/dist/cli/commands/__ask-cancel.d.ts +35 -0
- package/dist/cli/commands/__ask-cancel.js +91 -0
- package/dist/cli/commands/__ask-cancel.js.map +1 -0
- package/dist/cli/commands/__ask-refresh.d.ts +40 -0
- package/dist/cli/commands/__ask-refresh.js +54 -0
- package/dist/cli/commands/__ask-refresh.js.map +1 -0
- package/dist/cli/commands/__ask-run.d.ts +43 -0
- package/dist/cli/commands/__ask-run.js +126 -0
- package/dist/cli/commands/__ask-run.js.map +1 -0
- package/dist/cli/commands/__ask-send.d.ts +50 -0
- package/dist/cli/commands/__ask-send.js +138 -0
- package/dist/cli/commands/__ask-send.js.map +1 -0
- package/dist/cli/commands/__preview-card.d.ts +31 -0
- package/dist/cli/commands/__preview-card.js +72 -0
- package/dist/cli/commands/__preview-card.js.map +1 -0
- package/dist/cli/commands/ask.d.ts +50 -0
- package/dist/cli/commands/ask.js +240 -0
- package/dist/cli/commands/ask.js.map +1 -0
- package/dist/cli/commands/auto.d.ts +12 -0
- package/dist/cli/commands/auto.js +28 -0
- package/dist/cli/commands/auto.js.map +1 -0
- package/dist/cli/commands/cockpit.d.ts +14 -0
- package/dist/cli/commands/cockpit.js +52 -0
- package/dist/cli/commands/cockpit.js.map +1 -0
- package/dist/cli/commands/daemon.d.ts +75 -0
- package/dist/cli/commands/daemon.js +258 -0
- package/dist/cli/commands/daemon.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +6 -0
- package/dist/cli/commands/doctor.js +159 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/grep.d.ts +2 -0
- package/dist/cli/commands/grep.js +52 -0
- package/dist/cli/commands/grep.js.map +1 -0
- package/dist/cli/commands/index-cmd.d.ts +2 -0
- package/dist/cli/commands/index-cmd.js +29 -0
- package/dist/cli/commands/index-cmd.js.map +1 -0
- package/dist/cli/commands/ls.d.ts +30 -0
- package/dist/cli/commands/ls.js +95 -0
- package/dist/cli/commands/ls.js.map +1 -0
- package/dist/cli/commands/overlay.d.ts +26 -0
- package/dist/cli/commands/overlay.js +216 -0
- package/dist/cli/commands/overlay.js.map +1 -0
- package/dist/cli/commands/pick.d.ts +59 -0
- package/dist/cli/commands/pick.js +254 -0
- package/dist/cli/commands/pick.js.map +1 -0
- package/dist/cli/commands/picker-rows.d.ts +17 -0
- package/dist/cli/commands/picker-rows.js +47 -0
- package/dist/cli/commands/picker-rows.js.map +1 -0
- package/dist/cli/commands/resume.d.ts +25 -0
- package/dist/cli/commands/resume.js +88 -0
- package/dist/cli/commands/resume.js.map +1 -0
- package/dist/cli/commands/run.d.ts +13 -0
- package/dist/cli/commands/run.js +78 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +37 -0
- package/dist/cli/commands/setup.js +200 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/show.d.ts +2 -0
- package/dist/cli/commands/show.js +24 -0
- package/dist/cli/commands/show.js.map +1 -0
- package/dist/cli/commands/summarize.d.ts +2 -0
- package/dist/cli/commands/summarize.js +59 -0
- package/dist/cli/commands/summarize.js.map +1 -0
- package/dist/cli/commands/tmux.d.ts +11 -0
- package/dist/cli/commands/tmux.js +90 -0
- package/dist/cli/commands/tmux.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +2 -0
- package/dist/cli/commands/watch.js +76 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/format.d.ts +74 -0
- package/dist/cli/format.js +242 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/gmux-render.d.ts +11 -0
- package/dist/cli/gmux-render.js +60 -0
- package/dist/cli/gmux-render.js.map +1 -0
- package/dist/cli/main.d.ts +8 -0
- package/dist/cli/main.js +145 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/overlay-ask.d.ts +13 -0
- package/dist/cli/overlay-ask.js +32 -0
- package/dist/cli/overlay-ask.js.map +1 -0
- package/dist/cli/overlay.d.ts +26 -0
- package/dist/cli/overlay.js +149 -0
- package/dist/cli/overlay.js.map +1 -0
- package/dist/cli/picker.d.ts +308 -0
- package/dist/cli/picker.js +642 -0
- package/dist/cli/picker.js.map +1 -0
- package/dist/cli/preview.d.ts +87 -0
- package/dist/cli/preview.js +292 -0
- package/dist/cli/preview.js.map +1 -0
- package/dist/cli/tmux-label.d.ts +50 -0
- package/dist/cli/tmux-label.js +146 -0
- package/dist/cli/tmux-label.js.map +1 -0
- package/dist/core/errors.d.ts +54 -0
- package/dist/core/errors.js +91 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/fingerprint.d.ts +21 -0
- package/dist/core/fingerprint.js +59 -0
- package/dist/core/fingerprint.js.map +1 -0
- package/dist/core/gmux-types.d.ts +102 -0
- package/dist/core/gmux-types.js +13 -0
- package/dist/core/gmux-types.js.map +1 -0
- package/dist/core/pane-state.d.ts +5 -0
- package/dist/core/pane-state.js +15 -0
- package/dist/core/pane-state.js.map +1 -0
- package/dist/core/paths.d.ts +68 -0
- package/dist/core/paths.js +106 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/proc-tree.d.ts +9 -0
- package/dist/core/proc-tree.js +33 -0
- package/dist/core/proc-tree.js.map +1 -0
- package/dist/core/text.d.ts +34 -0
- package/dist/core/text.js +126 -0
- package/dist/core/text.js.map +1 -0
- package/dist/core/types.d.ts +322 -0
- package/dist/core/types.js +10 -0
- package/dist/core/types.js.map +1 -0
- package/dist/services/ask-transcript.d.ts +256 -0
- package/dist/services/ask-transcript.js +544 -0
- package/dist/services/ask-transcript.js.map +1 -0
- package/dist/services/ask.d.ts +54 -0
- package/dist/services/ask.js +161 -0
- package/dist/services/ask.js.map +1 -0
- package/dist/services/auto-summarize.d.ts +188 -0
- package/dist/services/auto-summarize.js +415 -0
- package/dist/services/auto-summarize.js.map +1 -0
- package/dist/services/concurrency.d.ts +2 -0
- package/dist/services/concurrency.js +16 -0
- package/dist/services/concurrency.js.map +1 -0
- package/dist/services/config.d.ts +131 -0
- package/dist/services/config.js +325 -0
- package/dist/services/config.js.map +1 -0
- package/dist/services/daemon-client.d.ts +9 -0
- package/dist/services/daemon-client.js +34 -0
- package/dist/services/daemon-client.js.map +1 -0
- package/dist/services/daemon-socket.d.ts +30 -0
- package/dist/services/daemon-socket.js +76 -0
- package/dist/services/daemon-socket.js.map +1 -0
- package/dist/services/daemon.d.ts +43 -0
- package/dist/services/daemon.js +106 -0
- package/dist/services/daemon.js.map +1 -0
- package/dist/services/distill.d.ts +39 -0
- package/dist/services/distill.js +93 -0
- package/dist/services/distill.js.map +1 -0
- package/dist/services/guardian.d.ts +26 -0
- package/dist/services/guardian.js +71 -0
- package/dist/services/guardian.js.map +1 -0
- package/dist/services/index-store.d.ts +36 -0
- package/dist/services/index-store.js +125 -0
- package/dist/services/index-store.js.map +1 -0
- package/dist/services/log-rotation.d.ts +3 -0
- package/dist/services/log-rotation.js +28 -0
- package/dist/services/log-rotation.js.map +1 -0
- package/dist/services/pane-links.d.ts +10 -0
- package/dist/services/pane-links.js +47 -0
- package/dist/services/pane-links.js.map +1 -0
- package/dist/services/pane-process.d.ts +95 -0
- package/dist/services/pane-process.js +183 -0
- package/dist/services/pane-process.js.map +1 -0
- package/dist/services/pane-registry.d.ts +24 -0
- package/dist/services/pane-registry.js +40 -0
- package/dist/services/pane-registry.js.map +1 -0
- package/dist/services/provider-process.d.ts +37 -0
- package/dist/services/provider-process.js +105 -0
- package/dist/services/provider-process.js.map +1 -0
- package/dist/services/providers.d.ts +76 -0
- package/dist/services/providers.js +104 -0
- package/dist/services/providers.js.map +1 -0
- package/dist/services/resolve.d.ts +3 -0
- package/dist/services/resolve.js +18 -0
- package/dist/services/resolve.js.map +1 -0
- package/dist/services/resources.d.ts +17 -0
- package/dist/services/resources.js +113 -0
- package/dist/services/resources.js.map +1 -0
- package/dist/services/search.d.ts +29 -0
- package/dist/services/search.js +135 -0
- package/dist/services/search.js.map +1 -0
- package/dist/services/semantic-gate.d.ts +13 -0
- package/dist/services/semantic-gate.js +23 -0
- package/dist/services/semantic-gate.js.map +1 -0
- package/dist/services/semantic.d.ts +113 -0
- package/dist/services/semantic.js +216 -0
- package/dist/services/semantic.js.map +1 -0
- package/dist/services/sensors.d.ts +92 -0
- package/dist/services/sensors.js +246 -0
- package/dist/services/sensors.js.map +1 -0
- package/dist/services/summarize.d.ts +84 -0
- package/dist/services/summarize.js +230 -0
- package/dist/services/summarize.js.map +1 -0
- package/dist/services/tmux-gateway.d.ts +17 -0
- package/dist/services/tmux-gateway.js +10 -0
- package/dist/services/tmux-gateway.js.map +1 -0
- package/dist/services/tmux-resolve.d.ts +54 -0
- package/dist/services/tmux-resolve.js +0 -0
- package/dist/services/tmux-resolve.js.map +1 -0
- package/dist/services/tmux.d.ts +32 -0
- package/dist/services/tmux.js +107 -0
- package/dist/services/tmux.js.map +1 -0
- package/dist/services/views.d.ts +7 -0
- package/dist/services/views.js +18 -0
- package/dist/services/views.js.map +1 -0
- package/dist/services/watch.d.ts +36 -0
- package/dist/services/watch.js +98 -0
- package/dist/services/watch.js.map +1 -0
- package/dist/services/workspace.d.ts +19 -0
- package/dist/services/workspace.js +88 -0
- package/dist/services/workspace.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { rm } from "node:fs/promises";
|
|
2
|
+
import { shellQuote } from "../../core/text.js";
|
|
3
|
+
import { askBrowseQueryPath, askLockPath, newAskTranscriptPath, readAskLock, sweepAskTranscripts, } from "../../services/ask-transcript.js";
|
|
4
|
+
import { inProgressIds, isLockStale, maybeAutoSummarize } from "../../services/auto-summarize.js";
|
|
5
|
+
import { loadViews } from "../../services/views.js";
|
|
6
|
+
import { listWidth, pickSession, selfCommandHere } from "../picker.js";
|
|
7
|
+
import { dim } from "../format.js";
|
|
8
|
+
import { ASK_CANCEL_COMMAND } from "./__ask-cancel.js";
|
|
9
|
+
import { ASK_SEND_COMMAND } from "./__ask-send.js";
|
|
10
|
+
import { askAboutSessions, askIsAvailable } from "./ask.js";
|
|
11
|
+
import { resumeInNewWindow, resumeSession } from "./resume.js";
|
|
12
|
+
import { autoSummarizeRequested, toFilters } from "./ls.js";
|
|
13
|
+
/** The hidden command fzf's ctrl-r binding runs. Not a thing a person runs. */
|
|
14
|
+
export const PICKER_ROWS_COMMAND = "__picker-rows";
|
|
15
|
+
/**
|
|
16
|
+
* The filter flags this picker was opened with, as argv.
|
|
17
|
+
*
|
|
18
|
+
* One copy, because every command the picker spawns must describe the *same*
|
|
19
|
+
* window. A filter that drifts in one of several copies is the silent
|
|
20
|
+
* wrong-window bug the `pickerAskArgs` comment below exists to warn about —
|
|
21
|
+
* nothing errors, the answers are just about other sessions.
|
|
22
|
+
*
|
|
23
|
+
* Values are NOT quoted here — the caller joins and quotes, because argv and a
|
|
24
|
+
* shell command string want different escaping.
|
|
25
|
+
*/
|
|
26
|
+
export function filterArgs(options) {
|
|
27
|
+
const args = [];
|
|
28
|
+
if (options.harness)
|
|
29
|
+
args.push("--harness", options.harness);
|
|
30
|
+
if (options.project)
|
|
31
|
+
args.push("-p", options.project);
|
|
32
|
+
if (options.branch)
|
|
33
|
+
args.push("-b", options.branch);
|
|
34
|
+
if (options.since)
|
|
35
|
+
args.push("-s", options.since);
|
|
36
|
+
if (options.limit)
|
|
37
|
+
args.push("-n", options.limit);
|
|
38
|
+
if (options.includeSidechains === true)
|
|
39
|
+
args.push("--include-sidechains");
|
|
40
|
+
if (options.includeAutomated === true)
|
|
41
|
+
args.push("--include-automated");
|
|
42
|
+
return args;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The argv behind ctrl-o, reproducing this picker's filter set for `gmux ask`.
|
|
46
|
+
*
|
|
47
|
+
* Pure, and separate from `pickerReloadArgs` only because the two target
|
|
48
|
+
* different commands — they carry the same filters for the same reason.
|
|
49
|
+
*
|
|
50
|
+
* THE FILTERS ARE THE POINT. `gmux ask` builds its own window; left to its
|
|
51
|
+
* defaults it takes the 20 most recent sessions across every project, which for
|
|
52
|
+
* `gmux pick -p webshop` (or any pick past the 20th row) does not contain the
|
|
53
|
+
* session you are highlighting. `--focus` then finds nothing, resolves to null,
|
|
54
|
+
* and the chat answers about sessions you were not looking at — with no sign
|
|
55
|
+
* anything went wrong.
|
|
56
|
+
*
|
|
57
|
+
* `-n` is forwarded too: the window ask reasons over should be the list you are
|
|
58
|
+
* looking at, not a shorter one it chose for itself.
|
|
59
|
+
*
|
|
60
|
+
* `--focus {1}` is NOT added here. fzf substitutes that token, so it is appended
|
|
61
|
+
* unquoted by the picker; a shell-quoted `{1}` would arrive as a literal.
|
|
62
|
+
*/
|
|
63
|
+
export function pickerAskArgs(options) {
|
|
64
|
+
return ["ask", ...filterArgs(options)];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The argv that reproduces this picker's filter set, for fzf's reload binding.
|
|
68
|
+
*
|
|
69
|
+
* Pure, so the thing a refresh actually runs is testable without spawning fzf.
|
|
70
|
+
*
|
|
71
|
+
* `--width` is passed explicitly: the reload child's stdout is a pipe, so it
|
|
72
|
+
* cannot measure the terminal and would fall back to a default width, reflowing
|
|
73
|
+
* every row on refresh. Only the parent, inside fzf, knows the real width.
|
|
74
|
+
*/
|
|
75
|
+
export function pickerReloadArgs(options, width, autoSummarize = true) {
|
|
76
|
+
const args = [PICKER_ROWS_COMMAND, "--width", String(width), ...filterArgs(options)];
|
|
77
|
+
// The opt-out MUST cross the process boundary. ctrl-r forces a pass — it
|
|
78
|
+
// bypasses the cooldown — so a dropped flag here would spend tokens the user
|
|
79
|
+
// explicitly declined, with the one thing that might have throttled it
|
|
80
|
+
// removed. Commander reads a root option after the subcommand name fine.
|
|
81
|
+
if (!autoSummarize)
|
|
82
|
+
args.push("--no-auto-summarize");
|
|
83
|
+
return args;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The chat pane's shell commands, or undefined when it cannot be offered.
|
|
87
|
+
*
|
|
88
|
+
* **Built here and not in the picker**, which is the same call `askArgs` already
|
|
89
|
+
* makes: opaque strings in, shell commands out. `pick.ts` owns the provider
|
|
90
|
+
* question (`askIsAvailable`) and the transcript path, so it owns everything the
|
|
91
|
+
* picker would otherwise have to learn — and the picker's import list stays free
|
|
92
|
+
* of `node:fs`, of the lock's shape, and of a provider.
|
|
93
|
+
*
|
|
94
|
+
* **The path is allocated and NOTHING is created.** It has to exist as a string
|
|
95
|
+
* before fzf starts, because it is baked into the preview command; the first
|
|
96
|
+
* `__ask-send` creates the file as a side effect of opening it for append. A run
|
|
97
|
+
* where nobody presses ctrl-o therefore never touches the disk, and a missing
|
|
98
|
+
* file is exactly the empty state.
|
|
99
|
+
*
|
|
100
|
+
* `--port`, `--focus` and `--question` are NOT here: fzf substitutes `{1}` and
|
|
101
|
+
* expands `$FZF_PORT`/`$FZF_QUERY`, and `shellQuote`'s allowed class contains
|
|
102
|
+
* neither `$` nor `{`, so all three would arrive at the child as literal strings.
|
|
103
|
+
* The picker appends them unquoted, after these.
|
|
104
|
+
*/
|
|
105
|
+
function pickerChatSpec(options, transcript) {
|
|
106
|
+
const self = selfCommandHere();
|
|
107
|
+
if (!self)
|
|
108
|
+
return undefined;
|
|
109
|
+
const command = (name, args) => `${self} ${[name, "--transcript", transcript, ...args].map(shellQuote).join(" ")}`;
|
|
110
|
+
return {
|
|
111
|
+
transcript,
|
|
112
|
+
// THE FILTERS ARE THE POINT, for the reason `pickerAskArgs` records: the
|
|
113
|
+
// worker builds its own window, and a window built from defaults does not
|
|
114
|
+
// contain the session you are pointing at — `--focus` then resolves to null
|
|
115
|
+
// and the chat answers about a list you never asked about, looking normal the
|
|
116
|
+
// whole time. Baked in at picker start, exactly as ctrl-r's are.
|
|
117
|
+
sendCmd: command(ASK_SEND_COMMAND, filterArgs(options)),
|
|
118
|
+
cancelCmd: command(ASK_CANCEL_COMMAND, []),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Everything the thread leaves on disk, gone when the picker is.
|
|
123
|
+
*
|
|
124
|
+
* **The group kill is here and not only in `__ask-cancel`** because accept and
|
|
125
|
+
* abort never run the esc binding: quit the picker mid-answer and `claude -p`
|
|
126
|
+
* would otherwise keep running, keep billing, and keep writing into a transcript
|
|
127
|
+
* nobody will ever read. Measured — `kill -TERM <worker>` leaves the provider
|
|
128
|
+
* orphaned and alive; only the group dies together.
|
|
129
|
+
*
|
|
130
|
+
* Never throws. A cleanup that fails must not become the way `gmux pick` reports
|
|
131
|
+
* that you picked a session.
|
|
132
|
+
*/
|
|
133
|
+
function closeChatThread(transcript) {
|
|
134
|
+
return async () => {
|
|
135
|
+
try {
|
|
136
|
+
const lock = await readAskLock(transcript);
|
|
137
|
+
// Liveness ANDed with age, exactly as `isLockStale` already does — a stale
|
|
138
|
+
// lock's pid is either dead or recycled into some innocent process, and
|
|
139
|
+
// signalling a stranger's group is the worst thing on this path.
|
|
140
|
+
if (lock && lock.pid > 0 && !isLockStale(lock, new Date())) {
|
|
141
|
+
try {
|
|
142
|
+
process.kill(-lock.pid, "SIGTERM");
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// ESRCH: it finished on its own. Nothing to reap.
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
await rm(transcript, { force: true });
|
|
149
|
+
await rm(askLockPath(transcript), { force: true });
|
|
150
|
+
await rm(askBrowseQueryPath(transcript), { force: true });
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// An orphan is a few KB of disposable cache and the sweep will get it.
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Load the list and start summaries for whatever needs them.
|
|
159
|
+
*
|
|
160
|
+
* Both the initial paint and a refresh go through here, so `r` in the numbered
|
|
161
|
+
* fallback does what ctrl-r does in fzf rather than only re-rendering stale
|
|
162
|
+
* rows. `force` is set for a refresh: a keypress is an explicit request.
|
|
163
|
+
*/
|
|
164
|
+
async function refresh(options, enabled, force, notify) {
|
|
165
|
+
const views = await loadViews(toFilters(options, 50));
|
|
166
|
+
const started = await maybeAutoSummarize({
|
|
167
|
+
records: views.map((v) => v.record),
|
|
168
|
+
enabled,
|
|
169
|
+
force,
|
|
170
|
+
...(notify ? { notify } : {}),
|
|
171
|
+
});
|
|
172
|
+
return { views, inProgress: new Set([...(await inProgressIds()), ...started.targetIds]) };
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The bare `gmux` command: pick a recent session, then resume it.
|
|
176
|
+
* This is the whole point of the tool — everything else is in service of it.
|
|
177
|
+
*
|
|
178
|
+
* Registered as commander's *default* command rather than as options on the root
|
|
179
|
+
* program. Hanging `-n`/`-p` off the root would shadow the identically-named
|
|
180
|
+
* flags on `gmux ls`, so `gmux ls -n 8` would silently ignore the 8.
|
|
181
|
+
*/
|
|
182
|
+
export function registerPick(program) {
|
|
183
|
+
program
|
|
184
|
+
.command("pick", { isDefault: true })
|
|
185
|
+
.description("pick a recent session and resume it (this is what bare `gmux` does)")
|
|
186
|
+
.option("--harness <id>", "only this harness")
|
|
187
|
+
.option("-p, --project <name>", "only sessions whose project matches")
|
|
188
|
+
.option("-b, --branch <name>", "only sessions whose git branch matches")
|
|
189
|
+
.option("-s, --since <when>", "only sessions newer than this (3d, 12h, 2w)")
|
|
190
|
+
.option("-n, --limit <count>", "how many sessions to offer", "50")
|
|
191
|
+
.option("--include-sidechains", "include subagent transcripts")
|
|
192
|
+
.option("--include-automated", "include non-interactive runs (claude -p, codex exec)")
|
|
193
|
+
.option("--resume-in-window", "resume the choice in a new tmux window (used by the tmux ctrl-shift-g binding)")
|
|
194
|
+
.action(async (options, command) => {
|
|
195
|
+
const enabled = autoSummarizeRequested(command);
|
|
196
|
+
// Kick the pass off over the sessions we are about to offer, exactly as
|
|
197
|
+
// `ls` does — the postAction hook cannot serve the picker, because our
|
|
198
|
+
// action ends in `resumeSession`, which waits on your harness. That hook
|
|
199
|
+
// fires when you quit Claude Code, not when the list is drawn.
|
|
200
|
+
//
|
|
201
|
+
// The notice goes to stderr, which fzf does not capture, so it prints
|
|
202
|
+
// before the picker paints rather than on top of it.
|
|
203
|
+
const opened = await refresh(options, enabled, false, (message) => process.stderr.write(`${dim(message)}\n`));
|
|
204
|
+
if (opened.views.length === 0) {
|
|
205
|
+
process.stdout.write(`${dim("No sessions found. If you expected some, run `gmux doctor`.")}\n`);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
// Ask is offered only when it would actually answer. Advertising ctrl-o to
|
|
209
|
+
// someone who chose "no model calls" — or who never installed what they
|
|
210
|
+
// chose — binds a key that opens a chat which dies instantly, and fzf
|
|
211
|
+
// repaints the list over the explanation before it can be read. That is
|
|
212
|
+
// the "key that does nothing" this file already refuses to offer.
|
|
213
|
+
const canAsk = await askIsAvailable();
|
|
214
|
+
// Reap transcripts left behind by pickers that were `kill -9`d. The
|
|
215
|
+
// parent's job, not the picker's, and it runs before we open so a live
|
|
216
|
+
// pane's file is never the one being read while we consider removing it.
|
|
217
|
+
await sweepAskTranscripts();
|
|
218
|
+
// Allocated whatever the fzf version is: only the `split` tier renders a
|
|
219
|
+
// chat, and it is the picker that knows which tier this is. A tier that
|
|
220
|
+
// ignores this never creates the file, so the cleanup below removes
|
|
221
|
+
// nothing and costs nothing.
|
|
222
|
+
const transcript = newAskTranscriptPath();
|
|
223
|
+
const chat = canAsk ? pickerChatSpec(options, transcript) : undefined;
|
|
224
|
+
const chosen = await pickSession(opened.views, {
|
|
225
|
+
inProgress: opened.inProgress,
|
|
226
|
+
reloadArgs: pickerReloadArgs(options, listWidth(), enabled),
|
|
227
|
+
...(canAsk ? { askArgs: pickerAskArgs(options) } : {}),
|
|
228
|
+
...(chat ? { chat, onClose: closeChatThread(transcript) } : {}),
|
|
229
|
+
// `a` in the numbered fallback. fzf's ctrl-o does NOT come through here:
|
|
230
|
+
// it runs its own `execute` binding against this build, so the chat gets
|
|
231
|
+
// a clean terminal instead of one fzf is painting.
|
|
232
|
+
...(canAsk ? { ask: () => askAboutSessions(options) } : {}),
|
|
233
|
+
// `r` in the numbered fallback: forced, like the ctrl-r it stands in for.
|
|
234
|
+
reload: () => refresh(options, enabled, true),
|
|
235
|
+
// ctrl-r can surface a session that did not exist when we opened. Look
|
|
236
|
+
// it up the way `gmux resume <id>` does — naming a session explicitly
|
|
237
|
+
// means you want it, even if the list filters would now hide it.
|
|
238
|
+
resolve: async (id) => {
|
|
239
|
+
const fresh = await loadViews({ includeSidechains: true, includeAutomated: true });
|
|
240
|
+
return fresh.find((v) => v.record.sessionId === id) ?? null;
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
if (!chosen) {
|
|
244
|
+
process.stdout.write(`${dim("Nothing selected.")}\n`);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (options.resumeInWindow === true && process.env.TMUX) {
|
|
248
|
+
await resumeInNewWindow(chosen.record);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
await resumeSession(chosen.record);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=pick.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pick.js","sourceRoot":"","sources":["../../../src/cli/commands/pick.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* The picker's ctrl-r target, re-entered as `gmux __picker-rows`.
|
|
4
|
+
*
|
|
5
|
+
* Hidden: like `__auto-summarize`, it is not a thing a person runs. fzf's
|
|
6
|
+
* `reload` binding replaces its item list with a command's stdout, so refresh
|
|
7
|
+
* is exactly "print the records again, having first kicked off summaries".
|
|
8
|
+
*
|
|
9
|
+
* Two rules, both because fzf owns the terminal while this runs:
|
|
10
|
+
*
|
|
11
|
+
* 1. NOTHING goes to stderr. `maybeAutoSummarize`'s notice would land on top of
|
|
12
|
+
* the picker and corrupt the display. The `◐` markers are the notice here.
|
|
13
|
+
* 2. Width comes from `--width`, not from measuring. Our stdout is a pipe, so
|
|
14
|
+
* `terminalWidth()` would report its default and every row would reflow to a
|
|
15
|
+
* different width than it had on open.
|
|
16
|
+
*/
|
|
17
|
+
export declare function registerPickerRows(program: Command): void;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { inProgressIds, maybeAutoSummarize } from "../../services/auto-summarize.js";
|
|
2
|
+
import { loadViews } from "../../services/views.js";
|
|
3
|
+
import { buildFzfRecords, fzfVersion, supportsMultiline } from "../picker.js";
|
|
4
|
+
import { PICKER_ROWS_COMMAND } from "./pick.js";
|
|
5
|
+
import { autoSummarizeRequested, toFilters } from "./ls.js";
|
|
6
|
+
/**
|
|
7
|
+
* The picker's ctrl-r target, re-entered as `gmux __picker-rows`.
|
|
8
|
+
*
|
|
9
|
+
* Hidden: like `__auto-summarize`, it is not a thing a person runs. fzf's
|
|
10
|
+
* `reload` binding replaces its item list with a command's stdout, so refresh
|
|
11
|
+
* is exactly "print the records again, having first kicked off summaries".
|
|
12
|
+
*
|
|
13
|
+
* Two rules, both because fzf owns the terminal while this runs:
|
|
14
|
+
*
|
|
15
|
+
* 1. NOTHING goes to stderr. `maybeAutoSummarize`'s notice would land on top of
|
|
16
|
+
* the picker and corrupt the display. The `◐` markers are the notice here.
|
|
17
|
+
* 2. Width comes from `--width`, not from measuring. Our stdout is a pipe, so
|
|
18
|
+
* `terminalWidth()` would report its default and every row would reflow to a
|
|
19
|
+
* different width than it had on open.
|
|
20
|
+
*/
|
|
21
|
+
export function registerPickerRows(program) {
|
|
22
|
+
program
|
|
23
|
+
.command(PICKER_ROWS_COMMAND, { hidden: true })
|
|
24
|
+
.description("internal: print picker rows (run by the picker's ctrl-r binding)")
|
|
25
|
+
.option("--harness <id>", "only this harness")
|
|
26
|
+
.option("-p, --project <name>", "only sessions whose project matches")
|
|
27
|
+
.option("-b, --branch <name>", "only sessions whose git branch matches")
|
|
28
|
+
.option("-s, --since <when>", "only sessions newer than this")
|
|
29
|
+
.option("-n, --limit <count>", "how many sessions to offer", "50")
|
|
30
|
+
.option("--include-sidechains", "include subagent transcripts")
|
|
31
|
+
.option("--include-automated", "include non-interactive runs")
|
|
32
|
+
.option("--width <columns>", "list column width, measured by the parent")
|
|
33
|
+
.action(async (options, command) => {
|
|
34
|
+
const views = await loadViews(toFilters(options, 50));
|
|
35
|
+
// Forced: the user pressed a key. The lock still stops a stampede, and
|
|
36
|
+
// `--no-auto-summarize` — forwarded by pickerReloadArgs — still wins.
|
|
37
|
+
const started = await maybeAutoSummarize({
|
|
38
|
+
records: views.map((v) => v.record),
|
|
39
|
+
enabled: autoSummarizeRequested(command),
|
|
40
|
+
force: true,
|
|
41
|
+
});
|
|
42
|
+
const inProgress = new Set([...(await inProgressIds()), ...started.targetIds]);
|
|
43
|
+
const width = Number.parseInt(options.width ?? "", 10);
|
|
44
|
+
process.stdout.write(buildFzfRecords(views, supportsMultiline(fzfVersion()), Number.isFinite(width) && width > 0 ? width : undefined, new Date(), inProgress));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=picker-rows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picker-rows.js","sourceRoot":"","sources":["../../../src/cli/commands/picker-rows.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAA0B,MAAM,WAAW,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAE5D;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,OAAO;SACJ,OAAO,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SAC9C,WAAW,CAAC,kEAAkE,CAAC;SAC/E,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC;SAC7C,MAAM,CAAC,sBAAsB,EAAE,qCAAqC,CAAC;SACrE,MAAM,CAAC,qBAAqB,EAAE,wCAAwC,CAAC;SACvE,MAAM,CAAC,oBAAoB,EAAE,+BAA+B,CAAC;SAC7D,MAAM,CAAC,qBAAqB,EAAE,4BAA4B,EAAE,IAAI,CAAC;SACjE,MAAM,CAAC,sBAAsB,EAAE,8BAA8B,CAAC;SAC9D,MAAM,CAAC,qBAAqB,EAAE,8BAA8B,CAAC;SAC7D,MAAM,CAAC,mBAAmB,EAAE,2CAA2C,CAAC;SACxE,MAAM,CAAC,KAAK,EAAE,OAA0B,EAAE,OAAgB,EAAE,EAAE;QAC7D,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QAEtD,uEAAuE;QACvE,sEAAsE;QACtE,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC;YACvC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;YACnC,OAAO,EAAE,sBAAsB,CAAC,OAAO,CAAC;YACxC,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,aAAa,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QAC/E,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAEvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,eAAe,CACb,KAAK,EACL,iBAAiB,CAAC,UAAU,EAAE,CAAC,EAC/B,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,EACvD,IAAI,IAAI,EAAE,EACV,UAAU,CACX,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { SessionRecord } from "../../core/types.js";
|
|
3
|
+
import type { ResumeCommand } from "../../adapters/types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Hand control to the harness that owns this session.
|
|
6
|
+
*
|
|
7
|
+
* We replace this process rather than wrapping it: the user wants to be *in*
|
|
8
|
+
* Claude Code or Codex, not in a gmux shell that proxies keystrokes.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resumeSession(record: SessionRecord, dryRun?: boolean): Promise<never | void>;
|
|
11
|
+
/**
|
|
12
|
+
* The tmux argv that opens the resume command in a new window in the current
|
|
13
|
+
* session. Args are passed after `--` so nothing has to be shell-escaped — tmux
|
|
14
|
+
* runs the vector directly. Pure, so the shape is tested without spawning tmux.
|
|
15
|
+
*/
|
|
16
|
+
export declare function newWindowArgv(resume: ResumeCommand): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Resume a session in a NEW tmux window instead of replacing this process.
|
|
19
|
+
*
|
|
20
|
+
* Used only by the picker bridge (`gmux pick --resume-in-window`), which runs
|
|
21
|
+
* inside a `display-popup`: exec'ing the harness there would trap it in the
|
|
22
|
+
* ephemeral popup, gone the moment it exits. A new window is a persistent pane.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resumeInNewWindow(record: SessionRecord): Promise<void>;
|
|
25
|
+
export declare function registerResume(program: Command): void;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { execFile, spawn } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { GmuxError } from "../../core/errors.js";
|
|
4
|
+
import { shellQuote } from "../../core/text.js";
|
|
5
|
+
import { adapterById } from "../../adapters/registry.js";
|
|
6
|
+
import { loadRecords } from "../../services/views.js";
|
|
7
|
+
import { resolveSession } from "../../services/resolve.js";
|
|
8
|
+
import { dim } from "../format.js";
|
|
9
|
+
/**
|
|
10
|
+
* Hand control to the harness that owns this session.
|
|
11
|
+
*
|
|
12
|
+
* We replace this process rather than wrapping it: the user wants to be *in*
|
|
13
|
+
* Claude Code or Codex, not in a gmux shell that proxies keystrokes.
|
|
14
|
+
*/
|
|
15
|
+
export async function resumeSession(record, dryRun = false) {
|
|
16
|
+
const adapter = adapterById(record.harness);
|
|
17
|
+
if (!adapter) {
|
|
18
|
+
throw new GmuxError(`No adapter is registered for harness "${record.harness}".`, {
|
|
19
|
+
fix: "This session was indexed by a version of gmux that supported more harnesses. Run `gmux index --rebuild`.",
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const { command, args, cwd } = adapter.resumeCommand(record);
|
|
23
|
+
if (!existsSync(cwd)) {
|
|
24
|
+
throw new GmuxError(`The session's directory no longer exists: ${cwd}`, {
|
|
25
|
+
fix: "The repo or worktree was moved or deleted. Recreate it, or resume manually from another directory.",
|
|
26
|
+
exitCode: 3,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (dryRun) {
|
|
30
|
+
// Quote it: this line is meant to be pasted into a shell, and a repo path
|
|
31
|
+
// with a space in it would otherwise silently run in the wrong directory.
|
|
32
|
+
process.stdout.write(`cd ${shellQuote(cwd)} && ${command} ${args.map(shellQuote).join(" ")}\n`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
process.stderr.write(`${dim(`→ ${command} ${args.join(" ")} (in ${cwd})`)}\n`);
|
|
36
|
+
const child = spawn(command, args, { cwd, stdio: "inherit" });
|
|
37
|
+
child.on("error", (error) => {
|
|
38
|
+
if (error.code === "ENOENT") {
|
|
39
|
+
process.stderr.write(`error "${command}" is not on your PATH, so this session cannot be resumed.\n` +
|
|
40
|
+
`fix Install ${adapter.displayName}, or run \`gmux resume ${record.sessionId.slice(0, 8)} --print\` to see the command.\n`);
|
|
41
|
+
process.exit(6);
|
|
42
|
+
}
|
|
43
|
+
process.stderr.write(`error ${error.message}\n`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
});
|
|
46
|
+
child.on("close", (code) => process.exit(code ?? 0));
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The tmux argv that opens the resume command in a new window in the current
|
|
50
|
+
* session. Args are passed after `--` so nothing has to be shell-escaped — tmux
|
|
51
|
+
* runs the vector directly. Pure, so the shape is tested without spawning tmux.
|
|
52
|
+
*/
|
|
53
|
+
export function newWindowArgv(resume) {
|
|
54
|
+
return ["new-window", "-c", resume.cwd, "--", resume.command, ...resume.args];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Resume a session in a NEW tmux window instead of replacing this process.
|
|
58
|
+
*
|
|
59
|
+
* Used only by the picker bridge (`gmux pick --resume-in-window`), which runs
|
|
60
|
+
* inside a `display-popup`: exec'ing the harness there would trap it in the
|
|
61
|
+
* ephemeral popup, gone the moment it exits. A new window is a persistent pane.
|
|
62
|
+
*/
|
|
63
|
+
export async function resumeInNewWindow(record) {
|
|
64
|
+
const adapter = adapterById(record.harness);
|
|
65
|
+
if (!adapter) {
|
|
66
|
+
throw new GmuxError(`No adapter is registered for harness "${record.harness}".`, {
|
|
67
|
+
fix: "Run `gmux index --rebuild`.",
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const argv = newWindowArgv(adapter.resumeCommand(record));
|
|
71
|
+
await new Promise((resolve, reject) => {
|
|
72
|
+
execFile("tmux", argv, (error) => (error ? reject(error) : resolve()));
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
export function registerResume(program) {
|
|
76
|
+
program
|
|
77
|
+
.command("resume <id>")
|
|
78
|
+
.description("resume a session in its original harness and directory")
|
|
79
|
+
.option("--print", "print the command instead of running it")
|
|
80
|
+
.action(async (id, options) => {
|
|
81
|
+
// As with `show`: naming a session explicitly means you want it, even if
|
|
82
|
+
// `gmux ls` would hide it by default.
|
|
83
|
+
const records = await loadRecords({ includeSidechains: true, includeAutomated: true });
|
|
84
|
+
const record = resolveSession(records, id);
|
|
85
|
+
await resumeSession(record, options.print === true);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=resume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../../../src/cli/commands/resume.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGrC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAqB,EAAE,MAAM,GAAG,KAAK;IACvE,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CAAC,yCAAyC,MAAM,CAAC,OAAO,IAAI,EAAE;YAC/E,GAAG,EAAE,0GAA0G;SAChH,CAAC,CAAC;IACL,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAE7D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,SAAS,CAAC,6CAA6C,GAAG,EAAE,EAAE;YACtE,GAAG,EAAE,oGAAoG;YACzG,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,0EAA0E;QAC1E,0EAA0E;QAC1E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,OAAO,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChG,OAAO;IACT,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IAEhF,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC1B,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,WAAW,OAAO,6DAA6D;gBAC7E,kBAAkB,OAAO,CAAC,WAAW,0BAA0B,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,kCAAkC,CAChI,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAAqB;IACjD,OAAO,CAAC,YAAY,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;AAChF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAqB;IAC3D,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CAAC,yCAAyC,MAAM,CAAC,OAAO,IAAI,EAAE;YAC/E,GAAG,EAAE,6BAA6B;SACnC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1D,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,OAAO;SACJ,OAAO,CAAC,aAAa,CAAC;SACtB,WAAW,CAAC,wDAAwD,CAAC;SACrE,MAAM,CAAC,SAAS,EAAE,yCAAyC,CAAC;SAC5D,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,OAA4B,EAAE,EAAE;QACzD,yEAAyE;QACzE,sCAAsC;QACtC,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;QACvF,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC3C,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { HarnessAdapter } from "../../adapters/types.js";
|
|
3
|
+
import type { SessionRef } from "../../core/types.js";
|
|
4
|
+
/** Match `gmux run <arg>` to a harness by id or by a process-name alias. */
|
|
5
|
+
export declare function resolveHarnessArg(arg: string): HarnessAdapter | null;
|
|
6
|
+
/**
|
|
7
|
+
* The session the harness just started or touched: newest among those whose id
|
|
8
|
+
* is either new (a fresh session) or whose mtime advanced since `before` (a
|
|
9
|
+
* resumed one — `gmux run codex resume`, `gmux run claude --resume <id>` write to
|
|
10
|
+
* an EXISTING session file, so no new id ever appears for those).
|
|
11
|
+
*/
|
|
12
|
+
export declare function pickChangedSession(before: readonly SessionRef[], after: readonly SessionRef[]): SessionRef | null;
|
|
13
|
+
export declare function registerRun(program: Command): void;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { adapterById, allAdapters } from "../../adapters/registry.js";
|
|
3
|
+
import { writePaneLink } from "../../services/pane-links.js";
|
|
4
|
+
import { dim } from "../format.js";
|
|
5
|
+
/** How long to watch for the harness's freshly-written session file. */
|
|
6
|
+
const DETECT_WINDOW_MS = 8000;
|
|
7
|
+
const DETECT_POLL_MS = 500;
|
|
8
|
+
/** Match `gmux run <arg>` to a harness by id or by a process-name alias. */
|
|
9
|
+
export function resolveHarnessArg(arg) {
|
|
10
|
+
const needle = arg.trim().toLowerCase();
|
|
11
|
+
return (adapterById(needle) ??
|
|
12
|
+
allAdapters().find((a) => a.processNames.some((n) => n.toLowerCase() === needle)) ??
|
|
13
|
+
null);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The session the harness just started or touched: newest among those whose id
|
|
17
|
+
* is either new (a fresh session) or whose mtime advanced since `before` (a
|
|
18
|
+
* resumed one — `gmux run codex resume`, `gmux run claude --resume <id>` write to
|
|
19
|
+
* an EXISTING session file, so no new id ever appears for those).
|
|
20
|
+
*/
|
|
21
|
+
export function pickChangedSession(before, after) {
|
|
22
|
+
const beforeMtimes = new Map(before.map((r) => [r.sessionId, r.mtimeMs]));
|
|
23
|
+
const changed = after.filter((r) => {
|
|
24
|
+
const priorMtime = beforeMtimes.get(r.sessionId);
|
|
25
|
+
return priorMtime === undefined || r.mtimeMs > priorMtime;
|
|
26
|
+
});
|
|
27
|
+
return [...changed].sort((a, b) => b.mtimeMs - a.mtimeMs)[0] ?? null;
|
|
28
|
+
}
|
|
29
|
+
async function captureLink(adapter, paneId, before) {
|
|
30
|
+
const deadline = Date.now() + DETECT_WINDOW_MS;
|
|
31
|
+
while (Date.now() < deadline) {
|
|
32
|
+
await new Promise((r) => setTimeout(r, DETECT_POLL_MS));
|
|
33
|
+
try {
|
|
34
|
+
const after = await adapter.listSessions();
|
|
35
|
+
const picked = pickChangedSession(before, after);
|
|
36
|
+
if (picked) {
|
|
37
|
+
await writePaneLink({ paneId, harness: adapter.id, sessionId: picked.sessionId });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// The harness may not have written its dir yet; keep watching.
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
process.stderr.write(`${dim("gmux: could not link this pane automatically (the overlay will fall back to the cwd heuristic)")}\n`);
|
|
46
|
+
}
|
|
47
|
+
export function registerRun(program) {
|
|
48
|
+
program
|
|
49
|
+
.command("run <harness> [args...]")
|
|
50
|
+
.description("launch an agent and record which pane it runs in, for exact overlay mapping")
|
|
51
|
+
.allowUnknownOption(true)
|
|
52
|
+
.action(async (harness, args = []) => {
|
|
53
|
+
const adapter = resolveHarnessArg(harness);
|
|
54
|
+
if (!adapter) {
|
|
55
|
+
process.stderr.write(`error unknown harness "${harness}". Known: ${allAdapters().map((a) => a.id).join(", ")}\n`);
|
|
56
|
+
process.exit(2);
|
|
57
|
+
}
|
|
58
|
+
const paneId = process.env.TMUX_PANE;
|
|
59
|
+
const before = paneId ? await adapter.listSessions().catch(() => []) : [];
|
|
60
|
+
// The wrapper lingers only to capture the session id; stdio is inherited,
|
|
61
|
+
// so the pane is the agent for all interactive purposes.
|
|
62
|
+
const child = spawn(adapter.launchCommand, args, { stdio: "inherit" });
|
|
63
|
+
if (paneId) {
|
|
64
|
+
process.stderr.write(`${dim(`gmux: linking pane ${paneId} to this ${adapter.displayName} session`)}\n`);
|
|
65
|
+
void captureLink(adapter, paneId, before);
|
|
66
|
+
}
|
|
67
|
+
child.on("error", (error) => {
|
|
68
|
+
if (error.code === "ENOENT") {
|
|
69
|
+
process.stderr.write(`error "${adapter.launchCommand}" is not on your PATH.\n`);
|
|
70
|
+
process.exit(6);
|
|
71
|
+
}
|
|
72
|
+
process.stderr.write(`error ${error.message}\n`);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
});
|
|
75
|
+
child.on("close", (code) => process.exit(code ?? 0));
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/cli/commands/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `gmux setup` — choose the harness gmux calls for summaries and `gmux ask`.
|
|
3
|
+
*
|
|
4
|
+
* The wizard is the only place gmux asks a question. Everything it writes
|
|
5
|
+
* is a choice a human made, which is why it goes to the config dir rather than
|
|
6
|
+
* the cache — see core/paths.ts.
|
|
7
|
+
*/
|
|
8
|
+
import { type Interface } from "node:readline/promises";
|
|
9
|
+
import type { Command } from "commander";
|
|
10
|
+
import { type GmConfig, type ProviderChoice } from "../../core/types.js";
|
|
11
|
+
/** One selectable answer to "which provider?". */
|
|
12
|
+
interface Option {
|
|
13
|
+
label: string;
|
|
14
|
+
detail: string;
|
|
15
|
+
/** null = make no model calls. */
|
|
16
|
+
choose: (rl: Interface) => Promise<ProviderChoice | null>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The menu.
|
|
20
|
+
*
|
|
21
|
+
* Every catalog provider is listed, installed or not, and an uninstalled one is
|
|
22
|
+
* still selectable — you might be about to install it, and a wizard that hides
|
|
23
|
+
* the option you came for is a wizard that sends you to the docs. The line says
|
|
24
|
+
* what's missing and how to get it.
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildOptions(): Option[];
|
|
27
|
+
/**
|
|
28
|
+
* The wizard itself. Returns the config it wrote.
|
|
29
|
+
*
|
|
30
|
+
* Takes its own readline interface so the first-run caller and `gmux setup` share
|
|
31
|
+
* one implementation and one teardown.
|
|
32
|
+
*/
|
|
33
|
+
export declare function runSetupWizard(options?: {
|
|
34
|
+
firstRun?: boolean;
|
|
35
|
+
}): Promise<GmConfig>;
|
|
36
|
+
export declare function registerSetup(program: Command): void;
|
|
37
|
+
export {};
|