@walldock/agent 0.1.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/pid.js ADDED
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.runningPid = runningPid;
37
+ exports.acquireLock = acquireLock;
38
+ exports.releaseLock = releaseLock;
39
+ const fs = __importStar(require("node:fs/promises"));
40
+ const path = __importStar(require("node:path"));
41
+ const os = __importStar(require("node:os"));
42
+ const PID_FILE = path.join(os.tmpdir(), 'walldock-agent.pid');
43
+ function isAlive(pid) {
44
+ try {
45
+ process.kill(pid, 0);
46
+ return true;
47
+ }
48
+ catch {
49
+ return false;
50
+ }
51
+ }
52
+ async function runningPid() {
53
+ try {
54
+ const raw = await fs.readFile(PID_FILE, 'utf8');
55
+ const pid = parseInt(raw.trim(), 10);
56
+ if (isNaN(pid))
57
+ return null;
58
+ return isAlive(pid) ? pid : null;
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
64
+ /**
65
+ * Write our PID to the lock file. Throws if another instance is already running.
66
+ */
67
+ async function acquireLock() {
68
+ const existing = await runningPid();
69
+ if (existing !== null) {
70
+ throw new Error(`Walldock Agent is already running (PID ${existing}).\n` +
71
+ 'Stop the existing instance before starting a new one.');
72
+ }
73
+ await fs.writeFile(PID_FILE, String(process.pid), 'utf8');
74
+ }
75
+ async function releaseLock() {
76
+ await fs.unlink(PID_FILE).catch(() => undefined);
77
+ }
@@ -0,0 +1,12 @@
1
+ export interface Screen {
2
+ stableId: string;
3
+ label: string;
4
+ width: number;
5
+ height: number;
6
+ scaleFactor: number;
7
+ positionX: number;
8
+ positionY: number;
9
+ isPrimary: boolean;
10
+ }
11
+ export declare function fingerprintScreens(screens: Screen[]): string;
12
+ export declare function listScreens(): Promise<Screen[]>;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.fingerprintScreens = fingerprintScreens;
37
+ exports.listScreens = listScreens;
38
+ function fingerprintScreens(screens) {
39
+ return screens
40
+ .map(s => `${s.stableId}:${s.width}x${s.height}@${s.scaleFactor}:p=${s.positionX},${s.positionY}:pri=${s.isPrimary ? 1 : 0}`)
41
+ .sort()
42
+ .join('|');
43
+ }
44
+ async function listScreens() {
45
+ try {
46
+ if (process.platform === 'darwin') {
47
+ const { listScreensMacOS } = await Promise.resolve().then(() => __importStar(require('./macos')));
48
+ return await listScreensMacOS();
49
+ }
50
+ if (process.platform === 'win32') {
51
+ const { listScreensWindows } = await Promise.resolve().then(() => __importStar(require('./windows')));
52
+ return await listScreensWindows();
53
+ }
54
+ const { listScreensLinux } = await Promise.resolve().then(() => __importStar(require('./linux')));
55
+ return await listScreensLinux();
56
+ }
57
+ catch (err) {
58
+ console.warn('[screens] enumeration failed:', err);
59
+ return [];
60
+ }
61
+ }
@@ -0,0 +1,2 @@
1
+ import type { Screen } from './index';
2
+ export declare function listScreensLinux(): Promise<Screen[]>;
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listScreensLinux = listScreensLinux;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const node_util_1 = require("node:util");
6
+ const stable_id_1 = require("./stable-id");
7
+ const exec = (0, node_util_1.promisify)(node_child_process_1.execFile);
8
+ async function tryExec(cmd, args) {
9
+ try {
10
+ const { stdout } = await exec(cmd, args);
11
+ return stdout;
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ }
17
+ async function listFromSway() {
18
+ const out = await tryExec('swaymsg', ['-t', 'get_outputs']);
19
+ if (!out)
20
+ return null;
21
+ try {
22
+ const outputs = JSON.parse(out);
23
+ return outputs
24
+ .filter(o => o.rect.width > 0)
25
+ .map((o, i) => {
26
+ const w = Math.round(o.rect.width * (o.scale ?? 1));
27
+ const h = Math.round(o.rect.height * (o.scale ?? 1));
28
+ return {
29
+ stableId: (0, stable_id_1.computeStableScreenId)(o.name, w, h, o.scale ?? 1, o.rect.x, o.rect.y),
30
+ label: o.name,
31
+ width: w,
32
+ height: h,
33
+ scaleFactor: o.scale ?? 1,
34
+ positionX: o.rect.x,
35
+ positionY: o.rect.y,
36
+ isPrimary: i === 0,
37
+ };
38
+ });
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
44
+ async function listFromHyprland() {
45
+ const out = await tryExec('hyprctl', ['monitors', '-j']);
46
+ if (!out)
47
+ return null;
48
+ try {
49
+ const monitors = JSON.parse(out);
50
+ return monitors.map((m, i) => ({
51
+ stableId: (0, stable_id_1.computeStableScreenId)(m.name, m.width, m.height, m.scale ?? 1, m.x, m.y),
52
+ label: m.name,
53
+ width: m.width,
54
+ height: m.height,
55
+ scaleFactor: m.scale ?? 1,
56
+ positionX: m.x,
57
+ positionY: m.y,
58
+ isPrimary: i === 0,
59
+ }));
60
+ }
61
+ catch {
62
+ return null;
63
+ }
64
+ }
65
+ async function listFromXrandr() {
66
+ const out = await tryExec('xrandr', ['--query']);
67
+ if (!out)
68
+ return null;
69
+ const screens = [];
70
+ // Matches lines like: HDMI-1 connected primary 1920x1080+0+0 (...)
71
+ const re = /^(\S+)\s+connected\s*(primary)?\s*(\d+)x(\d+)\+(-?\d+)\+(-?\d+)/gm;
72
+ let match;
73
+ while ((match = re.exec(out)) !== null) {
74
+ const [, name, primary, ws, hs, xs, ys] = match;
75
+ const width = parseInt(ws, 10);
76
+ const height = parseInt(hs, 10);
77
+ const positionX = parseInt(xs, 10);
78
+ const positionY = parseInt(ys, 10);
79
+ const scaleFactor = 1;
80
+ screens.push({
81
+ stableId: (0, stable_id_1.computeStableScreenId)(name, width, height, scaleFactor, positionX, positionY),
82
+ label: name,
83
+ width,
84
+ height,
85
+ scaleFactor,
86
+ positionX,
87
+ positionY,
88
+ isPrimary: primary === 'primary',
89
+ });
90
+ }
91
+ return screens.length > 0 ? screens : null;
92
+ }
93
+ async function listScreensLinux() {
94
+ if (process.env['SWAYSOCK']) {
95
+ const s = await listFromSway();
96
+ if (s)
97
+ return s;
98
+ }
99
+ if (process.env['HYPRLAND_INSTANCE_SIGNATURE']) {
100
+ const h = await listFromHyprland();
101
+ if (h)
102
+ return h;
103
+ }
104
+ const x = await listFromXrandr();
105
+ if (x)
106
+ return x;
107
+ // Final fallback: single synthetic screen
108
+ return [{
109
+ stableId: (0, stable_id_1.computeStableScreenId)('', 1920, 1080, 1, 0, 0),
110
+ label: 'Display',
111
+ width: 1920,
112
+ height: 1080,
113
+ scaleFactor: 1,
114
+ positionX: 0,
115
+ positionY: 0,
116
+ isPrimary: true,
117
+ }];
118
+ }
@@ -0,0 +1,2 @@
1
+ import type { Screen } from './index';
2
+ export declare function listScreensMacOS(): Promise<Screen[]>;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listScreensMacOS = listScreensMacOS;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const node_util_1 = require("node:util");
6
+ const stable_id_1 = require("./stable-id");
7
+ const exec = (0, node_util_1.promisify)(node_child_process_1.execFile);
8
+ // Swift one-liner: NSScreen gives us name, backing scale, frame in points.
9
+ // Physical pixels = points * backingScaleFactor.
10
+ const SWIFT_SCRIPT = `
11
+ import AppKit
12
+ let screens = NSScreen.screens
13
+ for screen in screens {
14
+ let b = screen.backingScaleFactor
15
+ let f = screen.frame
16
+ let name = screen.localizedName
17
+ let x = Int(f.origin.x)
18
+ let y = Int(f.origin.y)
19
+ let w = Int(f.size.width * b)
20
+ let h = Int(f.size.height * b)
21
+ let primary = (screen == NSScreen.main) ? 1 : 0
22
+ print("\\(name)|\\(x)|\\(y)|\\(w)|\\(h)|\\(b)|\\(primary)")
23
+ }
24
+ `.trim();
25
+ async function listScreensMacOS() {
26
+ const { stdout } = await exec('swift', ['-e', SWIFT_SCRIPT]);
27
+ const screens = [];
28
+ for (const line of stdout.trim().split('\n')) {
29
+ if (!line.trim())
30
+ continue;
31
+ const parts = line.split('|');
32
+ if (parts.length < 7)
33
+ continue;
34
+ const [name, xs, ys, ws, hs, scalS, priS] = parts;
35
+ const positionX = parseInt(xs, 10);
36
+ const positionY = parseInt(ys, 10);
37
+ const width = parseInt(ws, 10);
38
+ const height = parseInt(hs, 10);
39
+ const scaleFactor = parseFloat(scalS);
40
+ const isPrimary = priS.trim() === '1';
41
+ screens.push({
42
+ stableId: (0, stable_id_1.computeStableScreenId)(name, width, height, scaleFactor, positionX, positionY),
43
+ label: name,
44
+ width,
45
+ height,
46
+ scaleFactor,
47
+ positionX,
48
+ positionY,
49
+ isPrimary,
50
+ });
51
+ }
52
+ return screens;
53
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Replicates the Rust compute_stable_screen_id() function exactly.
3
+ * SHA-256 of:
4
+ * if name empty: "pos:" + posX(i32 LE) + posY(i32 LE)
5
+ * else: "name:" + name(utf8)
6
+ * then: "|res:" + width(u32 LE) + height(u32 LE)
7
+ * then: "|scale:" + scale(f64 LE bits)
8
+ * Returns first 12 bytes as lowercase hex (24 chars).
9
+ */
10
+ export declare function computeStableScreenId(name: string, width: number, height: number, scale: number, posX: number, posY: number): string;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.computeStableScreenId = computeStableScreenId;
37
+ const crypto = __importStar(require("node:crypto"));
38
+ /**
39
+ * Replicates the Rust compute_stable_screen_id() function exactly.
40
+ * SHA-256 of:
41
+ * if name empty: "pos:" + posX(i32 LE) + posY(i32 LE)
42
+ * else: "name:" + name(utf8)
43
+ * then: "|res:" + width(u32 LE) + height(u32 LE)
44
+ * then: "|scale:" + scale(f64 LE bits)
45
+ * Returns first 12 bytes as lowercase hex (24 chars).
46
+ */
47
+ function computeStableScreenId(name, width, height, scale, posX, posY) {
48
+ const hash = crypto.createHash('sha256');
49
+ if (!name) {
50
+ const posBuf = Buffer.allocUnsafe(8);
51
+ posBuf.writeInt32LE(posX, 0);
52
+ posBuf.writeInt32LE(posY, 4);
53
+ hash.update(Buffer.from('pos:'));
54
+ hash.update(posBuf);
55
+ }
56
+ else {
57
+ hash.update(Buffer.from('name:'));
58
+ hash.update(Buffer.from(name, 'utf8'));
59
+ }
60
+ const resBuf = Buffer.allocUnsafe(8);
61
+ resBuf.writeUInt32LE(width, 0);
62
+ resBuf.writeUInt32LE(height, 4);
63
+ hash.update(Buffer.from('|res:'));
64
+ hash.update(resBuf);
65
+ const scaleBuf = Buffer.allocUnsafe(8);
66
+ scaleBuf.writeDoubleLE(scale, 0);
67
+ hash.update(Buffer.from('|scale:'));
68
+ hash.update(scaleBuf);
69
+ return hash.digest().slice(0, 12).toString('hex');
70
+ }
@@ -0,0 +1,2 @@
1
+ import type { Screen } from './index';
2
+ export declare function listScreensWindows(): Promise<Screen[]>;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listScreensWindows = listScreensWindows;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const node_util_1 = require("node:util");
6
+ const stable_id_1 = require("./stable-id");
7
+ const exec = (0, node_util_1.promisify)(node_child_process_1.execFile);
8
+ // PowerShell: enumerate screens with bounds + per-monitor DPI (shcore.dll GetDpiForMonitor).
9
+ // Scale = monitorDpi / 96. Bounds from Win32 are in physical pixels.
10
+ const PS_SCRIPT = `
11
+ Add-Type @"
12
+ using System;
13
+ using System.Collections.Generic;
14
+ using System.Runtime.InteropServices;
15
+ public class MonitorHelper {
16
+ [DllImport("user32.dll")] public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr clip, MonitorEnumProc cb, IntPtr data);
17
+ [DllImport("shcore.dll")] public static extern int GetDpiForMonitor(IntPtr hMon, int type, out uint dpiX, out uint dpiY);
18
+ [DllImport("user32.dll")] public static extern bool GetMonitorInfo(IntPtr hMon, ref MonitorInfo info);
19
+ [StructLayout(LayoutKind.Sequential)] public struct RECT { public int L,T,R,B; }
20
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
21
+ public struct MonitorInfo {
22
+ public uint Size; public RECT Monitor; public RECT Work; public uint Flags;
23
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public string Device;
24
+ }
25
+ public delegate bool MonitorEnumProc(IntPtr hMon, IntPtr hdc, ref RECT rc, IntPtr data);
26
+ public static List<string> Enumerate() {
27
+ var results = new List<string>();
28
+ EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, (hMon, hdc, ref rc, data) => {
29
+ var info = new MonitorInfo(); info.Size = (uint)Marshal.SizeOf(info);
30
+ GetMonitorInfo(hMon, ref info);
31
+ uint dx, dy;
32
+ GetDpiForMonitor(hMon, 0, out dx, out dy);
33
+ double scale = dx / 96.0;
34
+ int w = info.Monitor.R - info.Monitor.L;
35
+ int h = info.Monitor.B - info.Monitor.T;
36
+ int primary = (info.Flags & 1) != 0 ? 1 : 0;
37
+ results.Add(info.Device + "|" + info.Monitor.L + "|" + info.Monitor.T + "|" + w + "|" + h + "|" + scale.ToString("F6") + "|" + primary);
38
+ return true;
39
+ }, IntPtr.Zero);
40
+ return results;
41
+ }
42
+ }
43
+ "@
44
+ [MonitorHelper]::Enumerate() | ForEach-Object { Write-Output $_ }
45
+ `.trim();
46
+ async function listScreensWindows() {
47
+ const { stdout } = await exec('powershell.exe', ['-NoProfile', '-Command', PS_SCRIPT]);
48
+ const screens = [];
49
+ for (const line of stdout.trim().split(/\r?\n/)) {
50
+ if (!line.trim())
51
+ continue;
52
+ const parts = line.split('|');
53
+ if (parts.length < 7)
54
+ continue;
55
+ const [name, xs, ys, ws, hs, scalS, priS] = parts;
56
+ const positionX = parseInt(xs, 10);
57
+ const positionY = parseInt(ys, 10);
58
+ const width = parseInt(ws, 10);
59
+ const height = parseInt(hs, 10);
60
+ const scaleFactor = parseFloat(scalS);
61
+ const isPrimary = priS.trim() === '1';
62
+ screens.push({
63
+ stableId: (0, stable_id_1.computeStableScreenId)(name.trim(), width, height, scaleFactor, positionX, positionY),
64
+ label: name.trim(),
65
+ width,
66
+ height,
67
+ scaleFactor,
68
+ positionX,
69
+ positionY,
70
+ isPrimary,
71
+ });
72
+ }
73
+ return screens;
74
+ }
package/dist/sse.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export interface SseHandle {
2
+ stop(): void;
3
+ }
4
+ /**
5
+ * SSE client backed by fetch + ReadableStream. Reconnects with exponential
6
+ * back-off. Calls onEvent for each complete "event: … / data: …" block.
7
+ */
8
+ export declare function connectSse(url: string, onEvent: (type: string, data: string) => void, onConnect?: () => void): SseHandle;
package/dist/sse.js ADDED
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.connectSse = connectSse;
4
+ const promises_1 = require("node:timers/promises");
5
+ const RECONNECT_DELAY_MS = 5_000;
6
+ const MAX_RECONNECT_DELAY_MS = 60_000;
7
+ /**
8
+ * SSE client backed by fetch + ReadableStream. Reconnects with exponential
9
+ * back-off. Calls onEvent for each complete "event: … / data: …" block.
10
+ */
11
+ function connectSse(url, onEvent, onConnect) {
12
+ const controller = new AbortController();
13
+ async function run() {
14
+ let attempt = 0;
15
+ while (!controller.signal.aborted) {
16
+ try {
17
+ const res = await fetch(url, {
18
+ headers: { accept: 'text/event-stream', 'cache-control': 'no-cache' },
19
+ signal: controller.signal,
20
+ });
21
+ if (!res.ok || !res.body)
22
+ throw new Error(`SSE HTTP ${res.status}`);
23
+ attempt = 0;
24
+ onConnect?.();
25
+ const decoder = new TextDecoder();
26
+ const reader = res.body.getReader();
27
+ let buffer = '';
28
+ try {
29
+ for (;;) {
30
+ const { done, value } = await reader.read();
31
+ if (done)
32
+ break;
33
+ buffer += decoder.decode(value, { stream: true });
34
+ const blocks = buffer.split(/\n\n/);
35
+ buffer = blocks.pop() ?? '';
36
+ for (const block of blocks) {
37
+ if (!block.trim())
38
+ continue;
39
+ let type = 'message';
40
+ let data = '';
41
+ for (const line of block.split('\n')) {
42
+ if (line.startsWith('event:'))
43
+ type = line.slice(6).trim();
44
+ else if (line.startsWith('data:'))
45
+ data = line.slice(5).trim();
46
+ }
47
+ onEvent(type, data);
48
+ }
49
+ }
50
+ }
51
+ finally {
52
+ reader.releaseLock();
53
+ }
54
+ }
55
+ catch {
56
+ if (controller.signal.aborted)
57
+ return;
58
+ const delay = Math.min(RECONNECT_DELAY_MS * Math.pow(1.5, attempt), MAX_RECONNECT_DELAY_MS);
59
+ attempt++;
60
+ await (0, promises_1.setTimeout)(delay, undefined, { signal: controller.signal }).catch(() => undefined);
61
+ }
62
+ }
63
+ }
64
+ void run();
65
+ return { stop() { controller.abort(); } };
66
+ }
@@ -0,0 +1,5 @@
1
+ export declare function registerStartup(): Promise<void>;
2
+ export declare function unregisterStartup(): Promise<void>;
3
+ export declare function startupDescription(): string;
4
+ /** Returns the resolved global bin path, or null if not globally installed. */
5
+ export declare function getGlobalBin(): Promise<string | null>;