@gigaflow/gmux 0.15.0 → 0.16.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 +110 -80
- package/README.md +81 -57
- package/dist/adapters/claude-code.js +5 -2
- package/dist/adapters/claude-code.js.map +1 -1
- package/dist/adapters/codex.js +5 -2
- package/dist/adapters/codex.js.map +1 -1
- package/dist/cli/border-client.d.ts +1 -1
- package/dist/cli/border-client.js +1 -1
- package/dist/cli/commands/cockpit.d.ts +16 -6
- package/dist/cli/commands/cockpit.js +288 -20
- package/dist/cli/commands/cockpit.js.map +1 -1
- package/dist/cli/commands/daemon.d.ts +2 -19
- package/dist/cli/commands/daemon.js +39 -88
- package/dist/cli/commands/daemon.js.map +1 -1
- package/dist/cli/commands/doctor.js +24 -0
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/organize.d.ts +18 -0
- package/dist/cli/commands/organize.js +94 -0
- package/dist/cli/commands/organize.js.map +1 -0
- package/dist/cli/commands/setup.js +13 -1
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/tmux.d.ts +56 -0
- package/dist/cli/commands/tmux.js +158 -28
- package/dist/cli/commands/tmux.js.map +1 -1
- package/dist/cli/gmux-render.d.ts +12 -1
- package/dist/cli/gmux-render.js +18 -11
- package/dist/cli/gmux-render.js.map +1 -1
- package/dist/cli/main.js +2 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/organize-confirm.d.ts +45 -0
- package/dist/cli/organize-confirm.js +57 -0
- package/dist/cli/organize-confirm.js.map +1 -0
- package/dist/cli/overlay-ask.d.ts +3 -1
- package/dist/cli/overlay-ask.js +5 -3
- package/dist/cli/overlay-ask.js.map +1 -1
- package/dist/cli/tmux-label.d.ts +11 -4
- package/dist/cli/tmux-label.js +17 -6
- package/dist/cli/tmux-label.js.map +1 -1
- package/dist/cli/work-report.d.ts +18 -0
- package/dist/cli/work-report.js +50 -0
- package/dist/cli/work-report.js.map +1 -0
- package/dist/core/bytes.d.ts +6 -0
- package/dist/core/bytes.js +13 -0
- package/dist/core/bytes.js.map +1 -0
- package/dist/core/organize-types.d.ts +95 -0
- package/dist/core/organize-types.js +33 -0
- package/dist/core/organize-types.js.map +1 -0
- package/dist/core/paths.d.ts +13 -0
- package/dist/core/paths.js +20 -1
- package/dist/core/paths.js.map +1 -1
- package/dist/services/ask-router.d.ts +44 -0
- package/dist/services/ask-router.js +63 -0
- package/dist/services/ask-router.js.map +1 -0
- package/dist/services/daemon-lock.d.ts +31 -0
- package/dist/services/daemon-lock.js +77 -0
- package/dist/services/daemon-lock.js.map +1 -0
- package/dist/services/daemon.js +35 -6
- package/dist/services/daemon.js.map +1 -1
- package/dist/services/guardian.js +4 -4
- package/dist/services/guardian.js.map +1 -1
- package/dist/services/organize.d.ts +91 -0
- package/dist/services/organize.js +462 -0
- package/dist/services/organize.js.map +1 -0
- package/dist/services/tmux-gateway.d.ts +12 -0
- package/dist/services/tmux-gateway.js +7 -1
- package/dist/services/tmux-gateway.js.map +1 -1
- package/dist/services/tmux.d.ts +17 -1
- package/dist/services/tmux.js +34 -1
- package/dist/services/tmux.js.map +1 -1
- package/dist/services/work-view.d.ts +67 -0
- package/dist/services/work-view.js +155 -0
- package/dist/services/work-view.js.map +1 -0
- package/package.json +1 -1
package/dist/cli/gmux-render.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { basename } from "node:path";
|
|
2
|
+
import { formatBytes } from "../core/bytes.js";
|
|
2
3
|
import { stateGlyph } from "./tmux-label.js";
|
|
3
|
-
export
|
|
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
|
-
}
|
|
4
|
+
export { formatBytes };
|
|
10
5
|
export function relativeTime(ts, now) {
|
|
11
6
|
const s = Math.max(0, Math.round((now - ts) / 1000));
|
|
12
7
|
if (s < 60)
|
|
@@ -31,14 +26,16 @@ export function unattributedLine(host) {
|
|
|
31
26
|
/** Normalizes the legacy positional `width` arg and the newer options object into one shape. */
|
|
32
27
|
function normalizeCockpitOptions(widthOrOpts) {
|
|
33
28
|
if (typeof widthOrOpts === "number")
|
|
34
|
-
return { width: widthOrOpts, stale: null };
|
|
35
|
-
return { width: widthOrOpts?.width ?? 120, stale: widthOrOpts?.stale ?? null };
|
|
29
|
+
return { width: widthOrOpts, stale: null, status: null, ask: null };
|
|
30
|
+
return { width: widthOrOpts?.width ?? 120, stale: widthOrOpts?.stale ?? null, status: widthOrOpts?.status ?? null, ask: widthOrOpts?.ask ?? null };
|
|
36
31
|
}
|
|
37
32
|
export function renderCockpit(snapshot, now, widthOrOpts) {
|
|
38
|
-
const { stale } = normalizeCockpitOptions(widthOrOpts);
|
|
33
|
+
const { width, stale, status, ask } = normalizeCockpitOptions(widthOrOpts);
|
|
39
34
|
const lines = [];
|
|
40
35
|
if (stale)
|
|
41
36
|
lines.push(`⚠ daemon not connected — snapshot ${relativeTime(now - stale.ageMs, now)}`);
|
|
37
|
+
if (status)
|
|
38
|
+
lines.push(status);
|
|
42
39
|
for (const g of snapshot.guardianLog.slice(-3))
|
|
43
40
|
lines.push(`⚠ ${g.message}`);
|
|
44
41
|
if (snapshot.guardianLog.length > 0)
|
|
@@ -55,6 +52,16 @@ export function renderCockpit(snapshot, now, widthOrOpts) {
|
|
|
55
52
|
const unattr = unattributedLine(snapshot.hostPressure);
|
|
56
53
|
if (unattr)
|
|
57
54
|
lines.push(unattr);
|
|
58
|
-
|
|
55
|
+
// A broadcast question's per-session answers, terse (one clipped line each).
|
|
56
|
+
if (ask && ask.rows.length > 0) {
|
|
57
|
+
lines.push("", `» ${ask.question}`);
|
|
58
|
+
for (const r of ask.rows)
|
|
59
|
+
lines.push(` ${r.label}: ${r.answer ?? "⧗ asking…"}`);
|
|
60
|
+
}
|
|
61
|
+
lines.push("", "⌃v: work report");
|
|
62
|
+
// Hard clip to width — not word-aware, matches the terse style elsewhere
|
|
63
|
+
// in this file. Every line (banner, guardian warnings, header, pane rows,
|
|
64
|
+
// unattributed line) goes through the same clip uniformly.
|
|
65
|
+
return lines.map((l) => (l.length > width ? l.slice(0, width) : l));
|
|
59
66
|
}
|
|
60
67
|
//# sourceMappingURL=gmux-render.js.map
|
|
@@ -1 +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;
|
|
1
|
+
{"version":3,"file":"gmux-render.js","sourceRoot":"","sources":["../../src/cli/gmux-render.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/main.js
CHANGED
|
@@ -22,6 +22,7 @@ import { registerSetup, runSetupWizard } from "./commands/setup.js";
|
|
|
22
22
|
import { registerGrep } from "./commands/grep.js";
|
|
23
23
|
import { registerIndex } from "./commands/index-cmd.js";
|
|
24
24
|
import { registerLs } from "./commands/ls.js";
|
|
25
|
+
import { registerOrganize } from "./commands/organize.js";
|
|
25
26
|
import { registerOverlay } from "./commands/overlay.js";
|
|
26
27
|
import { registerWatch } from "./commands/watch.js";
|
|
27
28
|
import { registerPick } from "./commands/pick.js";
|
|
@@ -123,6 +124,7 @@ registerPick(program); // Also the default action when `gmux` is run bare.
|
|
|
123
124
|
registerOverlay(program);
|
|
124
125
|
registerCockpit(program);
|
|
125
126
|
registerTmux(program);
|
|
127
|
+
registerOrganize(program);
|
|
126
128
|
registerRun(program);
|
|
127
129
|
registerWatch(program);
|
|
128
130
|
registerDaemon(program);
|
package/dist/cli/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The organize confirm-state for the ctrl-g cockpit prompt. Pure string layout
|
|
3
|
+
* and pure key classification — the command owns the terminal and the async
|
|
4
|
+
* plan, and calls these to render the preview and to interpret a keystroke.
|
|
5
|
+
*
|
|
6
|
+
* When the cockpit prompt classifies as a reorganization, the cockpit shows the
|
|
7
|
+
* numbered plan and waits for the user to confirm. NOTHING is applied without
|
|
8
|
+
* that confirmation — this is the preview half of preview-then-apply.
|
|
9
|
+
*/
|
|
10
|
+
import { type OrganizePlan } from "../core/organize-types.js";
|
|
11
|
+
/** The hint shown under the plan: how to apply or back out. */
|
|
12
|
+
export declare const CONFIRM_HINT = "[Enter] apply [Esc] cancel";
|
|
13
|
+
/**
|
|
14
|
+
* The confirm screen: the numbered plan, a blank line, then the hint. Pure, so
|
|
15
|
+
* the rendering is tested without a terminal; the command positions it.
|
|
16
|
+
*/
|
|
17
|
+
export declare function confirmFrameLines(plan: OrganizePlan): string[];
|
|
18
|
+
/**
|
|
19
|
+
* A monotonic generation guard for the cockpit's async submit flow.
|
|
20
|
+
*
|
|
21
|
+
* Each submit claims a fresh generation with `next()`. A cancel (Esc/ctrl-g
|
|
22
|
+
* while planning) also calls `next()`, invalidating whatever classify/plan is
|
|
23
|
+
* in flight. When that awaited work resolves it checks `isCurrent(gen)` — false
|
|
24
|
+
* means the user backed out (or started another submit) meanwhile, so the late
|
|
25
|
+
* result is DROPPED and can never pop a confirm screen after the user left the
|
|
26
|
+
* planning state. Pure and synchronous, so the guard decision is unit-tested
|
|
27
|
+
* without the raw-mode loop.
|
|
28
|
+
*/
|
|
29
|
+
export declare function makeGeneration(): {
|
|
30
|
+
next: () => number;
|
|
31
|
+
isCurrent: (gen: number) => boolean;
|
|
32
|
+
};
|
|
33
|
+
/** What a keystroke means while the confirm screen is up. */
|
|
34
|
+
export type ConfirmAction = "apply" | "cancel" | "exit" | "ignore";
|
|
35
|
+
/**
|
|
36
|
+
* Classify a keystroke in the confirm state:
|
|
37
|
+
* - Enter / y → apply the plan
|
|
38
|
+
* - Esc / n → cancel back to the ask box
|
|
39
|
+
* - ctrl-c / ctrl-d → exit the cockpit entirely (the long-standing hard exits)
|
|
40
|
+
* - anything else → ignore (the plan stays on screen)
|
|
41
|
+
*
|
|
42
|
+
* Esc cancels here rather than closing the cockpit: with a plan on screen the
|
|
43
|
+
* least-surprising "escape" is out of the confirmation, not out of the peek.
|
|
44
|
+
*/
|
|
45
|
+
export declare function confirmKey(s: string): ConfirmAction;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The organize confirm-state for the ctrl-g cockpit prompt. Pure string layout
|
|
3
|
+
* and pure key classification — the command owns the terminal and the async
|
|
4
|
+
* plan, and calls these to render the preview and to interpret a keystroke.
|
|
5
|
+
*
|
|
6
|
+
* When the cockpit prompt classifies as a reorganization, the cockpit shows the
|
|
7
|
+
* numbered plan and waits for the user to confirm. NOTHING is applied without
|
|
8
|
+
* that confirmation — this is the preview half of preview-then-apply.
|
|
9
|
+
*/
|
|
10
|
+
import { organizePreviewLines } from "../core/organize-types.js";
|
|
11
|
+
/** The hint shown under the plan: how to apply or back out. */
|
|
12
|
+
export const CONFIRM_HINT = "[Enter] apply [Esc] cancel";
|
|
13
|
+
/**
|
|
14
|
+
* The confirm screen: the numbered plan, a blank line, then the hint. Pure, so
|
|
15
|
+
* the rendering is tested without a terminal; the command positions it.
|
|
16
|
+
*/
|
|
17
|
+
export function confirmFrameLines(plan) {
|
|
18
|
+
return [...organizePreviewLines(plan), "", CONFIRM_HINT];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A monotonic generation guard for the cockpit's async submit flow.
|
|
22
|
+
*
|
|
23
|
+
* Each submit claims a fresh generation with `next()`. A cancel (Esc/ctrl-g
|
|
24
|
+
* while planning) also calls `next()`, invalidating whatever classify/plan is
|
|
25
|
+
* in flight. When that awaited work resolves it checks `isCurrent(gen)` — false
|
|
26
|
+
* means the user backed out (or started another submit) meanwhile, so the late
|
|
27
|
+
* result is DROPPED and can never pop a confirm screen after the user left the
|
|
28
|
+
* planning state. Pure and synchronous, so the guard decision is unit-tested
|
|
29
|
+
* without the raw-mode loop.
|
|
30
|
+
*/
|
|
31
|
+
export function makeGeneration() {
|
|
32
|
+
let current = 0;
|
|
33
|
+
return {
|
|
34
|
+
next: () => (current += 1),
|
|
35
|
+
isCurrent: (gen) => gen === current,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Classify a keystroke in the confirm state:
|
|
40
|
+
* - Enter / y → apply the plan
|
|
41
|
+
* - Esc / n → cancel back to the ask box
|
|
42
|
+
* - ctrl-c / ctrl-d → exit the cockpit entirely (the long-standing hard exits)
|
|
43
|
+
* - anything else → ignore (the plan stays on screen)
|
|
44
|
+
*
|
|
45
|
+
* Esc cancels here rather than closing the cockpit: with a plan on screen the
|
|
46
|
+
* least-surprising "escape" is out of the confirmation, not out of the peek.
|
|
47
|
+
*/
|
|
48
|
+
export function confirmKey(s) {
|
|
49
|
+
if (s === "\x03" || s === "\x04")
|
|
50
|
+
return "exit";
|
|
51
|
+
if (s === "\r" || s === "\n" || s === "y" || s === "Y")
|
|
52
|
+
return "apply";
|
|
53
|
+
if (s === "\x1b" || s === "n" || s === "N")
|
|
54
|
+
return "cancel";
|
|
55
|
+
return "ignore";
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=organize-confirm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organize-confirm.js","sourceRoot":"","sources":["../../src/cli/organize-confirm.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,oBAAoB,EAAqB,MAAM,2BAA2B,CAAC;AAEpF,+DAA+D;AAC/D,MAAM,CAAC,MAAM,YAAY,GAAG,6BAA6B,CAAC;AAE1D;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAkB;IAClD,OAAO,CAAC,GAAG,oBAAoB,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,YAAY,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,OAAO;QACL,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;QAC1B,SAAS,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG,KAAK,OAAO;KAC5C,CAAC;AACJ,CAAC;AAKD;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC;IAChD,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;QAAE,OAAO,OAAO,CAAC;IACvE,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG;QAAE,OAAO,QAAQ,CAAC;IAC5D,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -7,7 +7,9 @@ export declare const ASK_BOX_HEIGHT = 3;
|
|
|
7
7
|
/**
|
|
8
8
|
* The three lines of the ask box (top border, the input line, bottom border),
|
|
9
9
|
* each clipped to `width`. A long input scrolls so its tail stays visible.
|
|
10
|
+
* `label` overrides the border caption (the cockpit's box does ask AND
|
|
11
|
+
* organize, so it names both); the overlay keeps the default.
|
|
10
12
|
*/
|
|
11
|
-
export declare function askBoxLines(input: string, width: number): string[];
|
|
13
|
+
export declare function askBoxLines(input: string, width: number, label?: string): string[];
|
|
12
14
|
/** The cursor's column (1-based) inside the input line, clamped to the field. */
|
|
13
15
|
export declare function askCursorColumn(input: string, width: number): number;
|
package/dist/cli/overlay-ask.js
CHANGED
|
@@ -8,12 +8,14 @@ const LABEL = "ask · Enter send · ^R refresh · ^G/Esc close";
|
|
|
8
8
|
/**
|
|
9
9
|
* The three lines of the ask box (top border, the input line, bottom border),
|
|
10
10
|
* each clipped to `width`. A long input scrolls so its tail stays visible.
|
|
11
|
+
* `label` overrides the border caption (the cockpit's box does ask AND
|
|
12
|
+
* organize, so it names both); the overlay keeps the default.
|
|
11
13
|
*/
|
|
12
|
-
export function askBoxLines(input, width) {
|
|
14
|
+
export function askBoxLines(input, width, label = LABEL) {
|
|
13
15
|
const w = Math.max(12, Math.floor(width));
|
|
14
16
|
const inner = w - 2; // between the │ │ borders
|
|
15
|
-
const dashes = Math.max(0, inner -
|
|
16
|
-
const top = `╭─ ${
|
|
17
|
+
const dashes = Math.max(0, inner - label.length - 3);
|
|
18
|
+
const top = `╭─ ${label} ${"─".repeat(dashes)}╮`.slice(0, w);
|
|
17
19
|
const field = inner - 2; // inside "│ … │"
|
|
18
20
|
const prompt = `> ${input}`;
|
|
19
21
|
const shown = prompt.length > field ? prompt.slice(prompt.length - field) : prompt;
|
|
@@ -1 +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
|
|
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;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,KAAa,EAAE,QAAgB,KAAK;IAC7E,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"}
|
package/dist/cli/tmux-label.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* pane title and shown on the pane border. The `gmux watch` service repaints these
|
|
4
4
|
* on a loop; `Alt-g` toggles the service.
|
|
5
5
|
*
|
|
6
|
-
* Labels live in a per-pane `@
|
|
6
|
+
* Labels live in a per-pane `@gmux_label` option, NOT `#{pane_title}`: a running
|
|
7
7
|
* agent sets its pane title via OSC escape sequences (a progress spinner), which
|
|
8
8
|
* would clobber a title we wrote. A `@`-prefixed user option is ours alone.
|
|
9
9
|
*/
|
|
@@ -25,7 +25,7 @@ export declare function stateGlyph(state: PaneState): string;
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function snapshotLabel(entry: PaneEntry): string;
|
|
27
27
|
/**
|
|
28
|
-
* Resolve a set of panes and write each one's `@
|
|
28
|
+
* Resolve a set of panes and write each one's `@gmux_label`. Returns the resolved
|
|
29
29
|
* session records, so the caller can feed exactly the on-screen sessions to the
|
|
30
30
|
* summariser. No model calls here — labels render from the cache.
|
|
31
31
|
*/
|
|
@@ -37,7 +37,7 @@ export declare function enableBorder(): Promise<void>;
|
|
|
37
37
|
/**
|
|
38
38
|
* Hide the label borders. Sets the global off, then clears any per-window
|
|
39
39
|
* override (older versions set `pane-border-status` per window, which would
|
|
40
|
-
* override the global and keep the border up) and wipes every pane's `@
|
|
40
|
+
* override the global and keep the border up) and wipes every pane's `@gmux_label`,
|
|
41
41
|
* so no headline lingers regardless of theme or leftover settings.
|
|
42
42
|
*/
|
|
43
43
|
export declare function disableBorder(): Promise<void>;
|
|
@@ -46,5 +46,12 @@ export declare function disableBorder(): Promise<void>;
|
|
|
46
46
|
* paint an immediate first frame for the current window, start the watcher); off
|
|
47
47
|
* when on (stop the watcher, hide the borders). "On" is the service running, not
|
|
48
48
|
* the border option — a theme may set the border for its own reasons.
|
|
49
|
+
*
|
|
50
|
+
* When `gmux daemon` is live, it already owns every pane's border (it repaints
|
|
51
|
+
* `@gmux_label` on every model change — see `commands/daemon.ts`'s `onChange`).
|
|
52
|
+
* Starting the legacy watcher loop on top of that would fight the daemon for
|
|
53
|
+
* the same option, so turning the watcher ON no-ops with `"daemon-owned"`
|
|
54
|
+
* instead. Turning it off is always safe (there is nothing for the daemon
|
|
55
|
+
* path to interfere with), so that branch is untouched.
|
|
49
56
|
*/
|
|
50
|
-
export declare function toggleWatch(windowId: string): Promise<"on" | "off">;
|
|
57
|
+
export declare function toggleWatch(windowId: string): Promise<"on" | "off" | "daemon-owned">;
|
package/dist/cli/tmux-label.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* pane title and shown on the pane border. The `gmux watch` service repaints these
|
|
4
4
|
* on a loop; `Alt-g` toggles the service.
|
|
5
5
|
*
|
|
6
|
-
* Labels live in a per-pane `@
|
|
6
|
+
* Labels live in a per-pane `@gmux_label` option, NOT `#{pane_title}`: a running
|
|
7
7
|
* agent sets its pane title via OSC escape sequences (a progress spinner), which
|
|
8
8
|
* would clobber a title we wrote. A `@`-prefixed user option is ours alone.
|
|
9
9
|
*/
|
|
@@ -11,6 +11,7 @@ import { execFile } from "node:child_process";
|
|
|
11
11
|
import { basename } from "node:path";
|
|
12
12
|
import { promisify } from "node:util";
|
|
13
13
|
import { inProgressIds } from "../services/auto-summarize.js";
|
|
14
|
+
import { isDaemonLockStale, readDaemonLock } from "../services/daemon-lock.js";
|
|
14
15
|
import { prunePaneLinks } from "../services/pane-links.js";
|
|
15
16
|
import { listAllPanes, listPanes } from "../services/tmux.js";
|
|
16
17
|
import { resolvePanesLive } from "../services/tmux-resolve.js";
|
|
@@ -22,7 +23,7 @@ const run = promisify(execFile);
|
|
|
22
23
|
* doesn't inherit a themed, dimmed `pane-border-style` (which would leave every
|
|
23
24
|
* inactive pane's label invisible).
|
|
24
25
|
*/
|
|
25
|
-
const PANE_BORDER_FORMAT = "#[align=centre]#[fg=colour252]#{?pane_active,#[reverse],} #{@
|
|
26
|
+
const PANE_BORDER_FORMAT = "#[align=centre]#[fg=colour252]#{?pane_active,#[reverse],} #{@gmux_label} #[default]";
|
|
26
27
|
/**
|
|
27
28
|
* The label for a pane: `project — headline`, `project — gmux summaries loading…`
|
|
28
29
|
* while a refresh is in flight, `○ project` when resolved but not yet summarised,
|
|
@@ -64,7 +65,7 @@ async function tmux(args) {
|
|
|
64
65
|
return stdout;
|
|
65
66
|
}
|
|
66
67
|
/**
|
|
67
|
-
* Resolve a set of panes and write each one's `@
|
|
68
|
+
* Resolve a set of panes and write each one's `@gmux_label`. Returns the resolved
|
|
68
69
|
* session records, so the caller can feed exactly the on-screen sessions to the
|
|
69
70
|
* summariser. No model calls here — labels render from the cache.
|
|
70
71
|
*/
|
|
@@ -83,7 +84,7 @@ export async function labelPanes(panes) {
|
|
|
83
84
|
? bySession.get(record.sessionId) ?? { record, summary: null }
|
|
84
85
|
: null;
|
|
85
86
|
const isRefreshing = record ? refreshing.has(record.sessionId) : false;
|
|
86
|
-
await tmux(["set-option", "-p", "-t", pane.paneId, "@
|
|
87
|
+
await tmux(["set-option", "-p", "-t", pane.paneId, "@gmux_label", paneLabel(view, isRefreshing)]);
|
|
87
88
|
}
|
|
88
89
|
return present;
|
|
89
90
|
}
|
|
@@ -111,7 +112,7 @@ export async function enableBorder() {
|
|
|
111
112
|
/**
|
|
112
113
|
* Hide the label borders. Sets the global off, then clears any per-window
|
|
113
114
|
* override (older versions set `pane-border-status` per window, which would
|
|
114
|
-
* override the global and keep the border up) and wipes every pane's `@
|
|
115
|
+
* override the global and keep the border up) and wipes every pane's `@gmux_label`,
|
|
115
116
|
* so no headline lingers regardless of theme or leftover settings.
|
|
116
117
|
*/
|
|
117
118
|
export async function disableBorder() {
|
|
@@ -119,7 +120,7 @@ export async function disableBorder() {
|
|
|
119
120
|
try {
|
|
120
121
|
await clearWindowOverrides();
|
|
121
122
|
for (const pane of await listAllPanes()) {
|
|
122
|
-
await tmux(["set-option", "-p", "-u", "-t", pane.paneId, "@
|
|
123
|
+
await tmux(["set-option", "-p", "-u", "-t", pane.paneId, "@gmux_label"]);
|
|
123
124
|
}
|
|
124
125
|
}
|
|
125
126
|
catch {
|
|
@@ -131,6 +132,13 @@ export async function disableBorder() {
|
|
|
131
132
|
* paint an immediate first frame for the current window, start the watcher); off
|
|
132
133
|
* when on (stop the watcher, hide the borders). "On" is the service running, not
|
|
133
134
|
* the border option — a theme may set the border for its own reasons.
|
|
135
|
+
*
|
|
136
|
+
* When `gmux daemon` is live, it already owns every pane's border (it repaints
|
|
137
|
+
* `@gmux_label` on every model change — see `commands/daemon.ts`'s `onChange`).
|
|
138
|
+
* Starting the legacy watcher loop on top of that would fight the daemon for
|
|
139
|
+
* the same option, so turning the watcher ON no-ops with `"daemon-owned"`
|
|
140
|
+
* instead. Turning it off is always safe (there is nothing for the daemon
|
|
141
|
+
* path to interfere with), so that branch is untouched.
|
|
134
142
|
*/
|
|
135
143
|
export async function toggleWatch(windowId) {
|
|
136
144
|
if (await isWatchRunning()) {
|
|
@@ -138,6 +146,9 @@ export async function toggleWatch(windowId) {
|
|
|
138
146
|
await disableBorder();
|
|
139
147
|
return "off";
|
|
140
148
|
}
|
|
149
|
+
const lock = await readDaemonLock();
|
|
150
|
+
if (lock && !isDaemonLockStale(lock))
|
|
151
|
+
return "daemon-owned";
|
|
141
152
|
await enableBorder();
|
|
142
153
|
await paintLabels(windowId); // instant first paint, before the loop's first tick
|
|
143
154
|
await startWatch();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tmux-label.js","sourceRoot":"","sources":["../../src/cli/tmux-label.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAItC,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EACL,cAAc,EACd,UAAU,EACV,SAAS,GACV,MAAM,sBAAsB,CAAC;AAE9B,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAEhC;;;;GAIG;AACH,MAAM,kBAAkB,GACtB,
|
|
1
|
+
{"version":3,"file":"tmux-label.js","sourceRoot":"","sources":["../../src/cli/tmux-label.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The work report: the wide-angle bottom of gmux's attention funnel. A pure
|
|
3
|
+
* assembly of per-session cards into one self-contained HTML page — no external
|
|
4
|
+
* references of any kind. Each model-generated fragment is UNTRUSTED and is
|
|
5
|
+
* embedded via a sandboxed <iframe srcdoc>, which is the trust boundary: bad
|
|
6
|
+
* markup can only affect its own card, never the shell or a sibling.
|
|
7
|
+
*/
|
|
8
|
+
export interface WorkReportCard {
|
|
9
|
+
/** Pane/project label — trusted chrome, escaped. */
|
|
10
|
+
label: string;
|
|
11
|
+
/** Session summary headline, if one exists — trusted chrome, escaped. */
|
|
12
|
+
headline: string | null;
|
|
13
|
+
/** The model fragment. null → render `note` instead. */
|
|
14
|
+
html: string | null;
|
|
15
|
+
/** Shown when there is no fragment (no provider, or generation failed). */
|
|
16
|
+
note: string | null;
|
|
17
|
+
}
|
|
18
|
+
export declare function renderWorkReportHtml(cards: readonly WorkReportCard[], now: number): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The work report: the wide-angle bottom of gmux's attention funnel. A pure
|
|
3
|
+
* assembly of per-session cards into one self-contained HTML page — no external
|
|
4
|
+
* references of any kind. Each model-generated fragment is UNTRUSTED and is
|
|
5
|
+
* embedded via a sandboxed <iframe srcdoc>, which is the trust boundary: bad
|
|
6
|
+
* markup can only affect its own card, never the shell or a sibling.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Escape text into our own HTML — element content OR a double-quoted attribute,
|
|
10
|
+
* including a `srcdoc`. Escaping `<`/`>` here is correct, not corrupting: the
|
|
11
|
+
* browser attribute-unescapes `srcdoc` (`<`→`<`) BEFORE parsing its value as
|
|
12
|
+
* a document, so `<svg>` and a literal `<svg>` render identically — and
|
|
13
|
+
* full escaping keeps the attribute well-formed. The sandbox contains the
|
|
14
|
+
* fragment's behavior; this escaping keeps our page well-formed around it.
|
|
15
|
+
*/
|
|
16
|
+
function esc(s) {
|
|
17
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
18
|
+
}
|
|
19
|
+
const STYLE = `
|
|
20
|
+
:root { color-scheme: light dark; }
|
|
21
|
+
body { margin: 0; font: 14px/1.5 system-ui, sans-serif; background: Canvas; color: CanvasText; }
|
|
22
|
+
header { padding: 12px 20px; border-bottom: 1px solid GrayText; font-weight: 600; }
|
|
23
|
+
main { display: grid; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); gap: 16px; padding: 20px; }
|
|
24
|
+
section.card { border: 1px solid GrayText; border-radius: 8px; overflow: hidden; }
|
|
25
|
+
section.card > h2 { margin: 0; padding: 10px 14px; font-size: 14px; border-bottom: 1px solid GrayText; }
|
|
26
|
+
section.card > .headline { margin: 0; padding: 6px 14px; opacity: 0.75; font-size: 13px; }
|
|
27
|
+
iframe { width: 100%; min-height: 240px; border: 0; background: Canvas; }
|
|
28
|
+
p.note { margin: 0; padding: 16px; opacity: 0.7; }
|
|
29
|
+
`;
|
|
30
|
+
function card(c) {
|
|
31
|
+
const head = `<h2>${esc(c.label)}</h2>` +
|
|
32
|
+
(c.headline ? `<p class="headline">${esc(c.headline)}</p>` : "");
|
|
33
|
+
const body = c.html
|
|
34
|
+
? `<iframe sandbox srcdoc="${esc(c.html)}"></iframe>`
|
|
35
|
+
: `<p class="note">${esc(c.note ?? "no work view")}</p>`;
|
|
36
|
+
return `<section class="card">${head}${body}</section>`;
|
|
37
|
+
}
|
|
38
|
+
export function renderWorkReportHtml(cards, now) {
|
|
39
|
+
const when = new Date(now).toISOString();
|
|
40
|
+
const title = `gmux work report · ${cards.length} session${cards.length === 1 ? "" : "s"} · ${when}`;
|
|
41
|
+
const main = cards.length === 0
|
|
42
|
+
? `<main><p class="note">No sessions to report.</p></main>`
|
|
43
|
+
: `<main>${cards.map(card).join("")}</main>`;
|
|
44
|
+
return (`<!doctype html><html lang="en"><head><meta charset="utf-8">` +
|
|
45
|
+
`<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src data:; style-src 'unsafe-inline'; font-src data:">` +
|
|
46
|
+
`<meta name="viewport" content="width=device-width, initial-scale=1">` +
|
|
47
|
+
`<title>gmux work report</title><style>${STYLE}</style></head>` +
|
|
48
|
+
`<body><header>${esc(title)}</header>${main}</body></html>`);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=work-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"work-report.js","sourceRoot":"","sources":["../../src/cli/work-report.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH;;;;;;;GAOG;AACH,SAAS,GAAG,CAAC,CAAS;IACpB,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACtG,CAAC;AAED,MAAM,KAAK,GAAG;;;;;;;;;;CAUb,CAAC;AAEF,SAAS,IAAI,CAAC,CAAiB;IAC7B,MAAM,IAAI,GACR,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO;QAC1B,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,uBAAuB,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI;QACjB,CAAC,CAAC,2BAA2B,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa;QACrD,CAAC,CAAC,mBAAmB,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,cAAc,CAAC,MAAM,CAAC;IAC3D,OAAO,yBAAyB,IAAI,GAAG,IAAI,YAAY,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAgC,EAAE,GAAW;IAChF,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,sBAAsB,KAAK,CAAC,MAAM,WAAW,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,EAAE,CAAC;IACrG,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC;QAC7B,CAAC,CAAC,yDAAyD;QAC3D,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC;IAC/C,OAAO,CACL,6DAA6D;QAC7D,oIAAoI;QACpI,sEAAsE;QACtE,yCAAyC,KAAK,iBAAiB;QAC/D,iBAAiB,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,gBAAgB,CAC5D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared binary byte formatting — GB/MB, matching the cockpit's historical
|
|
3
|
+
* display so the same pane shows the same figure everywhere it's mentioned
|
|
4
|
+
* (the cockpit's memory column, the guardian's broadcast message, ...).
|
|
5
|
+
*/
|
|
6
|
+
export declare function formatBytes(n: number): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared binary byte formatting — GB/MB, matching the cockpit's historical
|
|
3
|
+
* display so the same pane shows the same figure everywhere it's mentioned
|
|
4
|
+
* (the cockpit's memory column, the guardian's broadcast message, ...).
|
|
5
|
+
*/
|
|
6
|
+
export function formatBytes(n) {
|
|
7
|
+
const gb = n / (1024 ** 3);
|
|
8
|
+
if (gb >= 1)
|
|
9
|
+
return `${gb.toFixed(1)} GB`;
|
|
10
|
+
const mb = n / (1024 ** 2);
|
|
11
|
+
return `${mb.toFixed(0)} MB`;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=bytes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bytes.js","sourceRoot":"","sources":["../../src/core/bytes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure plan representation for `gmux organize`.
|
|
3
|
+
*
|
|
4
|
+
* A plan never carries a destructive op: the tagged union below is 1:1 with
|
|
5
|
+
* the tmux gateway's relocation verbs (`newWindow`, `renameWindow`,
|
|
6
|
+
* `joinPane`, `breakPane`, `swapPane`, `selectLayout`) and nothing else. There
|
|
7
|
+
* is deliberately no `kill-pane`/`kill-window` step — see the design
|
|
8
|
+
* invariant in the organize spec: reorganization relocates panes, it never
|
|
9
|
+
* destroys their processes.
|
|
10
|
+
*/
|
|
11
|
+
import type { PaneState } from "./gmux-types.js";
|
|
12
|
+
/** tmux preset layouts we allow the planner to choose. */
|
|
13
|
+
export declare const LAYOUTS: readonly ["tiled", "even-horizontal", "even-vertical", "main-horizontal", "main-vertical"];
|
|
14
|
+
export type LayoutName = (typeof LAYOUTS)[number];
|
|
15
|
+
export declare function isLayoutName(v: string): v is LayoutName;
|
|
16
|
+
/**
|
|
17
|
+
* A window a step acts on. Either a window that already exists in tmux ("@N"),
|
|
18
|
+
* or one that an earlier `new-window`/`break-pane` step in THIS plan creates,
|
|
19
|
+
* referenced by a plan-local symbolic handle. Handles let the plan be fully
|
|
20
|
+
* built (and printed) before any "@N" id exists.
|
|
21
|
+
*/
|
|
22
|
+
export type WindowTarget = {
|
|
23
|
+
kind: "window";
|
|
24
|
+
windowId: string;
|
|
25
|
+
} | {
|
|
26
|
+
kind: "handle";
|
|
27
|
+
handle: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* The flattened, normalized view of a pane the planner reasons over. Built from
|
|
31
|
+
* either the daemon snapshot (rich: state + label) or a live registry diff (lean).
|
|
32
|
+
*/
|
|
33
|
+
export interface OrganizePane {
|
|
34
|
+
paneId: string;
|
|
35
|
+
windowId: string | null;
|
|
36
|
+
cwd: string;
|
|
37
|
+
command: string;
|
|
38
|
+
harness: string | null;
|
|
39
|
+
state: PaneState | null;
|
|
40
|
+
label: string | null;
|
|
41
|
+
active: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* One reorg step. Tagged union, 1:1 with a gateway verb, plus a human
|
|
45
|
+
* `description` used verbatim in the dry-run preview.
|
|
46
|
+
*/
|
|
47
|
+
export type OrganizeStep = {
|
|
48
|
+
op: "new-window";
|
|
49
|
+
handle: string;
|
|
50
|
+
name: string;
|
|
51
|
+
description: string;
|
|
52
|
+
} | {
|
|
53
|
+
op: "rename-window";
|
|
54
|
+
window: WindowTarget;
|
|
55
|
+
name: string;
|
|
56
|
+
description: string;
|
|
57
|
+
} | {
|
|
58
|
+
op: "move-pane";
|
|
59
|
+
paneId: string;
|
|
60
|
+
to: WindowTarget;
|
|
61
|
+
description: string;
|
|
62
|
+
} | {
|
|
63
|
+
op: "break-pane";
|
|
64
|
+
paneId: string;
|
|
65
|
+
handle: string;
|
|
66
|
+
name?: string;
|
|
67
|
+
description: string;
|
|
68
|
+
} | {
|
|
69
|
+
op: "swap-pane";
|
|
70
|
+
a: string;
|
|
71
|
+
b: string;
|
|
72
|
+
description: string;
|
|
73
|
+
} | {
|
|
74
|
+
op: "select-layout";
|
|
75
|
+
window: WindowTarget;
|
|
76
|
+
layout: LayoutName;
|
|
77
|
+
description: string;
|
|
78
|
+
};
|
|
79
|
+
export interface OrganizePlan {
|
|
80
|
+
/** One line for the dry-run header, e.g. "3 windows, 5 panes moved". */
|
|
81
|
+
summary: string;
|
|
82
|
+
/** Ordered; executed top to bottom. */
|
|
83
|
+
steps: OrganizeStep[];
|
|
84
|
+
}
|
|
85
|
+
/** Something that turns a pane snapshot (+ optional natural-language intent) into a plan. */
|
|
86
|
+
export interface OrganizePlanner {
|
|
87
|
+
plan(panes: OrganizePane[], intent?: string): Promise<OrganizePlan>;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Pure. The plan as numbered preview lines: the summary, then one line per step
|
|
91
|
+
* (`1. <description>`). No footer and no styling — callers append their own
|
|
92
|
+
* ("run with --apply" for the command, an apply/cancel hint for the overlay).
|
|
93
|
+
* Shared so the CLI command and the ctrl-g overlay render an identical plan.
|
|
94
|
+
*/
|
|
95
|
+
export declare function organizePreviewLines(plan: OrganizePlan): string[];
|