tmux-ide 2.7.0 → 2.8.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/README.md +22 -5
- package/bin/cli.js +3532 -1090
- package/bin/cli.ts +368 -71
- package/package.json +2 -1
- package/packages/contracts/src/__tests__/control.test.ts +154 -0
- package/packages/contracts/src/control.ts +217 -0
- package/packages/contracts/src/index.ts +1 -0
- package/packages/daemon/dist/control/client.d.ts +23 -0
- package/packages/daemon/dist/control/client.js +105 -0
- package/packages/daemon/dist/control/dispatch.d.ts +34 -0
- package/packages/daemon/dist/control/dispatch.js +83 -0
- package/packages/daemon/dist/control/fanout.d.ts +19 -0
- package/packages/daemon/dist/control/fanout.js +37 -0
- package/packages/daemon/dist/control/frames.d.ts +23 -0
- package/packages/daemon/dist/control/frames.js +37 -0
- package/packages/daemon/dist/control/lifecycle.d.ts +45 -0
- package/packages/daemon/dist/control/lifecycle.js +114 -0
- package/packages/daemon/dist/control/server.d.ts +16 -0
- package/packages/daemon/dist/control/server.js +214 -0
- package/packages/daemon/dist/control/verbs.d.ts +11 -0
- package/packages/daemon/dist/control/verbs.js +91 -0
- package/packages/daemon/dist/doctor.d.ts +18 -0
- package/packages/daemon/dist/doctor.js +105 -15
- package/packages/daemon/dist/lib/agent-discovery.d.ts +27 -2
- package/packages/daemon/dist/lib/agent-discovery.js +29 -14
- package/packages/daemon/dist/lib/app-config.d.ts +106 -0
- package/packages/daemon/dist/lib/app-config.js +104 -5
- package/packages/daemon/dist/lib/manifest-pack.d.ts +79 -0
- package/packages/daemon/dist/lib/manifest-pack.js +232 -0
- package/packages/daemon/dist/lib/state-home.d.ts +2 -0
- package/packages/daemon/dist/lib/state-home.js +12 -0
- package/packages/daemon/dist/lib/update-check.js +5 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Info.plist +34 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/MacOS/tmux-ide-notifier +0 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/PkgInfo +1 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/AppIcon.icns +0 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/Assets.car +0 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/_CodeSignature/CodeResources +139 -0
- package/packages/daemon/dist/restore.d.ts +35 -8
- package/packages/daemon/dist/restore.js +52 -15
- package/packages/daemon/dist/send.d.ts +33 -1
- package/packages/daemon/dist/send.js +32 -19
- package/packages/daemon/src/control/client.ts +128 -0
- package/packages/daemon/src/control/dispatch.ts +107 -0
- package/packages/daemon/src/control/fanout.ts +44 -0
- package/packages/daemon/src/control/frames.ts +40 -0
- package/packages/daemon/src/control/lifecycle.ts +151 -0
- package/packages/daemon/src/control/server.ts +237 -0
- package/packages/daemon/src/control/verbs.ts +118 -0
- package/packages/daemon/src/doctor.ts +113 -28
- package/packages/daemon/src/lib/agent-discovery.ts +53 -13
- package/packages/daemon/src/lib/app-config.ts +103 -5
- package/packages/daemon/src/lib/manifest-pack.ts +255 -0
- package/packages/daemon/src/lib/state-home.ts +13 -0
- package/packages/daemon/src/lib/update-check.ts +5 -0
- package/packages/daemon/src/restore.ts +53 -15
- package/packages/daemon/src/send.ts +55 -21
- package/packages/daemon/src/tui/chrome/events.ts +4 -4
- package/packages/daemon/src/tui/chrome/front-door.ts +39 -0
- package/packages/daemon/src/tui/chrome/notify-prefs.ts +58 -0
- package/packages/daemon/src/tui/chrome/notify-state.ts +76 -0
- package/packages/daemon/src/tui/chrome/notify.ts +582 -84
- package/packages/daemon/src/tui/chrome/updater.ts +268 -62
- package/packages/daemon/src/tui/detect/classify.ts +34 -0
- package/packages/daemon/src/tui/detect/manifest-loader.ts +54 -5
- package/packages/daemon/src/tui/detect/manifest.ts +24 -3
- package/packages/daemon/src/tui/detect/manifests.ts +240 -6
- package/packages/daemon/src/tui/detect/process-tree.ts +13 -3
- package/packages/daemon/src/tui/detect/session-id.ts +503 -0
- package/packages/daemon/src/tui/integrations/opencode.ts +121 -0
- package/packages/daemon/src/tui/mirror/agent-chip.ts +40 -11
- package/packages/daemon/src/tui/mirror/agent-lifecycle.ts +437 -0
- package/packages/daemon/src/tui/mirror/agent-rows.ts +27 -5
- package/packages/daemon/src/tui/mirror/app-state.ts +171 -8
- package/packages/daemon/src/tui/mirror/app.tsx +2182 -399
- package/packages/daemon/src/tui/mirror/attention.ts +110 -0
- package/packages/daemon/src/tui/mirror/dialog-stack.ts +17 -4
- package/packages/daemon/src/tui/mirror/diff-model.ts +279 -4
- package/packages/daemon/src/tui/mirror/file-tree.ts +231 -6
- package/packages/daemon/src/tui/mirror/host-terminal.ts +49 -0
- package/packages/daemon/src/tui/mirror/hosted.ts +205 -0
- package/packages/daemon/src/tui/mirror/layout-parse.ts +154 -0
- package/packages/daemon/src/tui/mirror/menu-model.ts +27 -4
- package/packages/daemon/src/tui/mirror/palette.ts +299 -9
- package/packages/daemon/src/tui/mirror/pane-mirror.ts +82 -4
- package/packages/daemon/src/tui/mirror/pane-surface.tsx +18 -11
- package/packages/daemon/src/tui/mirror/perf-tap.ts +29 -3
- package/packages/daemon/src/tui/mirror/selection.ts +122 -8
- package/packages/daemon/src/tui/mirror/session-mirror.ts +349 -68
- package/packages/daemon/src/tui/mirror/settings-model.ts +96 -16
- package/packages/daemon/src/tui/mirror/sidebar.tsx +218 -0
- package/packages/daemon/src/tui/mirror/size-truth.ts +53 -0
- package/packages/daemon/src/tui/mirror/theme.ts +45 -0
- package/packages/daemon/src/tui/team/fuzzy.ts +20 -0
- package/packages/daemon/src/tui/team/sessions.ts +85 -7
- package/packages/daemon/src/tui/team/wait.ts +144 -0
- package/scripts/build-macos-notifier.mjs +160 -0
- package/scripts/postinstall.js +8 -1
- package/scripts/prepublish-check.mjs +37 -1
- package/scripts/publish-tap.sh +55 -0
- package/skill/SKILL.md +88 -2
|
@@ -103,9 +103,10 @@ export function tapInputTick(): void {
|
|
|
103
103
|
// ── size re-pin tap (M22.8) ─────────────────────────────────────────────────
|
|
104
104
|
// Every canvas-area change (terminal resize, sidebar drag) funnels through the
|
|
105
105
|
// mirror's `resize()` — the ONE re-pin chokepoint. This tap records each re-pin
|
|
106
|
-
// so a live drag/resize burst can be asserted
|
|
107
|
-
//
|
|
108
|
-
// behind TMUX_IDE_ZZ_PERF, appending `cols rows` lines to
|
|
106
|
+
// so a live drag/resize burst can be asserted against the expected count (since
|
|
107
|
+
// M23.5 the renderer dims signal re-pins per actual size change — no more 200ms
|
|
108
|
+
// poll). Gated behind TMUX_IDE_ZZ_PERF, appending `cols rows` lines to
|
|
109
|
+
// /tmp/zz-repin.log.
|
|
109
110
|
|
|
110
111
|
const REPIN_LOG = "/tmp/zz-repin.log";
|
|
111
112
|
|
|
@@ -119,6 +120,31 @@ export function tapRepin(cols: number, rows: number): void {
|
|
|
119
120
|
}
|
|
120
121
|
}
|
|
121
122
|
|
|
123
|
+
// ── resize tap (M23.5) ──────────────────────────────────────────────────────
|
|
124
|
+
// The event-driven geometry pipeline's flight recorder: one timestamped line
|
|
125
|
+
// per hop — %layout-change received (`notify`), geometry applied into the
|
|
126
|
+
// mirrors (`geometry-applied`), a canvas re-pin (`repin`), a per-pane term
|
|
127
|
+
// resize (`pane-resize`), and per-%output mirror dims (`output`) — so a resize
|
|
128
|
+
// battery can assert "geometry applied <5ms after the notify" and "no %output
|
|
129
|
+
// parsed into stale dims" straight from the log. Own env gate
|
|
130
|
+
// (TMUX_IDE_ZZ_RESIZE_TAP): the per-output line is too chatty for the general
|
|
131
|
+
// TMUX_IDE_ZZ_PERF sessions.
|
|
132
|
+
|
|
133
|
+
const RESIZE_LOG = "/tmp/zz-resize-tap.log";
|
|
134
|
+
|
|
135
|
+
/** Append one `<t> <event> <detail>` line. No-op unless TMUX_IDE_ZZ_RESIZE_TAP. */
|
|
136
|
+
export function tapResize(event: string, detail = ""): void {
|
|
137
|
+
if (!process.env.TMUX_IDE_ZZ_RESIZE_TAP) return;
|
|
138
|
+
try {
|
|
139
|
+
appendFileSync(
|
|
140
|
+
RESIZE_LOG,
|
|
141
|
+
`${performance.now().toFixed(2)} ${event}${detail ? ` ${detail}` : ""}\n`,
|
|
142
|
+
);
|
|
143
|
+
} catch {
|
|
144
|
+
/* perf tap only */
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
122
148
|
// ── pure reporting helpers (used by scripts/perf-mirror.mjs) ────────────────
|
|
123
149
|
|
|
124
150
|
/** A percentile of an ASCENDING-sorted array, linearly interpolated. Empty → 0. */
|
|
@@ -11,15 +11,21 @@
|
|
|
11
11
|
* cell is selected if it falls between the anchor and head in row-major order.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
/** A cell in surface-local coordinates
|
|
15
|
-
*
|
|
14
|
+
/** A cell in surface-local coordinates. Mirror (M25.6): ABSOLUTE xterm buffer
|
|
15
|
+
* line (0 = oldest scrollback line) + pane column — anchored to CONTENT, so
|
|
16
|
+
* the selection survives scrolling mid-drag and can span many screens. Editor:
|
|
17
|
+
* buffer line + buffer column (already absolute by nature). A visible pane row
|
|
18
|
+
* `r` at scroll offset `off` maps to absolute line `baseY + r` where
|
|
19
|
+
* `baseY = scrollbackDepth − off` (the search path's existing arithmetic —
|
|
20
|
+
* see PaneMirror.bufferLines). */
|
|
16
21
|
export interface Cell {
|
|
17
22
|
row: number;
|
|
18
23
|
col: number;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
/** An active selection on one surface. `anchor` is where the drag began, `head`
|
|
22
|
-
* the current/last pointer cell; either may precede the other.
|
|
27
|
+
* the current/last pointer cell; either may precede the other. Mirror cells
|
|
28
|
+
* are in ABSOLUTE buffer coordinates (see {@link Cell}). */
|
|
23
29
|
export type Selection =
|
|
24
30
|
| { surface: "mirror"; paneId: string; anchor: Cell; head: Cell }
|
|
25
31
|
| { surface: "editor"; anchor: Cell; head: Cell };
|
|
@@ -78,6 +84,68 @@ export function extractSelection(
|
|
|
78
84
|
return out.join("\n");
|
|
79
85
|
}
|
|
80
86
|
|
|
87
|
+
// ── Absolute-space mapping (M25.6) ──────────────────────────────────────────
|
|
88
|
+
// The selection model is anchored to ABSOLUTE buffer lines; the render works in
|
|
89
|
+
// visible pane rows. These mappers are the one bridge: given the pane's current
|
|
90
|
+
// baseY (scrollbackDepth − scrollOffset) and height, an absolute range resolves
|
|
91
|
+
// to the visible rows it covers and the per-row column spans to highlight.
|
|
92
|
+
|
|
93
|
+
/** A highlighted span on one VISIBLE pane row (row is viewport-relative). */
|
|
94
|
+
export interface VisibleSpan {
|
|
95
|
+
row: number;
|
|
96
|
+
from: number;
|
|
97
|
+
to: number;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Visible pane rows [0,height) covered by an ORDERED absolute range at the
|
|
101
|
+
* current view (`baseY` = scrollbackDepth − scrollOffset). Empty when the
|
|
102
|
+
* whole range is scrolled off either edge. */
|
|
103
|
+
export function visibleSelRows(start: Cell, end: Cell, baseY: number, height: number): number[] {
|
|
104
|
+
const lo = Math.max(0, start.row - baseY);
|
|
105
|
+
const hi = Math.min(height - 1, end.row - baseY);
|
|
106
|
+
const out: number[] = [];
|
|
107
|
+
for (let r = lo; r <= hi; r++) out.push(r);
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Map an ORDERED absolute range to the visible per-row column spans at the
|
|
113
|
+
* current view. `rowLen(viewRow)` supplies each visible row's selectable cell
|
|
114
|
+
* count (grid width for the framebuffer swap; the row's char count for run
|
|
115
|
+
* tinting — wide glyphs collapse to one char there, so the two callers pass
|
|
116
|
+
* different lengths and each gets spans clamped to ITS space). Rows whose
|
|
117
|
+
* span is empty (zero-length row, or a first/last-row column interval that
|
|
118
|
+
* falls outside it) are omitted.
|
|
119
|
+
*/
|
|
120
|
+
export function visibleSelectionSpans(
|
|
121
|
+
start: Cell,
|
|
122
|
+
end: Cell,
|
|
123
|
+
baseY: number,
|
|
124
|
+
height: number,
|
|
125
|
+
rowLen: (viewRow: number) => number,
|
|
126
|
+
): VisibleSpan[] {
|
|
127
|
+
const out: VisibleSpan[] = [];
|
|
128
|
+
for (const r of visibleSelRows(start, end, baseY, height)) {
|
|
129
|
+
const range = rowSelectionRange(baseY + r, rowLen(r), start, end);
|
|
130
|
+
if (range) out.push({ row: r, from: range.from, to: range.to });
|
|
131
|
+
}
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Re-anchor an absolute cell after the buffer trimmed `trimDelta` lines off its
|
|
137
|
+
* top (the scrollback cap rotating mid-drag): every retained line's index
|
|
138
|
+
* dropped by the trim, so the cell follows its content down. A cell whose line
|
|
139
|
+
* was trimmed away clamps to the oldest retained line (row 0), col 0 — the
|
|
140
|
+
* selection top pins to the oldest text still in the buffer.
|
|
141
|
+
*/
|
|
142
|
+
export function trimAdjustCell(cell: Cell, trimDelta: number): Cell {
|
|
143
|
+
if (trimDelta <= 0) return cell;
|
|
144
|
+
const row = cell.row - trimDelta;
|
|
145
|
+
if (row < 0) return { row: 0, col: 0 };
|
|
146
|
+
return { row, col: cell.col };
|
|
147
|
+
}
|
|
148
|
+
|
|
81
149
|
/**
|
|
82
150
|
* The inclusive [from,to] char interval of the word at `col` in `text`,
|
|
83
151
|
* splitting on /\W/ (word chars are [A-Za-z0-9_]). A click on a non-word char
|
|
@@ -198,14 +266,60 @@ export function tintRunsBg<T extends { text: string; bg: number | null }>(
|
|
|
198
266
|
// through (SGR encodes it as +4 on the button code; many terminals keep
|
|
199
267
|
// shift+drag for native selection instead — then only select mode applies).
|
|
200
268
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
269
|
+
// ── Implicit drag-select default (M24.2) ─────────────────────────────────────
|
|
270
|
+
// Every agent pane (claude/codex) is app-mouse, so "forwarding wins" meant a
|
|
271
|
+
// user's whole fleet couldn't drag-select. The DEFAULT now follows the pane:
|
|
272
|
+
// where our own detection says an agent runs there, a plain drag selects and
|
|
273
|
+
// only a genuine click (press+release in one cell) is forwarded — deferred
|
|
274
|
+
// until motion or release decides. Shift INVERTS the pane's default (so on an
|
|
275
|
+
// agent pane shift+drag forwards; on a vim pane it selects, as in M22.9), the
|
|
276
|
+
// right-click toggle overrides per pane for the session, and `app.dragSelect`
|
|
277
|
+
// ("agents"|"always"|"never") sets the policy.
|
|
278
|
+
|
|
279
|
+
/** Where a plain left drag on a pane goes by default. */
|
|
280
|
+
export type PaneDragDefault = "select" | "forward";
|
|
281
|
+
/** The `app.dragSelect` policy values (app-config). */
|
|
282
|
+
export type DragSelectSetting = "agents" | "always" | "never";
|
|
283
|
+
|
|
284
|
+
/** PURE — a pane's drag default. Precedence: the session's per-pane override
|
|
285
|
+
* (the right-click toggle) > the config policy ("always"/"never") > the agent
|
|
286
|
+
* join ("agents": a pane matching a fleet agent entry selects; every other
|
|
287
|
+
* app-mouse pane forwards). */
|
|
288
|
+
export function paneDragDefault(
|
|
289
|
+
agentEntry: { paneId: string } | undefined,
|
|
290
|
+
config: DragSelectSetting,
|
|
291
|
+
override: PaneDragDefault | null,
|
|
292
|
+
): PaneDragDefault {
|
|
293
|
+
if (override !== null) return override;
|
|
294
|
+
if (config === "always") return "select";
|
|
295
|
+
if (config === "never") return "forward";
|
|
296
|
+
return agentEntry !== undefined ? "select" : "forward";
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/** What a left press on a pane does: run the selection machine NOW, forward
|
|
300
|
+
* the SGR press NOW, or DEFER (withhold the press until motion starts a
|
|
301
|
+
* selection or a release-in-place forwards the owed click pair). */
|
|
302
|
+
export type PressRouting = "select" | "forward" | "defer";
|
|
303
|
+
|
|
304
|
+
/** PURE — route a left press. Plain panes and select mode keep the immediate
|
|
305
|
+
* selection machine. Otherwise the pane's drag default decides, with shift
|
|
306
|
+
* inverting it: a shift press that lands on "select" stays IMMEDIATE (the
|
|
307
|
+
* M22.9 behavior — a shift-click was never forwarded), while an unshifted
|
|
308
|
+
* "select" defers so the pane's app still gets genuine clicks. */
|
|
309
|
+
export function routePanePress(
|
|
204
310
|
appMouse: boolean,
|
|
205
311
|
selectModeOn: boolean,
|
|
206
312
|
shift: boolean,
|
|
207
|
-
|
|
208
|
-
|
|
313
|
+
dragDefault: PaneDragDefault,
|
|
314
|
+
): PressRouting {
|
|
315
|
+
if (!appMouse || selectModeOn) return "select";
|
|
316
|
+
const effective: PaneDragDefault = shift
|
|
317
|
+
? dragDefault === "select"
|
|
318
|
+
? "forward"
|
|
319
|
+
: "select"
|
|
320
|
+
: dragDefault;
|
|
321
|
+
if (effective === "forward") return "forward";
|
|
322
|
+
return shift ? "select" : "defer";
|
|
209
323
|
}
|
|
210
324
|
|
|
211
325
|
/** PURE — whether the wheel scrolls the LOCAL mirror scrollback (vs. being
|