@gurugokul/doomscroller 0.0.0-stage → 0.2.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/LICENSE +21 -0
  3. package/README.md +323 -2
  4. package/dist/adapters/claude-code-hooks.js +27 -0
  5. package/dist/adapters/claude-code-hooks.js.map +1 -0
  6. package/dist/adapters/cli-wrapper.js +230 -0
  7. package/dist/adapters/cli-wrapper.js.map +1 -0
  8. package/dist/adapters/command-code-hooks.js +32 -0
  9. package/dist/adapters/command-code-hooks.js.map +1 -0
  10. package/dist/adapters/file-activity.js +78 -0
  11. package/dist/adapters/file-activity.js.map +1 -0
  12. package/dist/adapters/hook-settings.js +164 -0
  13. package/dist/adapters/hook-settings.js.map +1 -0
  14. package/dist/adapters/hook.js +17 -0
  15. package/dist/adapters/hook.js.map +1 -0
  16. package/dist/adapters/hotkey.js +50 -0
  17. package/dist/adapters/hotkey.js.map +1 -0
  18. package/dist/adapters/ide-activity.js +245 -0
  19. package/dist/adapters/ide-activity.js.map +1 -0
  20. package/dist/adapters/ports.js +3 -0
  21. package/dist/adapters/ports.js.map +1 -0
  22. package/dist/adapters/wrapper-tracker.js +77 -0
  23. package/dist/adapters/wrapper-tracker.js.map +1 -0
  24. package/dist/cli.js +343 -0
  25. package/dist/cli.js.map +1 -0
  26. package/dist/core/config.js +192 -0
  27. package/dist/core/config.js.map +1 -0
  28. package/dist/core/daemon.js +156 -0
  29. package/dist/core/daemon.js.map +1 -0
  30. package/dist/core/ipc.js +215 -0
  31. package/dist/core/ipc.js.map +1 -0
  32. package/dist/core/logger.js +53 -0
  33. package/dist/core/logger.js.map +1 -0
  34. package/dist/core/sound.js +38 -0
  35. package/dist/core/sound.js.map +1 -0
  36. package/dist/core/state-machine.js +272 -0
  37. package/dist/core/state-machine.js.map +1 -0
  38. package/dist/core/stats.js +109 -0
  39. package/dist/core/stats.js.map +1 -0
  40. package/dist/core/targets.js +27 -0
  41. package/dist/core/targets.js.map +1 -0
  42. package/dist/core/types.js +6 -0
  43. package/dist/core/types.js.map +1 -0
  44. package/dist/index.js +15 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/util/errors.js +16 -0
  47. package/dist/util/errors.js.map +1 -0
  48. package/dist/util/paths.js +77 -0
  49. package/dist/util/paths.js.map +1 -0
  50. package/dist/windows/cpu-probe.js +108 -0
  51. package/dist/windows/cpu-probe.js.map +1 -0
  52. package/dist/windows/key-listener.js +198 -0
  53. package/dist/windows/key-listener.js.map +1 -0
  54. package/dist/windows/win32.js +158 -0
  55. package/dist/windows/win32.js.map +1 -0
  56. package/dist/windows/window-controller.js +3 -0
  57. package/dist/windows/window-controller.js.map +1 -0
  58. package/package.json +57 -4
  59. package/scripts/cpu-sampler.ps1 +83 -0
  60. package/scripts/key-watcher.ps1 +132 -0
  61. package/scripts/win32-window.ps1 +344 -0
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startDaemon = startDaemon;
4
+ const config_1 = require("./config");
5
+ const logger_1 = require("./logger");
6
+ const stats_1 = require("./stats");
7
+ const targets_1 = require("./targets");
8
+ const state_machine_1 = require("./state-machine");
9
+ const sound_1 = require("./sound");
10
+ const ipc_1 = require("./ipc");
11
+ const hotkey_1 = require("../adapters/hotkey");
12
+ const ide_activity_1 = require("../adapters/ide-activity");
13
+ const cpu_probe_1 = require("../windows/cpu-probe");
14
+ const key_listener_1 = require("../windows/key-listener");
15
+ const win32_1 = require("../windows/win32");
16
+ async function startDaemon(config, logger) {
17
+ const windows = new win32_1.Win32WindowController(config.browser, logger);
18
+ const sound = new sound_1.WindowsSoundPlayer(config.sound, logger);
19
+ const targets = new targets_1.TargetRotator(config.targets);
20
+ let currentConfig = config;
21
+ const machine = new state_machine_1.DoomscrollerStateMachine({
22
+ config: currentConfig,
23
+ windows,
24
+ logger,
25
+ stats: new stats_1.SessionLogger(currentConfig.sessionLogPath),
26
+ sound,
27
+ targets,
28
+ });
29
+ // Re-read the config file at the start of each session so edits take effect
30
+ // without restarting the daemon. On a missing or invalid file the previous
31
+ // values are kept. Port, hotkey and log paths still require a restart.
32
+ const refreshConfig = () => {
33
+ try {
34
+ const loaded = (0, config_1.loadConfig)();
35
+ if (!loaded.exists || loaded.error)
36
+ return;
37
+ const next = {
38
+ ...currentConfig,
39
+ delaySeconds: loaded.config.delaySeconds,
40
+ maxDoomscrollSeconds: loaded.config.maxDoomscrollSeconds,
41
+ targets: loaded.config.targets,
42
+ browser: loaded.config.browser,
43
+ sound: loaded.config.sound,
44
+ };
45
+ currentConfig = next;
46
+ machine.updateConfig(next);
47
+ targets.setTargets(next.targets);
48
+ windows.setBrowser(next.browser);
49
+ sound.setEnabled(next.sound);
50
+ logger.info(`config reloaded (delay=${next.delaySeconds}s, cap=${next.maxDoomscrollSeconds}s, targets=${next.targets.length}, browser=${next.browser}, sound=${next.sound})`);
51
+ }
52
+ catch (error) {
53
+ (0, logger_1.logCaught)(logger, 'could not reload config; keeping previous values', error);
54
+ }
55
+ };
56
+ const hotkeySpec = (0, key_listener_1.parseHotkey)(config.hotkey);
57
+ const hasIdeAgents = config.registeredAgents.some((agent) => agent.adapter === 'ide-activity');
58
+ const keyListener = new key_listener_1.GlobalKeyListener(logger, hotkeySpec?.key ?? 'D');
59
+ const hotkeyAdapter = new hotkey_1.HotkeyAdapter({
60
+ listener: keyListener,
61
+ machine,
62
+ hotkey: hotkeySpec,
63
+ logger,
64
+ });
65
+ const ideAdapter = new ide_activity_1.IdeActivityAdapter({
66
+ config,
67
+ machine,
68
+ logger,
69
+ keySource: keyListener,
70
+ cpuProbes: new cpu_probe_1.PowerShellCpuProbeFactory(logger),
71
+ });
72
+ let server = null;
73
+ let closeDaemon = null;
74
+ const handler = (request) => {
75
+ if (!request || typeof request !== 'object') {
76
+ return { ok: false, error: 'invalid request' };
77
+ }
78
+ if (request.type === 'status') {
79
+ return { ok: true, state: machine.state, target: machine.currentTarget };
80
+ }
81
+ if (request.type === 'shutdown') {
82
+ logger.info('shutdown requested over IPC');
83
+ setTimeout(() => {
84
+ void closeDaemon?.();
85
+ }, 100);
86
+ return { ok: true, state: machine.state };
87
+ }
88
+ if (request.type === 'event' && (request.event === 'agent:started' || request.event === 'agent:finished')) {
89
+ if (request.event === 'agent:started')
90
+ refreshConfig();
91
+ void machine.handle(request.event);
92
+ return { ok: true, state: machine.state, target: machine.currentTarget };
93
+ }
94
+ return { ok: false, error: 'unknown request' };
95
+ };
96
+ try {
97
+ server = await (0, ipc_1.createIpcServer)(config.port, handler);
98
+ }
99
+ catch (error) {
100
+ throw new Error(`could not listen on 127.0.0.1:${config.port} (is another daemon running?): ${String(error)}`);
101
+ }
102
+ if (hotkeySpec || hasIdeAgents) {
103
+ keyListener.start();
104
+ }
105
+ else {
106
+ logger.info('no hotkey and no IDE agents configured; key listener not started');
107
+ }
108
+ hotkeyAdapter.start();
109
+ ideAdapter.start();
110
+ logger.info(`daemon listening on 127.0.0.1:${config.port} (hotkey=${config.hotkey ?? 'disabled'}, targets=${config.targets.length}, agents=${config.registeredAgents.length})`);
111
+ let closed = false;
112
+ closeDaemon = async () => {
113
+ if (closed)
114
+ return;
115
+ closed = true;
116
+ if (machine.isWorking) {
117
+ try {
118
+ await machine.forceReturn('hotkey');
119
+ }
120
+ catch (error) {
121
+ (0, logger_1.logCaught)(logger, 'could not restore focus while stopping', error);
122
+ }
123
+ }
124
+ try {
125
+ ideAdapter.stop();
126
+ }
127
+ catch (error) {
128
+ (0, logger_1.logCaught)(logger, 'could not stop ide adapter', error);
129
+ }
130
+ try {
131
+ hotkeyAdapter.stop();
132
+ }
133
+ catch (error) {
134
+ (0, logger_1.logCaught)(logger, 'could not stop hotkey adapter', error);
135
+ }
136
+ try {
137
+ keyListener.stop();
138
+ }
139
+ catch (error) {
140
+ (0, logger_1.logCaught)(logger, 'could not stop key listener', error);
141
+ }
142
+ machine.dispose();
143
+ try {
144
+ await server?.close();
145
+ }
146
+ catch (error) {
147
+ (0, logger_1.logCaught)(logger, 'could not close IPC server', error);
148
+ }
149
+ logger.info('daemon stopped');
150
+ };
151
+ return {
152
+ machine,
153
+ close: () => closeDaemon(),
154
+ };
155
+ }
156
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/core/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EventClient = void 0;
7
+ exports.sendIpcRequest = sendIpcRequest;
8
+ exports.createIpcServer = createIpcServer;
9
+ exports.spawnNodeDetached = spawnNodeDetached;
10
+ exports.spawnDaemonDetached = spawnDaemonDetached;
11
+ exports.spawnDispatchDetached = spawnDispatchDetached;
12
+ exports.isDaemonRunning = isDaemonRunning;
13
+ exports.ensureDaemon = ensureDaemon;
14
+ exports.dispatchFast = dispatchFast;
15
+ exports.dispatchWithDaemon = dispatchWithDaemon;
16
+ const node_net_1 = __importDefault(require("node:net"));
17
+ const node_child_process_1 = require("node:child_process");
18
+ const node_path_1 = __importDefault(require("node:path"));
19
+ const paths_1 = require("../util/paths");
20
+ const HOST = '127.0.0.1';
21
+ function sendIpcRequest(port, request, timeoutMs = 1000) {
22
+ return new Promise((resolve) => {
23
+ let settled = false;
24
+ let buffer = '';
25
+ let socket;
26
+ const finish = (response) => {
27
+ if (settled)
28
+ return;
29
+ settled = true;
30
+ clearTimeout(timer);
31
+ try {
32
+ socket.destroy();
33
+ }
34
+ catch {
35
+ // ignore
36
+ }
37
+ resolve(response);
38
+ };
39
+ const timer = setTimeout(() => finish(null), timeoutMs);
40
+ try {
41
+ socket = node_net_1.default.createConnection({ host: HOST, port });
42
+ }
43
+ catch {
44
+ resolve(null);
45
+ return;
46
+ }
47
+ socket.setEncoding('utf8');
48
+ socket.on('connect', () => {
49
+ try {
50
+ socket.write(`${JSON.stringify(request)}\n`);
51
+ }
52
+ catch {
53
+ finish(null);
54
+ }
55
+ });
56
+ socket.on('data', (chunk) => {
57
+ buffer += chunk;
58
+ const newline = buffer.indexOf('\n');
59
+ if (newline < 0)
60
+ return;
61
+ try {
62
+ const parsed = JSON.parse(buffer.slice(0, newline));
63
+ finish(parsed && typeof parsed === 'object' ? parsed : null);
64
+ }
65
+ catch {
66
+ finish(null);
67
+ }
68
+ });
69
+ socket.on('error', () => finish(null));
70
+ socket.on('close', () => finish(null));
71
+ });
72
+ }
73
+ function createIpcServer(port, handler) {
74
+ return new Promise((resolve, reject) => {
75
+ const server = node_net_1.default.createServer((socket) => {
76
+ let buffer = '';
77
+ let handled = false;
78
+ const respond = (response) => {
79
+ if (handled)
80
+ return;
81
+ handled = true;
82
+ try {
83
+ socket.end(`${JSON.stringify(response)}\n`);
84
+ }
85
+ catch {
86
+ // ignore
87
+ }
88
+ };
89
+ socket.setEncoding('utf8');
90
+ socket.on('data', (chunk) => {
91
+ buffer += chunk;
92
+ if (buffer.length > 65536) {
93
+ respond({ ok: false, error: 'request too large' });
94
+ return;
95
+ }
96
+ const newline = buffer.indexOf('\n');
97
+ if (newline < 0)
98
+ return;
99
+ try {
100
+ const parsed = JSON.parse(buffer.slice(0, newline));
101
+ respond(handler(parsed));
102
+ }
103
+ catch {
104
+ respond({ ok: false, error: 'invalid request' });
105
+ }
106
+ });
107
+ socket.on('error', () => { });
108
+ });
109
+ server.once('error', (error) => reject(error));
110
+ server.listen({ host: HOST, port }, () => {
111
+ resolve({
112
+ close: () => new Promise((done) => {
113
+ server.close(() => done());
114
+ }),
115
+ });
116
+ });
117
+ });
118
+ }
119
+ function spawnNodeDetached(args) {
120
+ try {
121
+ const entry = (0, paths_1.cliEntryPath)();
122
+ const child = (0, node_child_process_1.spawn)(process.execPath, [entry, ...args], {
123
+ detached: true,
124
+ stdio: 'ignore',
125
+ windowsHide: true,
126
+ cwd: node_path_1.default.dirname(entry),
127
+ });
128
+ child.on('error', () => { });
129
+ child.unref();
130
+ }
131
+ catch {
132
+ // Never let daemon spawning break the caller.
133
+ }
134
+ }
135
+ function spawnDaemonDetached() {
136
+ spawnNodeDetached(['daemon', '--hidden']);
137
+ }
138
+ function spawnDispatchDetached(event) {
139
+ spawnNodeDetached(['__dispatch', event]);
140
+ }
141
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
142
+ async function isDaemonRunning(port, timeoutMs = 250) {
143
+ const response = await sendIpcRequest(port, { type: 'status' }, timeoutMs);
144
+ return Boolean(response?.ok);
145
+ }
146
+ async function ensureDaemon(port, timeoutMs = 5000) {
147
+ if (await isDaemonRunning(port, 250))
148
+ return true;
149
+ spawnDaemonDetached();
150
+ const deadline = Date.now() + timeoutMs;
151
+ while (Date.now() < deadline) {
152
+ await sleep(120);
153
+ if (await isDaemonRunning(port, 200))
154
+ return true;
155
+ }
156
+ return false;
157
+ }
158
+ /**
159
+ * Hook-safe dispatch: try the daemon briefly, then hand the event to a
160
+ * detached helper and return immediately. The hook process never waits for
161
+ * the daemon to become ready. The helper's ensureDaemon starts the daemon if
162
+ * needed, so this function must not spawn one too: two spawns race and the
163
+ * loser fails to bind the port (EADDRINUSE).
164
+ */
165
+ async function dispatchFast(event, port) {
166
+ try {
167
+ const response = await sendIpcRequest(port, { type: 'event', event }, 180);
168
+ if (response?.ok)
169
+ return true;
170
+ }
171
+ catch {
172
+ // fall through
173
+ }
174
+ spawnDispatchDetached(event);
175
+ return false;
176
+ }
177
+ /** Used by the detached helper: wait for the daemon, then deliver exactly once. */
178
+ async function dispatchWithDaemon(event, port, timeoutMs = 8000) {
179
+ const ready = await ensureDaemon(port, timeoutMs);
180
+ if (!ready)
181
+ return false;
182
+ const response = await sendIpcRequest(port, { type: 'event', event }, 1500);
183
+ return Boolean(response?.ok);
184
+ }
185
+ class EventClient {
186
+ port;
187
+ ready;
188
+ pending = Promise.resolve();
189
+ constructor(port) {
190
+ this.port = port;
191
+ // Prewarm so the first Enter in a wrapped agent isn't delayed by daemon
192
+ // startup. ensureDaemon is a no-op when another daemon is already running.
193
+ this.ready = ensureDaemon(port, 6000);
194
+ }
195
+ emit(event) {
196
+ this.pending = this.pending
197
+ .then(async () => {
198
+ const ready = await this.ready;
199
+ if (!ready)
200
+ return;
201
+ const response = await sendIpcRequest(this.port, { type: 'event', event }, 1500);
202
+ if (!response?.ok) {
203
+ this.ready = ensureDaemon(this.port, 6000);
204
+ }
205
+ })
206
+ .catch(() => {
207
+ this.ready = ensureDaemon(this.port, 6000);
208
+ });
209
+ }
210
+ async flush() {
211
+ await this.pending;
212
+ }
213
+ }
214
+ exports.EventClient = EventClient;
215
+ //# sourceMappingURL=ipc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipc.js","sourceRoot":"","sources":["../../src/core/ipc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.noopLogger = void 0;
7
+ exports.createLogger = createLogger;
8
+ exports.logCaught = logCaught;
9
+ const node_fs_1 = __importDefault(require("node:fs"));
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const errors_1 = require("../util/errors");
12
+ function createLogger(options = {}) {
13
+ let directoryReady = false;
14
+ const write = (level, message) => {
15
+ const line = `[${new Date().toISOString()}] ${level} ${message}`;
16
+ if (options.console) {
17
+ try {
18
+ process.stderr.write(`${line}\n`);
19
+ }
20
+ catch {
21
+ // Logging must never be the reason something fails.
22
+ }
23
+ }
24
+ if (!options.filePath)
25
+ return;
26
+ try {
27
+ if (!directoryReady) {
28
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(options.filePath), { recursive: true });
29
+ directoryReady = true;
30
+ }
31
+ node_fs_1.default.appendFileSync(options.filePath, `${line}\n`, 'utf8');
32
+ }
33
+ catch {
34
+ // Intentionally silent.
35
+ }
36
+ };
37
+ return {
38
+ debug: (message) => write('DEBUG', message),
39
+ info: (message) => write('INFO', message),
40
+ warn: (message) => write('WARN', message),
41
+ error: (message) => write('ERROR', message),
42
+ };
43
+ }
44
+ exports.noopLogger = {
45
+ debug: () => { },
46
+ info: () => { },
47
+ warn: () => { },
48
+ error: () => { },
49
+ };
50
+ function logCaught(logger, context, error) {
51
+ logger.warn(`${context}: ${(0, errors_1.errorMessage)(error)}`);
52
+ }
53
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":";;;;;;AAkBA,oCA8BC;AASD,8BAEC;AA3DD,sDAAyB;AACzB,0DAA6B;AAC7B,2CAA8C;AAgB9C,SAAgB,YAAY,CAAC,UAAyB,EAAE;IACtD,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,MAAM,KAAK,GAAG,CAAC,KAAY,EAAE,OAAe,EAAQ,EAAE;QACpD,MAAM,IAAI,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,KAAK,IAAI,OAAO,EAAE,CAAC;QACjE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,IAAI,CAAC;gBACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,oDAAoD;YACtD,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,QAAQ;YAAE,OAAO;QAC9B,IAAI,CAAC;YACH,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,iBAAE,CAAC,SAAS,CAAC,mBAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClE,cAAc,GAAG,IAAI,CAAC;YACxB,CAAC;YACD,iBAAE,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,IAAI,IAAI,EAAE,MAAM,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;IACH,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;QAC3C,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC;QACzC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC;QACzC,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;KAC5C,CAAC;AACJ,CAAC;AAEY,QAAA,UAAU,GAAW;IAChC,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;IACf,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;CAChB,CAAC;AAEF,SAAgB,SAAS,CAAC,MAAc,EAAE,OAAe,EAAE,KAAc;IACvE,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,KAAK,IAAA,qBAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WindowsSoundPlayer = void 0;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const errors_1 = require("../util/errors");
6
+ const BEEP_SCRIPT = '[console]::beep(784,110); [console]::beep(1046,150)';
7
+ /** Plays a short two-tone chime without blocking the caller. */
8
+ class WindowsSoundPlayer {
9
+ enabled;
10
+ logger;
11
+ constructor(enabled = true, logger) {
12
+ this.enabled = enabled;
13
+ this.logger = logger;
14
+ }
15
+ setEnabled(enabled) {
16
+ this.enabled = enabled;
17
+ }
18
+ play() {
19
+ if (!this.enabled)
20
+ return;
21
+ if (process.platform !== 'win32')
22
+ return;
23
+ try {
24
+ // Not detached: a detached, console-less powershell.exe exits 0 without
25
+ // running -Command, so the chime would never play.
26
+ const child = (0, node_child_process_1.spawn)('powershell.exe', ['-NoProfile', '-NonInteractive', '-WindowStyle', 'Hidden', '-Command', BEEP_SCRIPT], { stdio: 'ignore', windowsHide: true });
27
+ child.on('error', (error) => {
28
+ this.logger?.debug(`could not play notification sound: ${(0, errors_1.errorMessage)(error)}`);
29
+ });
30
+ child.unref();
31
+ }
32
+ catch (error) {
33
+ this.logger?.debug(`could not play notification sound: ${(0, errors_1.errorMessage)(error)}`);
34
+ }
35
+ }
36
+ }
37
+ exports.WindowsSoundPlayer = WindowsSoundPlayer;
38
+ //# sourceMappingURL=sound.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sound.js","sourceRoot":"","sources":["../../src/core/sound.ts"],"names":[],"mappings":";;;AAAA,2DAA2C;AAG3C,2CAA8C;AAE9C,MAAM,WAAW,GAAG,qDAAqD,CAAC;AAE1E,gEAAgE;AAChE,MAAa,kBAAkB;IAEnB;IACS;IAFnB,YACU,UAAU,IAAI,EACL,MAAe;QADxB,YAAO,GAAP,OAAO,CAAO;QACL,WAAM,GAAN,MAAM,CAAS;IAC/B,CAAC;IAEJ,UAAU,CAAC,OAAgB;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,IAAI;QACF,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;YAAE,OAAO;QACzC,IAAI,CAAC;YACH,wEAAwE;YACxE,mDAAmD;YACnD,MAAM,KAAK,GAAG,IAAA,0BAAK,EACjB,gBAAgB,EAChB,CAAC,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,EACpF,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CACvC,CAAC;YACF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC1B,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,sCAAsC,IAAA,qBAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClF,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,sCAAsC,IAAA,qBAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;CACF;AA7BD,gDA6BC"}