@monotykamary/localterm-server 2.31.0 → 2.33.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/dist/capture-renderer.d.ts +4 -0
- package/dist/capture-renderer.d.ts.map +1 -1
- package/dist/capture-renderer.js +21 -0
- package/dist/capture-renderer.js.map +1 -1
- package/dist/cdp/cdp-client.d.ts +58 -0
- package/dist/cdp/cdp-client.d.ts.map +1 -1
- package/dist/cdp/cdp-client.js +119 -3
- package/dist/cdp/cdp-client.js.map +1 -1
- package/dist/constants.d.ts +13 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +55 -0
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +201 -12
- package/dist/index.js.map +1 -1
- package/dist/process-activity-watcher.d.ts +33 -0
- package/dist/process-activity-watcher.d.ts.map +1 -0
- package/dist/process-activity-watcher.js +93 -0
- package/dist/process-activity-watcher.js.map +1 -0
- package/dist/protocol.d.ts +2 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +2 -2
- package/dist/protocol.js.map +1 -1
- package/dist/schemas.d.ts +75 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +157 -2
- package/dist/schemas.js.map +1 -1
- package/dist/secret-shims.d.ts +2 -2
- package/dist/secret-shims.d.ts.map +1 -1
- package/dist/secret-shims.js +55 -35
- package/dist/secret-shims.js.map +1 -1
- package/dist/session-automation.d.ts +53 -0
- package/dist/session-automation.d.ts.map +1 -0
- package/dist/session-automation.js +230 -0
- package/dist/session-automation.js.map +1 -0
- package/dist/session-manager.d.ts +21 -0
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/session-manager.js +123 -1
- package/dist/session-manager.js.map +1 -1
- package/dist/session.d.ts +1 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +8 -0
- package/dist/session.js.map +1 -1
- package/dist/utils/named-keys.d.ts +4 -0
- package/dist/utils/named-keys.d.ts.map +1 -0
- package/dist/utils/named-keys.js +82 -0
- package/dist/utils/named-keys.js.map +1 -0
- package/dist/utils/open-chrome-inspect.d.ts +2 -0
- package/dist/utils/open-chrome-inspect.d.ts.map +1 -0
- package/dist/utils/open-chrome-inspect.js +65 -0
- package/dist/utils/open-chrome-inspect.js.map +1 -0
- package/dist/utils/sgr-mouse.d.ts +13 -0
- package/dist/utils/sgr-mouse.d.ts.map +1 -0
- package/dist/utils/sgr-mouse.js +40 -0
- package/dist/utils/sgr-mouse.js.map +1 -0
- package/dist/utils/terminal-mode-state.d.ts +1 -0
- package/dist/utils/terminal-mode-state.d.ts.map +1 -1
- package/dist/utils/terminal-mode-state.js +13 -0
- package/dist/utils/terminal-mode-state.js.map +1 -1
- package/package.json +1 -1
package/dist/secret-shims.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-shims.js","sourceRoot":"","sources":["../src/secret-shims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"secret-shims.js","sourceRoot":"","sources":["../src/secret-shims.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { CdpClient } from "./cdp/cdp-client.js";
|
|
2
|
+
import type { SessionManager } from "./session-manager.js";
|
|
3
|
+
import type { MouseButton } from "./utils/sgr-mouse.js";
|
|
4
|
+
export interface SessionAutomationDeps {
|
|
5
|
+
cdpClient: CdpClient | null;
|
|
6
|
+
buildTabUrl: (sessionId: string) => string;
|
|
7
|
+
}
|
|
8
|
+
export declare const capturePanePng: (deps: SessionAutomationDeps, registry: SessionManager, id: string) => Promise<Buffer | null>;
|
|
9
|
+
interface MouseActionBase {
|
|
10
|
+
button: MouseButton;
|
|
11
|
+
}
|
|
12
|
+
interface MouseClickColRow extends MouseActionBase {
|
|
13
|
+
action: "click";
|
|
14
|
+
col: number;
|
|
15
|
+
row: number;
|
|
16
|
+
clicks: number;
|
|
17
|
+
}
|
|
18
|
+
interface MouseClickText extends MouseActionBase {
|
|
19
|
+
action: "click";
|
|
20
|
+
onText: string;
|
|
21
|
+
clicks: number;
|
|
22
|
+
}
|
|
23
|
+
interface MouseDrag extends MouseActionBase {
|
|
24
|
+
action: "drag";
|
|
25
|
+
fromCol: number;
|
|
26
|
+
fromRow: number;
|
|
27
|
+
toCol: number;
|
|
28
|
+
toRow: number;
|
|
29
|
+
}
|
|
30
|
+
interface MouseMove {
|
|
31
|
+
action: "move";
|
|
32
|
+
col: number;
|
|
33
|
+
row: number;
|
|
34
|
+
}
|
|
35
|
+
interface MouseScroll {
|
|
36
|
+
action: "scroll";
|
|
37
|
+
direction: "up" | "down";
|
|
38
|
+
amount: number;
|
|
39
|
+
col: number;
|
|
40
|
+
row: number;
|
|
41
|
+
}
|
|
42
|
+
export type MouseAction = MouseClickColRow | MouseClickText | MouseDrag | MouseMove | MouseScroll;
|
|
43
|
+
export interface MouseResult {
|
|
44
|
+
ok: boolean;
|
|
45
|
+
mode: "cdp" | "sgr";
|
|
46
|
+
col: number | null;
|
|
47
|
+
row: number | null;
|
|
48
|
+
text: string | null;
|
|
49
|
+
reason: string | null;
|
|
50
|
+
}
|
|
51
|
+
export declare const sendMouse: (deps: SessionAutomationDeps, registry: SessionManager, id: string, action: MouseAction, sgrFallback: (id: string, action: MouseAction, col: number, row: number) => boolean) => Promise<MouseResult>;
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=session-automation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-automation.d.ts","sourceRoot":"","sources":["../src/session-automation.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAS3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIxD,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IAG5B,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CAC5C;AAkED,eAAO,MAAM,cAAc,GACzB,MAAM,qBAAqB,EAC3B,UAAU,cAAc,EACxB,IAAI,MAAM,KACT,OAAO,CAAC,MAAM,GAAG,IAAI,CAsBvB,CAAC;AAOF,UAAU,eAAe;IACvB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,UAAU,gBAAiB,SAAQ,eAAe;IAChD,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,cAAe,SAAQ,eAAe;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,SAAU,SAAQ,eAAe;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,SAAS;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,QAAQ,CAAC;IACjB,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAElG,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IAIZ,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IAGpB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAGpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAQD,eAAO,MAAM,SAAS,GACpB,MAAM,qBAAqB,EAC3B,UAAU,cAAc,EACxB,IAAI,MAAM,EACV,QAAQ,WAAW,EAGnB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,KAClF,OAAO,CAAC,WAAW,CAyIrB,CAAC"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// CDP-backed terminal-use parity: capture-pane --png and session mouse, built
|
|
2
|
+
// on the insight that the daemon's existing CDP socket (the one `localterm
|
|
3
|
+
// start` opened for background-tab automation) plus the tmux-parity surface
|
|
4
|
+
// compose without new deps. The browser (already a hard dep for the viewer) is
|
|
5
|
+
// the rasterizer; xterm.js (already speaking SGR mouse natively) is the mouse
|
|
6
|
+
// encoder. The tmux-parity capture renderer is the render-landed source of
|
|
7
|
+
// truth and the no-browser fallback for text capture.
|
|
8
|
+
//
|
|
9
|
+
// Reuse strategy: prefer a live viewer tab for the session (zero spawn latency,
|
|
10
|
+
// render already current) before opening an ephemeral background tab. A pinned
|
|
11
|
+
// session (the REST default) survives between calls with no tab burning a slot.
|
|
12
|
+
import { CDP_MOUSE_TIMEOUT_MS, CDP_RENDER_LANDED_POLL_INTERVAL_MS, CDP_RENDER_LANDED_SETTLE_MS, CDP_SCREENSHOT_TIMEOUT_MS, LOCALTERM_MOUSE_CELLS_PROPERTY, LOCALTERM_PANE_TEXT_PROPERTY, } from "./constants.js";
|
|
13
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
14
|
+
// Find an existing viewer tab for `id` (a page whose URL carries `?sid=<id>`),
|
|
15
|
+
// or open an ephemeral background tab and attach it. Returns null when no
|
|
16
|
+
// browser is reachable (caller falls back to the headless SGR path for mouse,
|
|
17
|
+
// or reports no_browser for screenshot).
|
|
18
|
+
const resolveTab = async (deps, id) => {
|
|
19
|
+
const { cdpClient } = deps;
|
|
20
|
+
if (!cdpClient)
|
|
21
|
+
return null;
|
|
22
|
+
const sidParam = `sid=${encodeURIComponent(id)}`;
|
|
23
|
+
const existing = await cdpClient.findTargetByUrl((url) => url.includes(sidParam));
|
|
24
|
+
const targetId = existing ?? (await cdpClient.openBackgroundTab(deps.buildTabUrl(id)));
|
|
25
|
+
if (!targetId)
|
|
26
|
+
return null;
|
|
27
|
+
const cdpSessionId = await cdpClient.attachSession(targetId);
|
|
28
|
+
if (!cdpSessionId) {
|
|
29
|
+
if (!existing)
|
|
30
|
+
await cdpClient.closeTab(targetId);
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
targetId,
|
|
35
|
+
cdpSessionId,
|
|
36
|
+
close: existing ? async () => undefined : async () => cdpClient.closeTab(targetId),
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
// Wait for the tab's xterm to render the session's current pane text. Robust
|
|
40
|
+
// against xterm's async write: polls the tab's `__localtermPaneText` and
|
|
41
|
+
// compares to the server-side `capturePane` (flushed, the source of truth) —
|
|
42
|
+
// when they're equal the grid is fully parsed; a short settle covers the
|
|
43
|
+
// canvas paint. Returns true on land, false on timeout (caller screenshots
|
|
44
|
+
// anyway, best effort).
|
|
45
|
+
const waitForRenderLanded = async (cdpClient, cdpSessionId, registry, id, timeoutMs) => {
|
|
46
|
+
const deadline = Date.now() + timeoutMs;
|
|
47
|
+
const expr = `window[${JSON.stringify(LOCALTERM_PANE_TEXT_PROPERTY)}]?.() ?? null`;
|
|
48
|
+
while (Date.now() < deadline) {
|
|
49
|
+
const expected = await registry.capturePane(id).catch(() => null);
|
|
50
|
+
const tabText = await cdpClient.evaluateInSession(cdpSessionId, expr);
|
|
51
|
+
if (expected !== null && tabText === expected) {
|
|
52
|
+
await sleep(CDP_RENDER_LANDED_SETTLE_MS);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
await sleep(CDP_RENDER_LANDED_POLL_INTERVAL_MS);
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
};
|
|
59
|
+
// `capture-pane --png`: render the session's current screen to a PNG via the
|
|
60
|
+
// browser. Reuses an existing viewer tab or opens an ephemeral one; clips to
|
|
61
|
+
// the `.xterm` element so the PNG is just the terminal. Returns the PNG bytes,
|
|
62
|
+
// or null when no browser is reachable (the caller reports `no_browser`; text
|
|
63
|
+
// `capture-pane` still works headlessly via the capture renderer).
|
|
64
|
+
export const capturePanePng = async (deps, registry, id) => {
|
|
65
|
+
const { cdpClient } = deps;
|
|
66
|
+
if (!cdpClient)
|
|
67
|
+
return null;
|
|
68
|
+
const tab = await resolveTab(deps, id);
|
|
69
|
+
if (!tab)
|
|
70
|
+
return null;
|
|
71
|
+
try {
|
|
72
|
+
await waitForRenderLanded(cdpClient, tab.cdpSessionId, registry, id, CDP_SCREENSHOT_TIMEOUT_MS);
|
|
73
|
+
const clipExpr = `(() => {
|
|
74
|
+
const el = document.querySelector(".xterm");
|
|
75
|
+
if (!el) return null;
|
|
76
|
+
const r = el.getBoundingClientRect();
|
|
77
|
+
return JSON.stringify({ x: r.left, y: r.top, width: r.width, height: r.height });
|
|
78
|
+
})()`;
|
|
79
|
+
const clipRaw = await cdpClient.evaluateInSession(tab.cdpSessionId, clipExpr);
|
|
80
|
+
const clip = typeof clipRaw === "string"
|
|
81
|
+
? JSON.parse(clipRaw)
|
|
82
|
+
: undefined;
|
|
83
|
+
return cdpClient.captureScreenshotInSession(tab.cdpSessionId, clip);
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
await tab.close();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
// `session mouse`: dispatch a mouse gesture. Primary path is CDP — drive the
|
|
90
|
+
// browser's xterm.js, which generates the SGR sequence itself, so drag/scroll/
|
|
91
|
+
// click-count semantics are exactly right with no encoder. Falls back to
|
|
92
|
+
// direct SGR-1006 bytes written to the PTY when no browser is reachable (the
|
|
93
|
+
// true-headless case), gated on the session's mouse mode so the bytes aren't
|
|
94
|
+
// fed to an app that didn't enable mouse.
|
|
95
|
+
export const sendMouse = async (deps, registry, id, action,
|
|
96
|
+
// Headless SGR fallback (injected from the route to avoid a circular import
|
|
97
|
+
// of the encoder here): writes the encoded sequence to the session PTY.
|
|
98
|
+
sgrFallback) => {
|
|
99
|
+
const { cdpClient } = deps;
|
|
100
|
+
// Resolve the target cell for any coord-bearing action. `--on-text` reads the
|
|
101
|
+
// server-side capture grid (no tab needed) so the fallback path can also
|
|
102
|
+
// locate a label.
|
|
103
|
+
let target = null;
|
|
104
|
+
let labelText = null;
|
|
105
|
+
if (action.action === "click" && "onText" in action) {
|
|
106
|
+
const found = await registry.findTextInViewport(id, action.onText);
|
|
107
|
+
if (!found) {
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
mode: "sgr",
|
|
111
|
+
col: null,
|
|
112
|
+
row: null,
|
|
113
|
+
text: action.onText,
|
|
114
|
+
reason: "text_not_found",
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
target = found;
|
|
118
|
+
labelText = action.onText;
|
|
119
|
+
}
|
|
120
|
+
else if ("col" in action && "row" in action) {
|
|
121
|
+
target = { col: action.col, row: action.row };
|
|
122
|
+
}
|
|
123
|
+
// Try the CDP path first: dispatch through the tab's xterm.js.
|
|
124
|
+
if (cdpClient) {
|
|
125
|
+
const tab = await resolveTab(deps, id);
|
|
126
|
+
if (tab) {
|
|
127
|
+
try {
|
|
128
|
+
await waitForRenderLanded(cdpClient, tab.cdpSessionId, registry, id, CDP_MOUSE_TIMEOUT_MS);
|
|
129
|
+
const cellsExpr = `window[${JSON.stringify(LOCALTERM_MOUSE_CELLS_PROPERTY)}]?.() ?? null`;
|
|
130
|
+
const cellsRaw = await cdpClient.evaluateInSession(tab.cdpSessionId, cellsExpr);
|
|
131
|
+
const cells = typeof cellsRaw === "string"
|
|
132
|
+
? JSON.parse(cellsRaw)
|
|
133
|
+
: null;
|
|
134
|
+
if (!cells) {
|
|
135
|
+
return {
|
|
136
|
+
ok: false,
|
|
137
|
+
mode: "cdp",
|
|
138
|
+
col: null,
|
|
139
|
+
row: null,
|
|
140
|
+
text: labelText,
|
|
141
|
+
reason: "no_xterm",
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// Coords for scroll: default to the viewport center so the wheel lands
|
|
145
|
+
// on the terminal even when the caller didn't specify a cell.
|
|
146
|
+
const t = target ?? { col: Math.floor(cells.cols / 2), row: Math.floor(cells.rows / 2) };
|
|
147
|
+
if (t.col < 0 || t.col >= cells.cols || t.row < 0 || t.row >= cells.rows) {
|
|
148
|
+
return {
|
|
149
|
+
ok: false,
|
|
150
|
+
mode: "cdp",
|
|
151
|
+
col: t.col,
|
|
152
|
+
row: t.row,
|
|
153
|
+
text: labelText,
|
|
154
|
+
reason: "out_of_bounds",
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const px = (col, row) => ({
|
|
158
|
+
x: cells.left + (col + 0.5) * cells.cellWidth,
|
|
159
|
+
y: cells.top + (row + 0.5) * cells.cellHeight,
|
|
160
|
+
});
|
|
161
|
+
const buttonName = action.action === "click" || action.action === "drag" ? action.button : "left";
|
|
162
|
+
const events = [];
|
|
163
|
+
if (action.action === "click") {
|
|
164
|
+
const at = px(t.col, t.row);
|
|
165
|
+
for (let i = 0; i < action.clicks; i++) {
|
|
166
|
+
events.push({ type: "mousePressed", ...at, button: buttonName, clickCount: 1 });
|
|
167
|
+
}
|
|
168
|
+
events.push({
|
|
169
|
+
type: "mouseReleased",
|
|
170
|
+
...at,
|
|
171
|
+
button: buttonName,
|
|
172
|
+
clickCount: action.clicks,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
else if (action.action === "drag") {
|
|
176
|
+
const from = px(action.fromCol, action.fromRow);
|
|
177
|
+
const to = px(action.toCol, action.toRow);
|
|
178
|
+
events.push({ type: "mousePressed", ...from, button: buttonName, clickCount: 1 });
|
|
179
|
+
events.push({ type: "mouseMoved", ...to, button: buttonName, buttons: 1 });
|
|
180
|
+
events.push({ type: "mouseReleased", ...to, button: buttonName, clickCount: 1 });
|
|
181
|
+
}
|
|
182
|
+
else if (action.action === "move") {
|
|
183
|
+
const at = px(t.col, t.row);
|
|
184
|
+
events.push({ type: "mouseMoved", ...at, button: "none" });
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
const at = px(t.col, t.row);
|
|
188
|
+
const delta = action.direction === "up" ? -action.amount : action.amount;
|
|
189
|
+
events.push({
|
|
190
|
+
type: "mouseWheel",
|
|
191
|
+
...at,
|
|
192
|
+
deltaX: 0,
|
|
193
|
+
deltaY: delta * Math.max(cells.cellHeight, 1),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
await cdpClient.dispatchMouseEventsInSession(tab.cdpSessionId, events);
|
|
197
|
+
// CDP dispatch via xterm.js always "succeeds" from our view — whether the
|
|
198
|
+
// app responds depends on its mouse mode, which xterm gates internally.
|
|
199
|
+
return { ok: true, mode: "cdp", col: t.col, row: t.row, text: labelText, reason: null };
|
|
200
|
+
}
|
|
201
|
+
finally {
|
|
202
|
+
await tab.close();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// Headless fallback: write SGR-1006 bytes straight to the PTY. Gated on the
|
|
207
|
+
// session's mouse mode so the bytes aren't fed to an app that can't read them.
|
|
208
|
+
if (!registry.mouseEnabledFor(id)) {
|
|
209
|
+
return {
|
|
210
|
+
ok: false,
|
|
211
|
+
mode: "sgr",
|
|
212
|
+
col: target?.col ?? null,
|
|
213
|
+
row: target?.row ?? null,
|
|
214
|
+
text: labelText,
|
|
215
|
+
reason: "mouse_disabled",
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
// Scroll needs a cell to anchor the SGR event; default to viewport center.
|
|
219
|
+
const fallbackTarget = target ?? { col: 0, row: 0 };
|
|
220
|
+
const written = sgrFallback(id, action, fallbackTarget.col, fallbackTarget.row);
|
|
221
|
+
return {
|
|
222
|
+
ok: written,
|
|
223
|
+
mode: "sgr",
|
|
224
|
+
col: fallbackTarget.col,
|
|
225
|
+
row: fallbackTarget.row,
|
|
226
|
+
text: labelText,
|
|
227
|
+
reason: written ? null : "not_found",
|
|
228
|
+
};
|
|
229
|
+
};
|
|
230
|
+
//# sourceMappingURL=session-automation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-automation.js","sourceRoot":"","sources":["../src/session-automation.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,15 @@ export interface ExecOptions {
|
|
|
20
20
|
timeoutMs?: number;
|
|
21
21
|
outputLimitBytes?: number;
|
|
22
22
|
}
|
|
23
|
+
export interface WaitPredicate {
|
|
24
|
+
kind: "text" | "regex" | "idle";
|
|
25
|
+
test: (text: string) => boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface WaitResult {
|
|
28
|
+
matched: boolean;
|
|
29
|
+
elapsedMs: number;
|
|
30
|
+
snapshot: string;
|
|
31
|
+
}
|
|
23
32
|
export type SessionActivityState = "running" | "alive-quiet" | "ready";
|
|
24
33
|
interface ManagedClient {
|
|
25
34
|
ws: ClientSocket;
|
|
@@ -103,6 +112,17 @@ export declare class SessionManager {
|
|
|
103
112
|
capturePane(id: string, lines?: number): Promise<string | null>;
|
|
104
113
|
setPinned(id: string, pinned: boolean): boolean;
|
|
105
114
|
setTitleById(id: string, title: string): boolean;
|
|
115
|
+
pressKeysById(id: string, input: string): boolean;
|
|
116
|
+
waitFor(id: string, predicate: WaitPredicate, timeoutMs: number, idleMs?: number): Promise<WaitResult | null>;
|
|
117
|
+
findTextInViewport(id: string, needle: string): Promise<{
|
|
118
|
+
col: number;
|
|
119
|
+
row: number;
|
|
120
|
+
} | null>;
|
|
121
|
+
mouseEnabledFor(id: string): boolean;
|
|
122
|
+
sessionSizeFor(id: string): {
|
|
123
|
+
cols: number;
|
|
124
|
+
rows: number;
|
|
125
|
+
};
|
|
106
126
|
private ensureCaptureRenderer;
|
|
107
127
|
execInSession(id: string, command: string, options?: ExecOptions): Promise<ExecResult | null>;
|
|
108
128
|
private buildExecResult;
|
|
@@ -130,6 +150,7 @@ export declare class SessionManager {
|
|
|
130
150
|
private coordinatorForCwd;
|
|
131
151
|
private releaseCoordinator;
|
|
132
152
|
broadcastGitBranchPr(cwd: string, pr: GitBranchPr | null): void;
|
|
153
|
+
hasCoordinatorFor(cwd: string): boolean;
|
|
133
154
|
}
|
|
134
155
|
export interface SessionListItem {
|
|
135
156
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/session-manager.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { CaptureRenderer } from "./capture-renderer.js";
|
|
4
|
-
import { CAPTURE_PANE_MAX_LINES, EXEC_DEFAULT_OUTPUT_LIMIT_BYTES, EXEC_DEFAULT_TIMEOUT_MS, EXEC_EPHEMERAL_SCROLLBACK, EXEC_MAX_OUTPUT_LIMIT_BYTES, EXEC_MAX_TIMEOUT_MS, EXEC_RAW_ACCUMULATE_CAP_BYTES, EXEC_TIMEOUT_INTERRUPT_GRACE_MS, MAX_CONCURRENT_SESSIONS, MAX_OUTPUT_BYTES, OUTPUT_BATCH_FLUSH_BYTES, OUTPUT_BATCH_WINDOW_MS, SESSION_ACTIVITY_WINDOW_MS, SESSION_GRACE_MS, SESSION_PENDING_PROMOTE_TIMEOUT_MS, WS_BACKPRESSURE_THRESHOLD_BYTES, WS_CLOSE_BACKPRESSURE, WS_OUTBOUND_DRAIN_POLL_MS, WS_OUTBOUND_PAUSE_HIGH_WATER_BYTES, WS_OUTBOUND_RESUME_LOW_WATER_BYTES, WS_READY_STATE_OPEN, } from "./constants.js";
|
|
4
|
+
import { CAPTURE_PANE_MAX_LINES, EXEC_DEFAULT_OUTPUT_LIMIT_BYTES, EXEC_DEFAULT_TIMEOUT_MS, EXEC_EPHEMERAL_SCROLLBACK, EXEC_MAX_OUTPUT_LIMIT_BYTES, EXEC_MAX_TIMEOUT_MS, EXEC_RAW_ACCUMULATE_CAP_BYTES, EXEC_TIMEOUT_INTERRUPT_GRACE_MS, MAX_CONCURRENT_SESSIONS, MAX_OUTPUT_BYTES, OUTPUT_BATCH_FLUSH_BYTES, OUTPUT_BATCH_WINDOW_MS, SESSION_ACTIVITY_WINDOW_MS, SESSION_GRACE_MS, SESSION_PENDING_PROMOTE_TIMEOUT_MS, WAIT_IDLE_POLL_INTERVAL_MS, WS_BACKPRESSURE_THRESHOLD_BYTES, WS_CLOSE_BACKPRESSURE, WS_OUTBOUND_DRAIN_POLL_MS, WS_OUTBOUND_PAUSE_HIGH_WATER_BYTES, WS_OUTBOUND_RESUME_LOW_WATER_BYTES, WS_READY_STATE_OPEN, } from "./constants.js";
|
|
5
5
|
import { GitDiffWatcher, GIT_DIFF_WATCHER_EVENT_NAMES, } from "./git-diff-watcher.js";
|
|
6
6
|
import { GitMetadataCoordinator } from "./git-metadata-coordinator.js";
|
|
7
7
|
import { Session } from "./session.js";
|
|
8
|
+
import { resolveNamedKeys } from "./utils/named-keys.js";
|
|
8
9
|
import { getBufferedAmount } from "./utils/ws-socket.js";
|
|
9
10
|
// Owns every live PTY for the daemon's lifetime. A Session is created on spawn
|
|
10
11
|
// and stays here until its shell exits, it's explicitly killed, or its
|
|
@@ -429,6 +430,119 @@ export class SessionManager {
|
|
|
429
430
|
managed.session.setTitle(title);
|
|
430
431
|
return true;
|
|
431
432
|
}
|
|
433
|
+
// Resolve space-separated named keys (`F2`, `Escape`, `Ctrl-C`, literal text)
|
|
434
|
+
// to xterm bytes and write them to a session — the `localterm session press`
|
|
435
|
+
// path. Unknown tokens pass through as literal text so `press hello` types
|
|
436
|
+
// "hello". Returns false for an unknown/exited session.
|
|
437
|
+
pressKeysById(id, input) {
|
|
438
|
+
const managed = this.sessions.get(id);
|
|
439
|
+
if (!managed || managed.session.isExited)
|
|
440
|
+
return false;
|
|
441
|
+
const data = resolveNamedKeys(input);
|
|
442
|
+
if (!data)
|
|
443
|
+
return false;
|
|
444
|
+
managed.session.write(data);
|
|
445
|
+
return true;
|
|
446
|
+
}
|
|
447
|
+
// Wait primitive: block until the session's rendered pane matches a text /
|
|
448
|
+
// regex predicate or goes idle for `idleMs`, bounded by `timeoutMs`. Reuses
|
|
449
|
+
// the tmux-parity capture renderer (flushed per frame) as the source of
|
|
450
|
+
// truth — the same grid `capture-pane` and `exec` read — so the predicate
|
|
451
|
+
// tests clean, ANSI-processed text, not raw bytes. Resolves `{matched,
|
|
452
|
+
// elapsedMs, snapshot}`. Returns null for an unknown/exited session.
|
|
453
|
+
async waitFor(id, predicate, timeoutMs, idleMs) {
|
|
454
|
+
const managed = this.sessions.get(id);
|
|
455
|
+
if (!managed || managed.session.isExited)
|
|
456
|
+
return null;
|
|
457
|
+
const session = managed.session;
|
|
458
|
+
const startedAt = Date.now();
|
|
459
|
+
let resolved = false;
|
|
460
|
+
let lastChangeAt = Date.now();
|
|
461
|
+
let timeoutHandle = null;
|
|
462
|
+
let idleTimer = null;
|
|
463
|
+
return new Promise((resolve) => {
|
|
464
|
+
const finalize = async (matched) => {
|
|
465
|
+
if (resolved)
|
|
466
|
+
return;
|
|
467
|
+
resolved = true;
|
|
468
|
+
if (timeoutHandle)
|
|
469
|
+
clearTimeout(timeoutHandle);
|
|
470
|
+
if (idleTimer)
|
|
471
|
+
clearInterval(idleTimer);
|
|
472
|
+
session.off("output", onOutput);
|
|
473
|
+
session.off("exit", onExit);
|
|
474
|
+
const snapshot = await this.capturePane(id).catch(() => "");
|
|
475
|
+
resolve({
|
|
476
|
+
matched,
|
|
477
|
+
elapsedMs: Date.now() - startedAt,
|
|
478
|
+
snapshot: snapshot ?? "",
|
|
479
|
+
});
|
|
480
|
+
};
|
|
481
|
+
const testPredicate = async () => {
|
|
482
|
+
const renderer = await this.ensureCaptureRenderer(managed);
|
|
483
|
+
await renderer.flush();
|
|
484
|
+
return predicate.test(renderer.capture());
|
|
485
|
+
};
|
|
486
|
+
const onOutput = () => {
|
|
487
|
+
lastChangeAt = Date.now();
|
|
488
|
+
void testPredicate().then((hit) => {
|
|
489
|
+
if (hit && !resolved)
|
|
490
|
+
finalize(true);
|
|
491
|
+
});
|
|
492
|
+
};
|
|
493
|
+
const onExit = () => {
|
|
494
|
+
void finalize(false);
|
|
495
|
+
};
|
|
496
|
+
// Idle mode: resolve once no output has arrived for `idleMs`. The interval
|
|
497
|
+
// checks recency without forcing a renderer read each tick (the output
|
|
498
|
+
// listener already bumps lastChangeAt).
|
|
499
|
+
if (predicate.kind === "idle") {
|
|
500
|
+
idleTimer = setInterval(() => {
|
|
501
|
+
if (!resolved && Date.now() - lastChangeAt >= (idleMs ?? 0))
|
|
502
|
+
finalize(true);
|
|
503
|
+
}, WAIT_IDLE_POLL_INTERVAL_MS);
|
|
504
|
+
idleTimer.unref?.();
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
// Text/regex: test once up front in case the pane already matches, then
|
|
508
|
+
// react to output events.
|
|
509
|
+
void testPredicate().then((hit) => {
|
|
510
|
+
if (hit && !resolved)
|
|
511
|
+
finalize(true);
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
session.on("output", onOutput);
|
|
515
|
+
session.on("exit", onExit);
|
|
516
|
+
timeoutHandle = setTimeout(() => finalize(false), timeoutMs);
|
|
517
|
+
timeoutHandle.unref?.();
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
// Resolve the (col, row) of a label on the session's visible viewport — the
|
|
521
|
+
// `mouse --on-text` coord source. Reads the capture renderer's grid (the same
|
|
522
|
+
// source `capture-pane` uses) so no browser tab is required to find the label.
|
|
523
|
+
// Returns null when the text isn't on screen.
|
|
524
|
+
async findTextInViewport(id, needle) {
|
|
525
|
+
const managed = this.sessions.get(id);
|
|
526
|
+
if (!managed || managed.session.isExited)
|
|
527
|
+
return null;
|
|
528
|
+
const renderer = await this.ensureCaptureRenderer(managed);
|
|
529
|
+
await renderer.flush();
|
|
530
|
+
return renderer.findTextInViewport(needle);
|
|
531
|
+
}
|
|
532
|
+
// Whether the session's foreground app enabled a mouse tracking mode — gates
|
|
533
|
+
// the SGR-1006 fallback for `mouse` when no CDP tab is available.
|
|
534
|
+
mouseEnabledFor(id) {
|
|
535
|
+
const managed = this.sessions.get(id);
|
|
536
|
+
return managed ? managed.session.mouseEnabled : false;
|
|
537
|
+
}
|
|
538
|
+
// The session's current PTY size (cols/rows), for the mouse-state endpoint
|
|
539
|
+
// and any coord-bounds check. Returns `{0,0}` for an unknown id.
|
|
540
|
+
sessionSizeFor(id) {
|
|
541
|
+
const managed = this.sessions.get(id);
|
|
542
|
+
return managed
|
|
543
|
+
? { cols: managed.session.cols, rows: managed.session.rows }
|
|
544
|
+
: { cols: 0, rows: 0 };
|
|
545
|
+
}
|
|
432
546
|
// Lazily create (and prime) a session's capture renderer. Fed the scrollback
|
|
433
547
|
// snapshot at creation so it catches up on recent history before the renderer
|
|
434
548
|
// existed, then kept alive and fed live output by onSessionOutput. Awaits the
|
|
@@ -972,5 +1086,13 @@ export class SessionManager {
|
|
|
972
1086
|
broadcastGitBranchPr(cwd, pr) {
|
|
973
1087
|
this.coordinatorsByCwd.get(path.resolve(cwd))?.broadcastPr(pr);
|
|
974
1088
|
}
|
|
1089
|
+
// Whether any tab is currently subscribed to the per-cwd coordinator — i.e.
|
|
1090
|
+
// there is a live audience for a PR lease refresh. Used to gate the
|
|
1091
|
+
// gh-activity refresh so a `gh` invocation in a cwd nobody is viewing never
|
|
1092
|
+
// triggers a pointless GitHub API call (mirrors broadcastGitBranchPr's
|
|
1093
|
+
// non-creating philosophy).
|
|
1094
|
+
hasCoordinatorFor(cwd) {
|
|
1095
|
+
return this.coordinatorsByCwd.has(path.resolve(cwd));
|
|
1096
|
+
}
|
|
975
1097
|
}
|
|
976
1098
|
//# sourceMappingURL=session-manager.js.map
|