@gurugokul/doomscroller 0.0.0-stage → 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.
Files changed (57) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/LICENSE +21 -0
  3. package/README.md +300 -2
  4. package/dist/adapters/claude-code-hooks.js +171 -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/file-activity.js +78 -0
  9. package/dist/adapters/file-activity.js.map +1 -0
  10. package/dist/adapters/hook.js +17 -0
  11. package/dist/adapters/hook.js.map +1 -0
  12. package/dist/adapters/hotkey.js +50 -0
  13. package/dist/adapters/hotkey.js.map +1 -0
  14. package/dist/adapters/ide-activity.js +245 -0
  15. package/dist/adapters/ide-activity.js.map +1 -0
  16. package/dist/adapters/ports.js +3 -0
  17. package/dist/adapters/ports.js.map +1 -0
  18. package/dist/adapters/wrapper-tracker.js +77 -0
  19. package/dist/adapters/wrapper-tracker.js.map +1 -0
  20. package/dist/cli.js +315 -0
  21. package/dist/cli.js.map +1 -0
  22. package/dist/core/config.js +192 -0
  23. package/dist/core/config.js.map +1 -0
  24. package/dist/core/daemon.js +123 -0
  25. package/dist/core/daemon.js.map +1 -0
  26. package/dist/core/ipc.js +214 -0
  27. package/dist/core/ipc.js.map +1 -0
  28. package/dist/core/logger.js +53 -0
  29. package/dist/core/logger.js.map +1 -0
  30. package/dist/core/sound.js +28 -0
  31. package/dist/core/sound.js.map +1 -0
  32. package/dist/core/state-machine.js +268 -0
  33. package/dist/core/state-machine.js.map +1 -0
  34. package/dist/core/stats.js +109 -0
  35. package/dist/core/stats.js.map +1 -0
  36. package/dist/core/targets.js +23 -0
  37. package/dist/core/targets.js.map +1 -0
  38. package/dist/core/types.js +6 -0
  39. package/dist/core/types.js.map +1 -0
  40. package/dist/index.js +15 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/util/errors.js +16 -0
  43. package/dist/util/errors.js.map +1 -0
  44. package/dist/util/paths.js +70 -0
  45. package/dist/util/paths.js.map +1 -0
  46. package/dist/windows/cpu-probe.js +108 -0
  47. package/dist/windows/cpu-probe.js.map +1 -0
  48. package/dist/windows/key-listener.js +198 -0
  49. package/dist/windows/key-listener.js.map +1 -0
  50. package/dist/windows/win32.js +155 -0
  51. package/dist/windows/win32.js.map +1 -0
  52. package/dist/windows/window-controller.js +3 -0
  53. package/dist/windows/window-controller.js.map +1 -0
  54. package/package.json +57 -4
  55. package/scripts/cpu-sampler.ps1 +83 -0
  56. package/scripts/key-watcher.ps1 +132 -0
  57. package/scripts/win32-window.ps1 +344 -0
@@ -0,0 +1,230 @@
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.resolveExecutable = resolveExecutable;
7
+ exports.resolveCommandForPty = resolveCommandForPty;
8
+ exports.runCliWrapper = runCliWrapper;
9
+ const node_fs_1 = __importDefault(require("node:fs"));
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const ipc_1 = require("../core/ipc");
12
+ const types_1 = require("../core/types");
13
+ const errors_1 = require("../util/errors");
14
+ const wrapper_tracker_1 = require("./wrapper-tracker");
15
+ function resolveExecutable(command) {
16
+ if (command.includes('/') || command.includes('\\')) {
17
+ return node_fs_1.default.existsSync(command) ? command : null;
18
+ }
19
+ const pathValue = process.env.PATH ?? '';
20
+ const directories = pathValue.split(node_path_1.default.delimiter).filter(Boolean);
21
+ const extensions = (process.env.PATHEXT ?? '.COM;.EXE;.BAT;.CMD')
22
+ .split(';')
23
+ .filter(Boolean);
24
+ if (!extensions.some((extension) => extension.toLowerCase() === '.ps1')) {
25
+ extensions.push('.PS1');
26
+ }
27
+ const hasExtension = /\.[^\\/]+$/.test(command);
28
+ for (const directory of directories) {
29
+ if (hasExtension) {
30
+ const candidate = node_path_1.default.join(directory, command);
31
+ if (node_fs_1.default.existsSync(candidate))
32
+ return candidate;
33
+ continue;
34
+ }
35
+ // Prefer real Windows executable extensions; the extensionless file in an
36
+ // npm install (C:\Program Files\nodejs\npm) is a Unix shell script.
37
+ for (const extension of [...extensions, '']) {
38
+ const candidate = node_path_1.default.join(directory, `${command}${extension}`);
39
+ if (node_fs_1.default.existsSync(candidate))
40
+ return candidate;
41
+ }
42
+ }
43
+ return null;
44
+ }
45
+ /**
46
+ * Resolves .cmd/.bat npm shims and .ps1 scripts so node-pty can launch them on
47
+ * Windows. Plain executables are spawned directly.
48
+ */
49
+ function resolveCommandForPty(command, args, platform = process.platform) {
50
+ if (platform !== 'win32')
51
+ return { file: command, args };
52
+ const resolved = resolveExecutable(command);
53
+ if (!resolved)
54
+ return { file: command, args };
55
+ const lower = resolved.toLowerCase();
56
+ if (lower.endsWith('.cmd') || lower.endsWith('.bat')) {
57
+ // node-pty launches .cmd/.bat shims through the Windows shell itself.
58
+ // Passing them to `cmd /c` as an argv array mangles quoted paths.
59
+ return { file: resolved, args };
60
+ }
61
+ if (lower.endsWith('.ps1')) {
62
+ return {
63
+ file: 'powershell.exe',
64
+ args: ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', resolved, ...args],
65
+ };
66
+ }
67
+ return { file: resolved, args };
68
+ }
69
+ function loadNodePty(logger) {
70
+ try {
71
+ // Loaded lazily so all non-PTY commands work even if the native module
72
+ // cannot be rebuilt on this machine.
73
+ return require('node-pty');
74
+ }
75
+ catch (error) {
76
+ logger.error(`node-pty is not available: ${(0, errors_1.errorMessage)(error)}`);
77
+ return null;
78
+ }
79
+ }
80
+ function terminalSize() {
81
+ const cols = process.stdout.columns && process.stdout.columns > 0 ? process.stdout.columns : 120;
82
+ const rows = process.stdout.rows && process.stdout.rows > 0 ? process.stdout.rows : 30;
83
+ return { cols, rows };
84
+ }
85
+ async function runCliWrapper(commandArgs, config, logger) {
86
+ if (commandArgs.length === 0) {
87
+ process.stderr.write('Usage: doomscroller run -- <command> [args...]\n');
88
+ process.stderr.write('Example: doomscroller run -- claude\n');
89
+ return 2;
90
+ }
91
+ const ptyModule = loadNodePty(logger);
92
+ if (!ptyModule) {
93
+ process.stderr.write('doomscroller run: node-pty is not available. Re-run "npm install" in the doomscroller directory.\n');
94
+ return 1;
95
+ }
96
+ const resolved = resolveCommandForPty(commandArgs[0], commandArgs.slice(1));
97
+ const size = terminalSize();
98
+ const env = {};
99
+ for (const [key, value] of Object.entries(process.env)) {
100
+ if (typeof value === 'string')
101
+ env[key] = value;
102
+ }
103
+ let pty;
104
+ try {
105
+ pty = ptyModule.spawn(resolved.file, resolved.args, {
106
+ name: 'xterm-256color',
107
+ cols: size.cols,
108
+ rows: size.rows,
109
+ cwd: process.cwd(),
110
+ env,
111
+ });
112
+ }
113
+ catch (error) {
114
+ process.stderr.write(`doomscroller run: could not start command: ${(0, errors_1.errorMessage)(error)}\n`);
115
+ return 1;
116
+ }
117
+ const client = new ipc_1.EventClient(config.port);
118
+ const tracker = new wrapper_tracker_1.WrapperActivityTracker({
119
+ quietMs: Math.max(1, config.quietSeconds) * 1000,
120
+ onStarted: () => client.emit(types_1.AGENT_STARTED),
121
+ onFinished: () => client.emit(types_1.AGENT_FINISHED),
122
+ });
123
+ const wasRaw = process.stdin.isTTY ? process.stdin.isRaw : false;
124
+ return new Promise((resolve) => {
125
+ let cleaned = false;
126
+ const onStdin = (chunk) => {
127
+ const text = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
128
+ tracker.onInput(text);
129
+ try {
130
+ pty.write(text);
131
+ }
132
+ catch {
133
+ // The child may have exited.
134
+ }
135
+ };
136
+ const onResize = () => {
137
+ const next = terminalSize();
138
+ try {
139
+ pty.resize(next.cols, next.rows);
140
+ }
141
+ catch {
142
+ // ignore
143
+ }
144
+ };
145
+ const onSignal = () => {
146
+ try {
147
+ pty.kill();
148
+ }
149
+ catch {
150
+ // ignore
151
+ }
152
+ };
153
+ const cleanup = () => {
154
+ if (cleaned)
155
+ return;
156
+ cleaned = true;
157
+ try {
158
+ process.stdin.pause();
159
+ }
160
+ catch {
161
+ // ignore
162
+ }
163
+ if (process.stdin.isTTY) {
164
+ try {
165
+ process.stdin.setRawMode(Boolean(wasRaw));
166
+ }
167
+ catch {
168
+ // ignore
169
+ }
170
+ }
171
+ try {
172
+ process.stdin.off('data', onStdin);
173
+ }
174
+ catch {
175
+ // ignore
176
+ }
177
+ try {
178
+ process.stdout.off('resize', onResize);
179
+ }
180
+ catch {
181
+ // ignore
182
+ }
183
+ try {
184
+ process.off('SIGINT', onSignal);
185
+ process.off('SIGTERM', onSignal);
186
+ }
187
+ catch {
188
+ // ignore
189
+ }
190
+ tracker.dispose();
191
+ };
192
+ const dataSubscription = pty.onData((data) => {
193
+ try {
194
+ process.stdout.write(data);
195
+ }
196
+ catch {
197
+ // ignore
198
+ }
199
+ tracker.onOutput(data);
200
+ });
201
+ if (process.stdin.isTTY) {
202
+ try {
203
+ process.stdin.setRawMode(true);
204
+ }
205
+ catch {
206
+ // Not fatal; line-buffered input still works.
207
+ }
208
+ }
209
+ process.stdin.resume();
210
+ process.stdin.on('data', onStdin);
211
+ process.stdout.on('resize', onResize);
212
+ process.on('SIGINT', onSignal);
213
+ process.on('SIGTERM', onSignal);
214
+ pty.onExit(({ exitCode }) => {
215
+ tracker.onExit();
216
+ void (async () => {
217
+ await client.flush();
218
+ try {
219
+ dataSubscription.dispose();
220
+ }
221
+ catch {
222
+ // ignore
223
+ }
224
+ cleanup();
225
+ resolve(typeof exitCode === 'number' ? exitCode : 0);
226
+ })();
227
+ });
228
+ });
229
+ }
230
+ //# sourceMappingURL=cli-wrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-wrapper.js","sourceRoot":"","sources":["../../src/adapters/cli-wrapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
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.scanMaxMtime = scanMaxMtime;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const IGNORED_DIRECTORIES = new Set([
10
+ '.git',
11
+ '.hg',
12
+ '.svn',
13
+ 'node_modules',
14
+ 'dist',
15
+ 'build',
16
+ 'out',
17
+ '.next',
18
+ '.nuxt',
19
+ '.svelte-kit',
20
+ '.turbo',
21
+ '.cache',
22
+ 'coverage',
23
+ 'target',
24
+ '.venv',
25
+ 'venv',
26
+ '__pycache__',
27
+ '.pytest_cache',
28
+ '.mypy_cache',
29
+ '.gradle',
30
+ '.idea',
31
+ 'bin',
32
+ 'obj',
33
+ ]);
34
+ /**
35
+ * Returns the newest modification time found in a workspace. Used only as an
36
+ * activity signal, so the scan is deliberately bounded and skips build output.
37
+ */
38
+ async function scanMaxMtime(root, options = {}) {
39
+ const maxEntries = options.maxEntries ?? 4000;
40
+ const ignored = options.ignoredDirectories ?? IGNORED_DIRECTORIES;
41
+ let newest = 0;
42
+ let entriesSeen = 0;
43
+ const stack = [root];
44
+ while (stack.length > 0 && entriesSeen < maxEntries) {
45
+ const directory = stack.pop();
46
+ let entries;
47
+ try {
48
+ entries = await node_fs_1.default.promises.readdir(directory, { withFileTypes: true });
49
+ }
50
+ catch {
51
+ continue;
52
+ }
53
+ for (const entry of entries) {
54
+ if (entriesSeen >= maxEntries)
55
+ break;
56
+ entriesSeen++;
57
+ if (entry.isSymbolicLink())
58
+ continue;
59
+ if (entry.isDirectory()) {
60
+ if (!ignored.has(entry.name))
61
+ stack.push(node_path_1.default.join(directory, entry.name));
62
+ continue;
63
+ }
64
+ if (!entry.isFile())
65
+ continue;
66
+ try {
67
+ const stats = await node_fs_1.default.promises.stat(node_path_1.default.join(directory, entry.name));
68
+ if (stats.mtimeMs > newest)
69
+ newest = stats.mtimeMs;
70
+ }
71
+ catch {
72
+ // File disappeared or is locked; ignore.
73
+ }
74
+ }
75
+ }
76
+ return newest;
77
+ }
78
+ //# sourceMappingURL=file-activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-activity.js","sourceRoot":"","sources":["../../src/adapters/file-activity.ts"],"names":[],"mappings":";;;;;AAsCA,oCAsCC;AA5ED,sDAAyB;AACzB,0DAA6B;AAE7B,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,MAAM;IACN,KAAK;IACL,MAAM;IACN,cAAc;IACd,MAAM;IACN,OAAO;IACP,KAAK;IACL,OAAO;IACP,OAAO;IACP,aAAa;IACb,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,QAAQ;IACR,OAAO;IACP,MAAM;IACN,aAAa;IACb,eAAe;IACf,aAAa;IACb,SAAS;IACT,OAAO;IACP,KAAK;IACL,KAAK;CACN,CAAC,CAAC;AAOH;;;GAGG;AACI,KAAK,UAAU,YAAY,CAAC,IAAY,EAAE,UAAuB,EAAE;IACxE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;IAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,kBAAkB,IAAI,mBAAmB,CAAC;IAElE,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,MAAM,KAAK,GAAa,CAAC,IAAI,CAAC,CAAC;IAE/B,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,GAAG,UAAU,EAAE,CAAC;QACpD,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;QAC/B,IAAI,OAAoB,CAAC;QACzB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,iBAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1E,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,WAAW,IAAI,UAAU;gBAAE,MAAM;YACrC,WAAW,EAAE,CAAC;YAEd,IAAI,KAAK,CAAC,cAAc,EAAE;gBAAE,SAAS;YACrC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC3E,SAAS;YACX,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;gBAAE,SAAS;YAE9B,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,iBAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;gBACvE,IAAI,KAAK,CAAC,OAAO,GAAG,MAAM;oBAAE,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC;YACrD,CAAC;YAAC,MAAM,CAAC;gBACP,yCAAyC;YAC3C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.emitHookEvent = emitHookEvent;
4
+ const ipc_1 = require("../core/ipc");
5
+ /**
6
+ * Hook entry point. Runs in an agent-spawned process, so every failure is
7
+ * swallowed and the caller is never blocked.
8
+ */
9
+ async function emitHookEvent(event, port) {
10
+ try {
11
+ await (0, ipc_1.dispatchFast)(event, port);
12
+ }
13
+ catch {
14
+ // Intentionally silent: hooks must never break the agent.
15
+ }
16
+ }
17
+ //# sourceMappingURL=hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/adapters/hook.ts"],"names":[],"mappings":";;AAOA,sCAMC;AAbD,qCAA2C;AAG3C;;;GAGG;AACI,KAAK,UAAU,aAAa,CAAC,KAAiB,EAAE,IAAY;IACjE,IAAI,CAAC;QACH,MAAM,IAAA,kBAAY,EAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;IAC5D,CAAC;AACH,CAAC"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HotkeyAdapter = void 0;
4
+ const types_1 = require("../core/types");
5
+ const errors_1 = require("../util/errors");
6
+ const key_listener_1 = require("../windows/key-listener");
7
+ /**
8
+ * Default adapter: Ctrl+Alt+D starts a session when idle and force-returns
9
+ * the agent window when a session is already running.
10
+ */
11
+ class HotkeyAdapter {
12
+ deps;
13
+ unsubscribe = null;
14
+ constructor(deps) {
15
+ this.deps = deps;
16
+ }
17
+ start() {
18
+ if (!this.deps.hotkey) {
19
+ this.deps.logger.info('global hotkey disabled');
20
+ return;
21
+ }
22
+ this.unsubscribe = this.deps.listener.onKey((event) => {
23
+ if (!(0, key_listener_1.matchesHotkey)(event, this.deps.hotkey))
24
+ return;
25
+ try {
26
+ if (this.deps.machine.state === 'working') {
27
+ this.deps.logger.info('hotkey: force return');
28
+ void this.deps.machine.forceReturn('hotkey').catch((error) => {
29
+ this.deps.logger.warn(`hotkey force return failed: ${(0, errors_1.errorMessage)(error)}`);
30
+ });
31
+ }
32
+ else {
33
+ this.deps.logger.info('hotkey: agent started');
34
+ void this.deps.machine.handle(types_1.AGENT_STARTED).catch((error) => {
35
+ this.deps.logger.warn(`hotkey start failed: ${(0, errors_1.errorMessage)(error)}`);
36
+ });
37
+ }
38
+ }
39
+ catch (error) {
40
+ this.deps.logger.warn(`hotkey handler failed: ${(0, errors_1.errorMessage)(error)}`);
41
+ }
42
+ });
43
+ }
44
+ stop() {
45
+ this.unsubscribe?.();
46
+ this.unsubscribe = null;
47
+ }
48
+ }
49
+ exports.HotkeyAdapter = HotkeyAdapter;
50
+ //# sourceMappingURL=hotkey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hotkey.js","sourceRoot":"","sources":["../../src/adapters/hotkey.ts"],"names":[],"mappings":";;;AACA,yCAA8C;AAC9C,2CAA8C;AAC9C,0DAAoE;AAUpE;;;GAGG;AACH,MAAa,aAAa;IAGK;IAFrB,WAAW,GAAwB,IAAI,CAAC;IAEhD,YAA6B,IAAuB;QAAvB,SAAI,GAAJ,IAAI,CAAmB;IAAG,CAAC;IAExD,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACtB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACpD,IAAI,CAAC,IAAA,4BAAa,EAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,MAAO,CAAC;gBAAE,OAAO;YACrD,IAAI,CAAC;gBACH,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC1C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;oBAC9C,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;wBAC3D,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+BAA+B,IAAA,qBAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBAC9E,CAAC,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;oBAC/C,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,qBAAa,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;wBAC3D,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,IAAA,qBAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBACvE,CAAC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,0BAA0B,IAAA,qBAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACzE,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI;QACF,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;CACF;AAlCD,sCAkCC"}
@@ -0,0 +1,245 @@
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.IdeActivityAdapter = exports.systemIntervals = void 0;
7
+ exports.normalizeProcessName = normalizeProcessName;
8
+ exports.windowMatches = windowMatches;
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const logger_1 = require("../core/logger");
11
+ const types_1 = require("../core/types");
12
+ const errors_1 = require("../util/errors");
13
+ const paths_1 = require("../util/paths");
14
+ const file_activity_1 = require("./file-activity");
15
+ exports.systemIntervals = {
16
+ setInterval: (callback, intervalMs) => setInterval(callback, intervalMs),
17
+ clearInterval: (handle) => clearInterval(handle),
18
+ };
19
+ function normalizeProcessName(value) {
20
+ return value.trim().toLowerCase().replace(/\.exe$/i, '');
21
+ }
22
+ function windowMatches(window, match) {
23
+ if (!match)
24
+ return false;
25
+ const wantedProcess = match.process ? normalizeProcessName(match.process) : '';
26
+ const wantedTitle = match.title ? match.title.trim().toLowerCase() : '';
27
+ if (!wantedProcess && !wantedTitle)
28
+ return false;
29
+ if (wantedProcess && normalizeProcessName(window.processName) !== wantedProcess)
30
+ return false;
31
+ if (wantedTitle && !window.title.toLowerCase().includes(wantedTitle))
32
+ return false;
33
+ return true;
34
+ }
35
+ /**
36
+ * GUI-agent adapter. Enter inside a registered IDE window starts a session.
37
+ * A session finishes after quietSeconds with no workspace file changes and
38
+ * low CPU across the window's process tree.
39
+ */
40
+ class IdeActivityAdapter {
41
+ deps;
42
+ unsubscribe = null;
43
+ session = null;
44
+ starting = false;
45
+ finishing = false;
46
+ intervals;
47
+ now;
48
+ scanWorkspace;
49
+ constructor(deps) {
50
+ this.deps = deps;
51
+ this.intervals = deps.intervals ?? exports.systemIntervals;
52
+ this.now = deps.now ?? Date.now;
53
+ this.scanWorkspace = deps.scanWorkspace ?? file_activity_1.scanMaxMtime;
54
+ }
55
+ currentState() {
56
+ return this.deps.machine.state;
57
+ }
58
+ get isMonitoring() {
59
+ return this.session !== null;
60
+ }
61
+ start() {
62
+ if (!this.deps.keySource)
63
+ return;
64
+ this.unsubscribe = this.deps.keySource.onKey((event) => {
65
+ void this.handleKeyEvent(event);
66
+ });
67
+ }
68
+ stop() {
69
+ this.unsubscribe?.();
70
+ this.unsubscribe = null;
71
+ this.stopMonitor();
72
+ }
73
+ findAgentForWindow(window) {
74
+ for (const agent of this.deps.config.registeredAgents) {
75
+ if (agent.adapter !== 'ide-activity')
76
+ continue;
77
+ if (windowMatches(window, agent.match))
78
+ return agent;
79
+ }
80
+ return null;
81
+ }
82
+ async handleKeyEvent(event) {
83
+ try {
84
+ if (event.key !== 'ENTER' || !event.window)
85
+ return;
86
+ if (this.session || this.starting || this.finishing)
87
+ return;
88
+ if (this.currentState() === 'working')
89
+ return;
90
+ const agent = this.findAgentForWindow(event.window);
91
+ if (!agent)
92
+ return;
93
+ await this.beginSession(agent, event.window);
94
+ }
95
+ catch (error) {
96
+ this.starting = false;
97
+ this.stopMonitor();
98
+ (0, logger_1.logCaught)(this.deps.logger, 'ide-activity key handling failed', error);
99
+ }
100
+ }
101
+ async tick() {
102
+ const session = this.session;
103
+ if (!session)
104
+ return;
105
+ if (this.currentState() !== 'working') {
106
+ this.stopMonitor();
107
+ return;
108
+ }
109
+ if (session.ticking)
110
+ return;
111
+ session.ticking = true;
112
+ try {
113
+ const now = this.now();
114
+ let activity = false;
115
+ const sample = session.probe.latest();
116
+ if (sample && sample.alive && sample.at !== session.lastCpuAt) {
117
+ if (session.lastCpuSeconds !== null) {
118
+ const elapsedSeconds = (sample.at - session.lastCpuAt) / 1000;
119
+ const deltaSeconds = Math.max(0, sample.cpuSeconds - session.lastCpuSeconds);
120
+ if (elapsedSeconds > 0) {
121
+ const cpuPercent = (deltaSeconds / elapsedSeconds) * 100;
122
+ if (cpuPercent > this.deps.config.idleCpuPercent)
123
+ activity = true;
124
+ }
125
+ }
126
+ session.lastCpuSeconds = sample.cpuSeconds;
127
+ session.lastCpuAt = sample.at;
128
+ }
129
+ const scanInterval = this.deps.scanIntervalMs ?? 2000;
130
+ if (session.workspace && now - session.lastScanAt >= scanInterval) {
131
+ session.lastScanAt = now;
132
+ try {
133
+ const newest = await this.scanWorkspace(session.workspace);
134
+ if (newest > session.lastMaxMtime) {
135
+ session.lastMaxMtime = newest;
136
+ activity = true;
137
+ }
138
+ }
139
+ catch (error) {
140
+ this.deps.logger.debug(`workspace scan failed: ${(0, errors_1.errorMessage)(error)}`);
141
+ }
142
+ }
143
+ if (activity)
144
+ session.lastActivityAt = this.now();
145
+ if (this.now() - session.lastActivityAt >= session.quietMs) {
146
+ await this.finishSession(session);
147
+ }
148
+ }
149
+ catch (error) {
150
+ (0, logger_1.logCaught)(this.deps.logger, 'ide-activity tick failed', error);
151
+ }
152
+ finally {
153
+ const current = this.session;
154
+ if (current)
155
+ current.ticking = false;
156
+ }
157
+ }
158
+ async beginSession(agent, window) {
159
+ this.starting = true;
160
+ try {
161
+ if (this.currentState() === 'working')
162
+ return;
163
+ const quietSeconds = agent.quietSeconds ?? this.deps.config.quietSeconds;
164
+ const workspace = agent.workspace ? node_path_1.default.resolve((0, paths_1.expandHome)(agent.workspace)) : null;
165
+ let baseline = 0;
166
+ if (workspace) {
167
+ try {
168
+ baseline = await this.scanWorkspace(workspace);
169
+ }
170
+ catch (error) {
171
+ this.deps.logger.debug(`could not baseline workspace: ${(0, errors_1.errorMessage)(error)}`);
172
+ }
173
+ }
174
+ if (this.currentState() === 'working')
175
+ return;
176
+ const now = this.now();
177
+ const probe = this.deps.cpuProbes.create(window.pid);
178
+ const initial = probe.latest();
179
+ const session = {
180
+ agent,
181
+ quietMs: Math.max(1, quietSeconds) * 1000,
182
+ probe,
183
+ workspace,
184
+ lastMaxMtime: baseline,
185
+ lastScanAt: now,
186
+ lastActivityAt: now,
187
+ lastCpuSeconds: initial?.cpuSeconds ?? null,
188
+ lastCpuAt: initial?.at ?? now,
189
+ timer: null,
190
+ ticking: false,
191
+ };
192
+ this.session = session;
193
+ this.deps.logger.info(`ide-activity: ${agent.name} started ("${window.title}", pid ${window.pid})`);
194
+ await this.deps.machine.handle(types_1.AGENT_STARTED);
195
+ if (!this.session || this.currentState() !== 'working') {
196
+ this.stopMonitor();
197
+ return;
198
+ }
199
+ session.timer = this.intervals.setInterval(() => {
200
+ void this.tick();
201
+ }, this.deps.tickIntervalMs ?? 1000);
202
+ }
203
+ finally {
204
+ this.starting = false;
205
+ }
206
+ }
207
+ async finishSession(session) {
208
+ if (this.session !== session)
209
+ return;
210
+ this.finishing = true;
211
+ try {
212
+ this.deps.logger.info(`ide-activity: ${session.agent.name} idle for ${Math.round(session.quietMs / 1000)}s -> finished`);
213
+ this.stopMonitor();
214
+ await this.deps.machine.handle(types_1.AGENT_FINISHED);
215
+ }
216
+ catch (error) {
217
+ (0, logger_1.logCaught)(this.deps.logger, 'ide-activity finish failed', error);
218
+ }
219
+ finally {
220
+ this.finishing = false;
221
+ }
222
+ }
223
+ stopMonitor() {
224
+ const session = this.session;
225
+ this.session = null;
226
+ if (!session)
227
+ return;
228
+ if (session.timer !== null) {
229
+ try {
230
+ this.intervals.clearInterval(session.timer);
231
+ }
232
+ catch {
233
+ // ignore
234
+ }
235
+ }
236
+ try {
237
+ session.probe.stop();
238
+ }
239
+ catch {
240
+ // ignore
241
+ }
242
+ }
243
+ }
244
+ exports.IdeActivityAdapter = IdeActivityAdapter;
245
+ //# sourceMappingURL=ide-activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ide-activity.js","sourceRoot":"","sources":["../../src/adapters/ide-activity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/adapters/ports.ts"],"names":[],"mappings":""}