@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,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rendering.
|
|
3
|
+
*
|
|
4
|
+
* Colour is applied only when stdout is a TTY and NO_COLOR is unset, so piping
|
|
5
|
+
* `gmux ls` into another program — or into an agent — yields clean text.
|
|
6
|
+
*/
|
|
7
|
+
import { cell, relativeAge, truncate, wrapText } from "../core/text.js";
|
|
8
|
+
/** Colour is off unless the user leaves it on — a `NO_COLOR`/`dumb` opt-out we honour everywhere. */
|
|
9
|
+
const colorEnabled = () => !process.env.NO_COLOR && process.env.TERM !== "dumb";
|
|
10
|
+
const useColor = () => process.stdout.isTTY === true && colorEnabled();
|
|
11
|
+
const wrap = (code) => (text) => (useColor() ? `[${code}m${text}[0m` : text);
|
|
12
|
+
export const dim = wrap("2");
|
|
13
|
+
export const bold = wrap("1");
|
|
14
|
+
export const cyan = wrap("36");
|
|
15
|
+
export const yellow = wrap("33");
|
|
16
|
+
export const red = wrap("31");
|
|
17
|
+
export const green = wrap("32");
|
|
18
|
+
/**
|
|
19
|
+
* Colour forced on for output we KNOW an ANSI renderer consumes, even off a TTY.
|
|
20
|
+
*
|
|
21
|
+
* The picker's preview command writes to a pipe, so `process.stdout.isTTY` is
|
|
22
|
+
* false and `useColor()` above is too — yet fzf renders that pipe with `--ansi`.
|
|
23
|
+
* These variants drop only the TTY test, so the pane can carry colour while
|
|
24
|
+
* `NO_COLOR` and `TERM=dumb` still turn it off. Used solely by `preview.ts`; the
|
|
25
|
+
* card and `gmux ls`/`gmux show` keep the gated `dim`/`cyan`/`bold` and stay clean
|
|
26
|
+
* when piped into another program.
|
|
27
|
+
*/
|
|
28
|
+
const wrapForced = (code) => (text) => colorEnabled() ? `[${code}m${text}[0m` : text;
|
|
29
|
+
export const paneCyan = wrapForced("36");
|
|
30
|
+
export const paneBold = wrapForced("1");
|
|
31
|
+
export const paneDim = wrapForced("2");
|
|
32
|
+
/** Marks a session that stopped mid-task — usually the one you want to resume. */
|
|
33
|
+
const MID_TASK = "⚠";
|
|
34
|
+
/**
|
|
35
|
+
* Marks a row whose summary has not been written yet.
|
|
36
|
+
*
|
|
37
|
+
* One column, so a row that gains a summary does not shift the layout. It used
|
|
38
|
+
* to be a dim `~`, which was invisible next to the yellow `⚠` — and now that
|
|
39
|
+
* these rows are actively being summarized in the background, "pending" is a
|
|
40
|
+
* state worth seeing.
|
|
41
|
+
*/
|
|
42
|
+
const NO_SUMMARY = "○";
|
|
43
|
+
/** Marks a row whose summary is being written right now, by the background worker. */
|
|
44
|
+
const IN_PROGRESS = "◐";
|
|
45
|
+
const MARKERS = [
|
|
46
|
+
{
|
|
47
|
+
icon: MID_TASK,
|
|
48
|
+
color: yellow,
|
|
49
|
+
label: "ended mid-task",
|
|
50
|
+
matches: (view) => view.record.endedMidTask === true,
|
|
51
|
+
counted: false,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
icon: IN_PROGRESS,
|
|
55
|
+
color: green,
|
|
56
|
+
label: "summarizing now",
|
|
57
|
+
matches: (view, inProgress) => !view.summary && inProgress.has(view.record.sessionId),
|
|
58
|
+
counted: true,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
icon: NO_SUMMARY,
|
|
62
|
+
color: cyan,
|
|
63
|
+
label: "no summary yet",
|
|
64
|
+
matches: (view, inProgress) => !view.summary && !inProgress.has(view.record.sessionId),
|
|
65
|
+
counted: true,
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
/** Wide enough to read as separate entries, narrow enough to hold one line. */
|
|
69
|
+
const KEY_GAP = " ";
|
|
70
|
+
const keyEntry = (marker, label) => `${marker.color(marker.icon)} ${dim(label)}`;
|
|
71
|
+
/** "repo/branch", or just "repo" when the branch adds nothing. */
|
|
72
|
+
export function sessionLabel(record) {
|
|
73
|
+
const project = record.project ?? "?";
|
|
74
|
+
return record.gitBranch ? `${project}/${record.gitBranch}` : project;
|
|
75
|
+
}
|
|
76
|
+
const WHERE_WIDTH = 28;
|
|
77
|
+
/** Never squeeze the description below this, however narrow the terminal. */
|
|
78
|
+
const MIN_TEXT_WIDTH = 24;
|
|
79
|
+
/** The description shown for a session: summary first, and never blank. */
|
|
80
|
+
function rowText(view) {
|
|
81
|
+
const { record, summary } = view;
|
|
82
|
+
return summary?.headline ?? record.title ?? record.lastUserPrompt ?? "(no content)";
|
|
83
|
+
}
|
|
84
|
+
const NONE = new Set();
|
|
85
|
+
/** The fixed-width columns before the description, coloured and plain. */
|
|
86
|
+
function rowPrefix(view, now, inProgress = NONE) {
|
|
87
|
+
const { record, summary } = view;
|
|
88
|
+
const id = record.sessionId.slice(0, 8);
|
|
89
|
+
const age = cell(relativeAge(record.updatedAt, now), 4);
|
|
90
|
+
const where = cell(sessionLabel(record), WHERE_WIDTH);
|
|
91
|
+
const flag = record.endedMidTask ? yellow(MID_TASK) : " ";
|
|
92
|
+
const mark = summary
|
|
93
|
+
? " "
|
|
94
|
+
: inProgress.has(record.sessionId)
|
|
95
|
+
? green(IN_PROGRESS)
|
|
96
|
+
: cyan(NO_SUMMARY);
|
|
97
|
+
return {
|
|
98
|
+
colored: `${dim(id)} ${dim(age)} ${flag}${mark} ${cyan(where)} `,
|
|
99
|
+
// Measured from the plain text: colour codes take no screen columns.
|
|
100
|
+
width: id.length + 1 + age.length + 1 + 2 + 1 + where.length + 1,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* One row, on exactly one line.
|
|
105
|
+
*
|
|
106
|
+
* Used by the picker, where a session must occupy a single line — fzf maps lines
|
|
107
|
+
* back to session ids, so a wrapped row would break selection.
|
|
108
|
+
*/
|
|
109
|
+
export function formatRow(view, now = new Date(), inProgress = NONE) {
|
|
110
|
+
return `${rowPrefix(view, now, inProgress).colored}${truncate(rowText(view), 72)}`;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* One row of `gmux ls`, wrapped to the terminal so the whole description is
|
|
114
|
+
* readable rather than chopped off at the right edge. Continuation lines are
|
|
115
|
+
* indented to sit under the description column.
|
|
116
|
+
*
|
|
117
|
+
* Pass `width: Infinity` when the output is not a terminal: piped output should
|
|
118
|
+
* be one line per session, so `gmux ls | grep` behaves.
|
|
119
|
+
*/
|
|
120
|
+
export function formatRowLines(view, now = new Date(), width = terminalWidth(), inProgress = NONE) {
|
|
121
|
+
const prefix = rowPrefix(view, now, inProgress);
|
|
122
|
+
const text = rowText(view);
|
|
123
|
+
if (!Number.isFinite(width)) {
|
|
124
|
+
return [`${prefix.colored}${text}`]; // Piped: one line, nothing lost.
|
|
125
|
+
}
|
|
126
|
+
const available = width - prefix.width;
|
|
127
|
+
// On a terminal too narrow to hold the columns AND a readable description,
|
|
128
|
+
// giving the description a sliver of a column would just overflow anyway.
|
|
129
|
+
// Drop it onto its own indented lines instead.
|
|
130
|
+
if (available < MIN_TEXT_WIDTH) {
|
|
131
|
+
const indent = " ";
|
|
132
|
+
return [
|
|
133
|
+
prefix.colored.trimEnd(),
|
|
134
|
+
...wrapText(text, Math.max(MIN_TEXT_WIDTH, width - indent.length)).map((line) => `${indent}${line}`),
|
|
135
|
+
];
|
|
136
|
+
}
|
|
137
|
+
const [first = "", ...rest] = wrapText(text, available);
|
|
138
|
+
const indent = " ".repeat(prefix.width);
|
|
139
|
+
return [`${prefix.colored}${first}`, ...rest.map((line) => `${indent}${dim(line)}`)];
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The key under the list. Only mentions markers that actually appear, so a fully
|
|
143
|
+
* summarized list carries no footer at all.
|
|
144
|
+
*/
|
|
145
|
+
export function formatLegend(views, inProgress = NONE) {
|
|
146
|
+
return MARKERS.flatMap((marker) => {
|
|
147
|
+
const on = views.filter((view) => marker.matches(view, inProgress)).length;
|
|
148
|
+
if (on === 0)
|
|
149
|
+
return [];
|
|
150
|
+
return [keyEntry(marker, marker.counted ? `${marker.label} (${on})` : marker.label)];
|
|
151
|
+
}).join(KEY_GAP);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* The key for a LIVE list: every marker, always, and never a count.
|
|
155
|
+
*
|
|
156
|
+
* The picker renders the same markers `gmux ls` does, so it needs the same
|
|
157
|
+
* explanation — but not `formatLegend`. fzf sets `--header` once, at spawn:
|
|
158
|
+
* `ctrl-r` reloads the item list and leaves the header untouched. Counts baked
|
|
159
|
+
* in there freeze at open and are wrong after the first refresh, and a key
|
|
160
|
+
* listing "only the markers present" goes stale the moment a refresh brings in
|
|
161
|
+
* one that wasn't. ctrl-r is precisely when both change.
|
|
162
|
+
*
|
|
163
|
+
* So: nothing here depends on the list. A stale key is worse than a fixed one —
|
|
164
|
+
* absent an explanation you go looking, given a wrong one you don't. The cost is
|
|
165
|
+
* one line naming `○` on a list that has none.
|
|
166
|
+
*/
|
|
167
|
+
export function formatMarkerKey() {
|
|
168
|
+
return MARKERS.map((marker) => keyEntry(marker, marker.label)).join(KEY_GAP);
|
|
169
|
+
}
|
|
170
|
+
/** Terminal width, or a sane default when we cannot tell. */
|
|
171
|
+
export function terminalWidth() {
|
|
172
|
+
return process.stdout.columns && process.stdout.columns > 0 ? process.stdout.columns : 100;
|
|
173
|
+
}
|
|
174
|
+
/** The detail card shown by `gmux show` and in the picker's preview pane. */
|
|
175
|
+
export function formatCard(view, now = new Date()) {
|
|
176
|
+
const { record, summary } = view;
|
|
177
|
+
const lines = [];
|
|
178
|
+
lines.push(bold(sessionLabel(record)), dim(`${record.harness} · ${record.sessionId} · ${relativeAge(record.updatedAt, now)} ago`));
|
|
179
|
+
lines.push("");
|
|
180
|
+
if (summary) {
|
|
181
|
+
// Widening zoom: the headline names the work, the overview frames it, the
|
|
182
|
+
// summary reorients you. `headline` is the one field parsing guarantees, so
|
|
183
|
+
// it stands in for the overview when that is empty.
|
|
184
|
+
lines.push(bold("HEADLINE"), indent(summary.headline), "");
|
|
185
|
+
if (summary.overview)
|
|
186
|
+
lines.push(bold("OVERVIEW"), indent(summary.overview), "");
|
|
187
|
+
if (summary.summary)
|
|
188
|
+
lines.push(bold("SUMMARY"), indent(summary.summary), "");
|
|
189
|
+
if (summary.landed)
|
|
190
|
+
lines.push(bold("RECENT WORK"), indent(summary.landed), "");
|
|
191
|
+
if (summary.open)
|
|
192
|
+
lines.push(bold("STILL OPEN"), indent(summary.open), "");
|
|
193
|
+
if (summary.nextStep)
|
|
194
|
+
lines.push(bold("NEXT STEP"), indent(green(summary.nextStep)), "");
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
lines.push(dim("No summary yet."), dim(`Run: gmux summarize ${record.sessionId.slice(0, 8)}`), "");
|
|
198
|
+
if (record.title)
|
|
199
|
+
lines.push(bold("TITLE (recorded at session start)"), indent(record.title), "");
|
|
200
|
+
}
|
|
201
|
+
if (record.lastUserPrompt) {
|
|
202
|
+
lines.push(bold("LAST THING YOU SAID"), indent(`"${truncate(record.lastUserPrompt, 240)}"`), "");
|
|
203
|
+
}
|
|
204
|
+
if (record.filesTouched.length > 0) {
|
|
205
|
+
const shown = record.filesTouched.slice(0, 6);
|
|
206
|
+
const extra = record.filesTouched.length - shown.length;
|
|
207
|
+
lines.push(bold("FILES TOUCHED"), ...shown.map((f) => ` ${f}`), ...(extra > 0 ? [dim(` … and ${extra} more`)] : []), "");
|
|
208
|
+
}
|
|
209
|
+
if (record.prLinks.length > 0) {
|
|
210
|
+
const shown = record.prLinks.slice(0, 8);
|
|
211
|
+
const extra = record.prLinks.length - shown.length;
|
|
212
|
+
lines.push(bold("PULL REQUESTS"), ...shown.map((pr) => ` #${pr.number} ${pr.url}`), ...(extra > 0 ? [dim(` … and ${extra} more`)] : []), "");
|
|
213
|
+
}
|
|
214
|
+
const facts = [`${record.messageCount} messages`, `${record.userPromptCount} prompts`];
|
|
215
|
+
if (record.endedMidTask)
|
|
216
|
+
facts.push(yellow("ended mid-task"));
|
|
217
|
+
if (record.lastToolFailure)
|
|
218
|
+
facts.push(red("last command failed"));
|
|
219
|
+
lines.push(dim(facts.join(" · ")));
|
|
220
|
+
if (record.cwd)
|
|
221
|
+
lines.push(dim(record.cwd));
|
|
222
|
+
return lines.join("\n");
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Two spaces under a heading — the card's only body indent.
|
|
226
|
+
*
|
|
227
|
+
* Exported for the preview's chat half, whose speaker bodies sit under `you` and
|
|
228
|
+
* `gmux` exactly as the card's text sits under `WHERE IT LANDED`. Both halves share
|
|
229
|
+
* one pane, so a second indent idiom would show up as two columns that almost
|
|
230
|
+
* line up.
|
|
231
|
+
*/
|
|
232
|
+
export function indent(text) {
|
|
233
|
+
return text
|
|
234
|
+
.split("\n")
|
|
235
|
+
.map((line) => ` ${line}`)
|
|
236
|
+
.join("\n");
|
|
237
|
+
}
|
|
238
|
+
/** Stable JSON envelope. Everything machine-readable goes through here. */
|
|
239
|
+
export function jsonEnvelope(schemaVersion, data) {
|
|
240
|
+
return JSON.stringify({ schemaVersion, data }, null, 2);
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/cli/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HostPressure, WorkspaceSnapshot } from "../core/gmux-types.js";
|
|
2
|
+
export declare function formatBytes(n: number): string;
|
|
3
|
+
export declare function relativeTime(ts: number, now: number): string;
|
|
4
|
+
export declare function unattributedLine(host: HostPressure | null): string | null;
|
|
5
|
+
export interface RenderCockpitOptions {
|
|
6
|
+
width?: number;
|
|
7
|
+
stale?: {
|
|
8
|
+
ageMs: number;
|
|
9
|
+
} | null;
|
|
10
|
+
}
|
|
11
|
+
export declare function renderCockpit(snapshot: WorkspaceSnapshot, now: number, widthOrOpts?: number | RenderCockpitOptions): string[];
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
import { stateGlyph } from "./tmux-label.js";
|
|
3
|
+
export function formatBytes(n) {
|
|
4
|
+
const gb = n / (1024 ** 3);
|
|
5
|
+
if (gb >= 1)
|
|
6
|
+
return `${gb.toFixed(1)} GB`;
|
|
7
|
+
const mb = n / (1024 ** 2);
|
|
8
|
+
return `${mb.toFixed(0)} MB`;
|
|
9
|
+
}
|
|
10
|
+
export function relativeTime(ts, now) {
|
|
11
|
+
const s = Math.max(0, Math.round((now - ts) / 1000));
|
|
12
|
+
if (s < 60)
|
|
13
|
+
return `${s}s ago`;
|
|
14
|
+
const m = Math.round(s / 60);
|
|
15
|
+
if (m < 60)
|
|
16
|
+
return `${m}m ago`;
|
|
17
|
+
return `${Math.round(m / 60)}h ago`;
|
|
18
|
+
}
|
|
19
|
+
function paneRow(e, now) {
|
|
20
|
+
const name = e.identity.cwd ? basename(e.identity.cwd) : e.identity.command;
|
|
21
|
+
const label = e.semantics?.label ?? e.state;
|
|
22
|
+
const mem = e.resources ? formatBytes(e.resources.perPaneRss) : "—";
|
|
23
|
+
const activity = e.lastActivityTs ? relativeTime(e.lastActivityTs, now) : "—";
|
|
24
|
+
return `${stateGlyph(e.state)} ${name} ${label} [${mem}] ${activity}`;
|
|
25
|
+
}
|
|
26
|
+
export function unattributedLine(host) {
|
|
27
|
+
if (!host || host.unattributed <= 0)
|
|
28
|
+
return null;
|
|
29
|
+
return ` unattributed: ${formatBytes(host.unattributed)} (source outside tracked panes)`;
|
|
30
|
+
}
|
|
31
|
+
/** Normalizes the legacy positional `width` arg and the newer options object into one shape. */
|
|
32
|
+
function normalizeCockpitOptions(widthOrOpts) {
|
|
33
|
+
if (typeof widthOrOpts === "number")
|
|
34
|
+
return { width: widthOrOpts, stale: null };
|
|
35
|
+
return { width: widthOrOpts?.width ?? 120, stale: widthOrOpts?.stale ?? null };
|
|
36
|
+
}
|
|
37
|
+
export function renderCockpit(snapshot, now, widthOrOpts) {
|
|
38
|
+
const { stale } = normalizeCockpitOptions(widthOrOpts);
|
|
39
|
+
const lines = [];
|
|
40
|
+
if (stale)
|
|
41
|
+
lines.push(`⚠ daemon not connected — snapshot ${relativeTime(now - stale.ageMs, now)}`);
|
|
42
|
+
for (const g of snapshot.guardianLog.slice(-3))
|
|
43
|
+
lines.push(`⚠ ${g.message}`);
|
|
44
|
+
if (snapshot.guardianLog.length > 0)
|
|
45
|
+
lines.push("");
|
|
46
|
+
lines.push(`gmux — ${snapshot.panes.length} panes`);
|
|
47
|
+
// Sort panes by memory descending if any have resources
|
|
48
|
+
const hasResources = snapshot.panes.some((p) => p.resources);
|
|
49
|
+
const sortedPanes = hasResources
|
|
50
|
+
? [...snapshot.panes].sort((a, b) => (b.resources?.perPaneRss ?? 0) - (a.resources?.perPaneRss ?? 0))
|
|
51
|
+
: snapshot.panes;
|
|
52
|
+
for (const e of sortedPanes)
|
|
53
|
+
lines.push(paneRow(e, now));
|
|
54
|
+
// Add unattributed line if present
|
|
55
|
+
const unattr = unattributedLine(snapshot.hostPressure);
|
|
56
|
+
if (unattr)
|
|
57
|
+
lines.push(unattr);
|
|
58
|
+
return lines;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=gmux-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gmux-render.js","sourceRoot":"","sources":["../../src/cli/gmux-render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IAC3B,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAC1C,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IAC3B,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAU,EAAE,GAAW;IAClD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACrD,IAAI,CAAC,GAAG,EAAE;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,EAAE;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC/B,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;AACtC,CAAC;AAED,SAAS,OAAO,CAAC,CAAY,EAAE,GAAW;IACxC,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;IAC5E,MAAM,KAAK,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC;IAC5C,MAAM,GAAG,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACpE,MAAM,QAAQ,GAAG,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC9E,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,KAAK,MAAM,GAAG,MAAM,QAAQ,EAAE,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAyB;IACxD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACjD,OAAO,mBAAmB,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,iCAAiC,CAAC;AAC5F,CAAC;AAOD,gGAAgG;AAChG,SAAS,uBAAuB,CAAC,WAAsD;IACrF,IAAI,OAAO,WAAW,KAAK,QAAQ;QAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAChF,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,IAAI,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,IAAI,IAAI,EAAE,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,QAA2B,EAC3B,GAAW,EACX,WAA2C;IAE3C,MAAM,EAAE,KAAK,EAAE,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,qCAAqC,YAAY,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACnG,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7E,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,KAAK,CAAC,IAAI,CAAC,UAAU,QAAQ,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC;IAEpD,wDAAwD;IACxD,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC7D,MAAM,WAAW,GAAG,YAAY;QAC9B,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,UAAU,IAAI,CAAC,CAAC,CAAC;QACrG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;IAEnB,KAAK,MAAM,CAAC,IAAI,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAEzD,mCAAmC;IACnC,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IACvD,IAAI,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAE/B,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* gmux — browse, search and resume agent coding sessions.
|
|
4
|
+
*
|
|
5
|
+
* Every read command supports `--json`. That is deliberate: gmux is a tool
|
|
6
|
+
* for agents as much as for people, and an agent can only use what it can parse.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
package/dist/cli/main.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* gmux — browse, search and resume agent coding sessions.
|
|
4
|
+
*
|
|
5
|
+
* Every read command supports `--json`. That is deliberate: gmux is a tool
|
|
6
|
+
* for agents as much as for people, and an agent can only use what it can parse.
|
|
7
|
+
*/
|
|
8
|
+
import { createRequire } from "node:module";
|
|
9
|
+
import { Command } from "commander";
|
|
10
|
+
import { GmuxError } from "../core/errors.js";
|
|
11
|
+
import { maybeAutoSummarize } from "../services/auto-summarize.js";
|
|
12
|
+
import { configExists, shouldRunSetupWizard } from "../services/config.js";
|
|
13
|
+
import { registerAsk } from "./commands/ask.js";
|
|
14
|
+
import { registerAskCancel } from "./commands/__ask-cancel.js";
|
|
15
|
+
import { registerAskRun } from "./commands/__ask-run.js";
|
|
16
|
+
import { registerAskSend } from "./commands/__ask-send.js";
|
|
17
|
+
import { registerAutoSummarizeWorker } from "./commands/auto.js";
|
|
18
|
+
import { registerCockpit } from "./commands/cockpit.js";
|
|
19
|
+
import { registerDaemon } from "./commands/daemon.js";
|
|
20
|
+
import { registerDoctor } from "./commands/doctor.js";
|
|
21
|
+
import { registerSetup, runSetupWizard } from "./commands/setup.js";
|
|
22
|
+
import { registerGrep } from "./commands/grep.js";
|
|
23
|
+
import { registerIndex } from "./commands/index-cmd.js";
|
|
24
|
+
import { registerLs } from "./commands/ls.js";
|
|
25
|
+
import { registerOverlay } from "./commands/overlay.js";
|
|
26
|
+
import { registerWatch } from "./commands/watch.js";
|
|
27
|
+
import { registerPick } from "./commands/pick.js";
|
|
28
|
+
import { registerPickerRows } from "./commands/picker-rows.js";
|
|
29
|
+
import { registerPreviewCard } from "./commands/__preview-card.js";
|
|
30
|
+
import { registerResume } from "./commands/resume.js";
|
|
31
|
+
import { registerRun } from "./commands/run.js";
|
|
32
|
+
import { registerShow } from "./commands/show.js";
|
|
33
|
+
import { registerSummarize } from "./commands/summarize.js";
|
|
34
|
+
import { registerTmux } from "./commands/tmux.js";
|
|
35
|
+
import { red, dim } from "./format.js";
|
|
36
|
+
/**
|
|
37
|
+
* Read the version from package.json rather than hardcoding it.
|
|
38
|
+
*
|
|
39
|
+
* A hardcoded string silently drifts on every release — v0.1.1 shipped
|
|
40
|
+
* reporting `0.1.0`. Resolves to the package root from both `dist/cli/` (built)
|
|
41
|
+
* and `src/cli/` (via tsx).
|
|
42
|
+
*/
|
|
43
|
+
const { version } = createRequire(import.meta.url)("../../package.json");
|
|
44
|
+
const program = new Command();
|
|
45
|
+
program
|
|
46
|
+
.name("gmux")
|
|
47
|
+
.description("Browse, search and resume your AI coding agent sessions.")
|
|
48
|
+
.version(version)
|
|
49
|
+
.option("--no-color", "disable coloured output")
|
|
50
|
+
.option("--no-auto-summarize", "do not summarize recent sessions in the background")
|
|
51
|
+
.hook("preAction", async (thisCommand, actionCommand) => {
|
|
52
|
+
if (thisCommand.opts()["color"] === false)
|
|
53
|
+
process.env.NO_COLOR = "1";
|
|
54
|
+
/**
|
|
55
|
+
* First run: ask who to call, before spending anything on calling them.
|
|
56
|
+
*
|
|
57
|
+
* Every gate here is load-bearing. `gmux ls --json` is an interface agents
|
|
58
|
+
* call, and a version of it that can block on a human prompt is a broken
|
|
59
|
+
* interface whatever it prints — so no TTY, or `--json`, or a `__`-prefixed
|
|
60
|
+
* internal command means we say nothing and behave exactly as gmux did before
|
|
61
|
+
* config existed: autodetect and carry on.
|
|
62
|
+
*/
|
|
63
|
+
const gate = {
|
|
64
|
+
hasConfig: await configExists(),
|
|
65
|
+
isTty: process.stdin.isTTY === true && process.stdout.isTTY === true,
|
|
66
|
+
isJson: actionCommand.opts()["json"] === true,
|
|
67
|
+
commandName: actionCommand.name(),
|
|
68
|
+
};
|
|
69
|
+
if (shouldRunSetupWizard(gate))
|
|
70
|
+
await runSetupWizard({ firstRun: true });
|
|
71
|
+
})
|
|
72
|
+
/**
|
|
73
|
+
* Keep the ten most recent sessions summarized — in the background, always.
|
|
74
|
+
*
|
|
75
|
+
* This runs in `postAction`, after the command has already written its output,
|
|
76
|
+
* so `gmux ls` still returns in ~60ms. The work itself is handed to a detached
|
|
77
|
+
* child that outlives us (see services/auto-summarize.ts); we only decide, and
|
|
78
|
+
* we tell the user on STDERR so `gmux ls --json` stays machine-readable.
|
|
79
|
+
*
|
|
80
|
+
* The worker command is exempt, or it would spawn a copy of itself forever.
|
|
81
|
+
*/
|
|
82
|
+
.hook("postAction", async (thisCommand, actionCommand) => {
|
|
83
|
+
/**
|
|
84
|
+
* `__`-prefixed commands are the internals gmux spawns at itself, and none of
|
|
85
|
+
* them may decide anything here — by prefix, not by a list that the next
|
|
86
|
+
* hidden command has to remember to join. `__auto-summarize` would fork a
|
|
87
|
+
* copy of itself; `__picker-rows` runs its own pass first; `__ask-send`
|
|
88
|
+
* inherits fzf's env, so GMUX_CHILD is unset and every question typed
|
|
89
|
+
* into the chat pane would fork a summarize decision from inside fzf —
|
|
90
|
+
* whose `notify` writes to the stderr fzf is painting. Same convention
|
|
91
|
+
* `shouldRunSetupWizard` already uses.
|
|
92
|
+
*/
|
|
93
|
+
if (actionCommand.name().startsWith("__"))
|
|
94
|
+
return;
|
|
95
|
+
// `ls` and `pick` run the pass themselves, BEFORE rendering, so they can
|
|
96
|
+
// mark the rows they just kicked off with ◐. Running it again here would be
|
|
97
|
+
// a wasted decision — and for `pick` a badly timed one: its action ends in
|
|
98
|
+
// `resumeSession`, which waits on your harness, so this hook would not fire
|
|
99
|
+
// until you quit Claude Code.
|
|
100
|
+
if (actionCommand.name() === "ls" || actionCommand.name() === "pick")
|
|
101
|
+
return;
|
|
102
|
+
await maybeAutoSummarize({
|
|
103
|
+
enabled: thisCommand.opts()["autoSummarize"] !== false,
|
|
104
|
+
notify: (message) => process.stderr.write(`${dim(message)}\n`),
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
registerLs(program);
|
|
108
|
+
registerShow(program);
|
|
109
|
+
registerGrep(program);
|
|
110
|
+
registerAsk(program);
|
|
111
|
+
registerResume(program);
|
|
112
|
+
registerSummarize(program);
|
|
113
|
+
registerSetup(program);
|
|
114
|
+
registerIndex(program);
|
|
115
|
+
registerDoctor(program);
|
|
116
|
+
registerAutoSummarizeWorker(program);
|
|
117
|
+
registerPickerRows(program);
|
|
118
|
+
registerPreviewCard(program);
|
|
119
|
+
registerAskSend(program);
|
|
120
|
+
registerAskRun(program);
|
|
121
|
+
registerAskCancel(program);
|
|
122
|
+
registerPick(program); // Also the default action when `gmux` is run bare.
|
|
123
|
+
registerOverlay(program);
|
|
124
|
+
registerCockpit(program);
|
|
125
|
+
registerTmux(program);
|
|
126
|
+
registerRun(program);
|
|
127
|
+
registerWatch(program);
|
|
128
|
+
registerDaemon(program);
|
|
129
|
+
async function main() {
|
|
130
|
+
try {
|
|
131
|
+
await program.parseAsync(process.argv);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
if (error instanceof GmuxError) {
|
|
135
|
+
process.stderr.write(`${red("error")} ${error.message}\n`);
|
|
136
|
+
if (error.fix)
|
|
137
|
+
process.stderr.write(`${dim("fix")} ${error.fix}\n`);
|
|
138
|
+
process.exit(error.exitCode);
|
|
139
|
+
}
|
|
140
|
+
process.stderr.write(`${red("error")} ${error.message}\n`);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
void main();
|
|
145
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ask box that sits at the bottom of the ctrl-g overlay. Pure string
|
|
3
|
+
* layout — the command positions it on the popup and drives the keystrokes.
|
|
4
|
+
*/
|
|
5
|
+
/** Rows the ask box occupies at the bottom of the overlay. */
|
|
6
|
+
export declare const ASK_BOX_HEIGHT = 3;
|
|
7
|
+
/**
|
|
8
|
+
* The three lines of the ask box (top border, the input line, bottom border),
|
|
9
|
+
* each clipped to `width`. A long input scrolls so its tail stays visible.
|
|
10
|
+
*/
|
|
11
|
+
export declare function askBoxLines(input: string, width: number): string[];
|
|
12
|
+
/** The cursor's column (1-based) inside the input line, clamped to the field. */
|
|
13
|
+
export declare function askCursorColumn(input: string, width: number): number;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ask box that sits at the bottom of the ctrl-g overlay. Pure string
|
|
3
|
+
* layout — the command positions it on the popup and drives the keystrokes.
|
|
4
|
+
*/
|
|
5
|
+
/** Rows the ask box occupies at the bottom of the overlay. */
|
|
6
|
+
export const ASK_BOX_HEIGHT = 3;
|
|
7
|
+
const LABEL = "ask · Enter send · ^R refresh · ^G/Esc close";
|
|
8
|
+
/**
|
|
9
|
+
* The three lines of the ask box (top border, the input line, bottom border),
|
|
10
|
+
* each clipped to `width`. A long input scrolls so its tail stays visible.
|
|
11
|
+
*/
|
|
12
|
+
export function askBoxLines(input, width) {
|
|
13
|
+
const w = Math.max(12, Math.floor(width));
|
|
14
|
+
const inner = w - 2; // between the │ │ borders
|
|
15
|
+
const dashes = Math.max(0, inner - LABEL.length - 3);
|
|
16
|
+
const top = `╭─ ${LABEL} ${"─".repeat(dashes)}╮`.slice(0, w);
|
|
17
|
+
const field = inner - 2; // inside "│ … │"
|
|
18
|
+
const prompt = `> ${input}`;
|
|
19
|
+
const shown = prompt.length > field ? prompt.slice(prompt.length - field) : prompt;
|
|
20
|
+
const mid = `│ ${shown.padEnd(field, " ")} │`.slice(0, w);
|
|
21
|
+
const bottom = `╰${"─".repeat(inner)}╯`.slice(0, w);
|
|
22
|
+
return [top, mid, bottom];
|
|
23
|
+
}
|
|
24
|
+
/** The cursor's column (1-based) inside the input line, clamped to the field. */
|
|
25
|
+
export function askCursorColumn(input, width) {
|
|
26
|
+
const inner = Math.max(12, Math.floor(width)) - 2;
|
|
27
|
+
const field = inner - 2;
|
|
28
|
+
const prompt = `> ${input}`;
|
|
29
|
+
const offset = Math.min(prompt.length, field);
|
|
30
|
+
return 3 + offset; // "│ " is 2 cols, field starts at col 3
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=overlay-ask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay-ask.js","sourceRoot":"","sources":["../../src/cli/overlay-ask.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC,MAAM,KAAK,GAAG,8CAA8C,CAAC;AAE7D;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,KAAa;IACtD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,0BAA0B;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE7D,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,iBAAiB;IAC1C,MAAM,MAAM,GAAG,KAAK,KAAK,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACnF,MAAM,GAAG,GAAG,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE1D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,KAAa;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC;IACxB,MAAM,MAAM,GAAG,KAAK,KAAK,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,wCAAwC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Draw every pane's summary card in place. Pure: given resolved cells and the
|
|
3
|
+
* clock, produce one string of ANSI cursor moves that paints a full-screen
|
|
4
|
+
* overlay. The command layer supplies the cells and the terminal; nothing here
|
|
5
|
+
* reads tmux, stdin, or the clock on its own.
|
|
6
|
+
*
|
|
7
|
+
* A compact sibling of `formatCard`: same summary fields and section names,
|
|
8
|
+
* sized to a rectangle with a degradation ladder — full card, then title +
|
|
9
|
+
* what-landed, then just the title, then a muted placeholder for a pane with no
|
|
10
|
+
* agent. Monochrome: the structure is carried by layout, so it survives a pane
|
|
11
|
+
* that cannot render colour.
|
|
12
|
+
*/
|
|
13
|
+
import type { SessionView, TmuxPane } from "../core/types.js";
|
|
14
|
+
export interface OverlayCell {
|
|
15
|
+
pane: TmuxPane;
|
|
16
|
+
/** null when the pane runs no resolvable agent. */
|
|
17
|
+
view: SessionView | null;
|
|
18
|
+
/** True while a background refresh for this session is in flight. */
|
|
19
|
+
refreshing: boolean;
|
|
20
|
+
/** A broadcast question is being answered for this pane's session right now. */
|
|
21
|
+
asking?: boolean;
|
|
22
|
+
/** This pane's own answer to the current broadcast question, if it has landed. */
|
|
23
|
+
answer?: string | null;
|
|
24
|
+
}
|
|
25
|
+
export declare function cellLines(cell: OverlayCell, width: number, height: number, now: Date): string[];
|
|
26
|
+
export declare function renderOverlay(cells: readonly OverlayCell[], now?: Date): string;
|