claude-pager 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 (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +207 -0
  3. package/dist/channels/channel.d.ts +27 -0
  4. package/dist/channels/channel.d.ts.map +1 -0
  5. package/dist/channels/channel.js +3 -0
  6. package/dist/channels/channel.js.map +1 -0
  7. package/dist/channels/factory.d.ts +4 -0
  8. package/dist/channels/factory.d.ts.map +1 -0
  9. package/dist/channels/factory.js +22 -0
  10. package/dist/channels/factory.js.map +1 -0
  11. package/dist/channels/ntfy/__tests__/provider.test.d.ts +2 -0
  12. package/dist/channels/ntfy/__tests__/provider.test.d.ts.map +1 -0
  13. package/dist/channels/ntfy/__tests__/provider.test.js +29 -0
  14. package/dist/channels/ntfy/__tests__/provider.test.js.map +1 -0
  15. package/dist/channels/ntfy/provider.d.ts +17 -0
  16. package/dist/channels/ntfy/provider.d.ts.map +1 -0
  17. package/dist/channels/ntfy/provider.js +142 -0
  18. package/dist/channels/ntfy/provider.js.map +1 -0
  19. package/dist/channels/telegram/provider.d.ts +27 -0
  20. package/dist/channels/telegram/provider.d.ts.map +1 -0
  21. package/dist/channels/telegram/provider.js +312 -0
  22. package/dist/channels/telegram/provider.js.map +1 -0
  23. package/dist/channels/telegram/voice-handler.d.ts +22 -0
  24. package/dist/channels/telegram/voice-handler.d.ts.map +1 -0
  25. package/dist/channels/telegram/voice-handler.js +68 -0
  26. package/dist/channels/telegram/voice-handler.js.map +1 -0
  27. package/dist/cli/index.d.ts +3 -0
  28. package/dist/cli/index.d.ts.map +1 -0
  29. package/dist/cli/index.js +99 -0
  30. package/dist/cli/index.js.map +1 -0
  31. package/dist/cli/recover.d.ts +2 -0
  32. package/dist/cli/recover.d.ts.map +1 -0
  33. package/dist/cli/recover.js +45 -0
  34. package/dist/cli/recover.js.map +1 -0
  35. package/dist/cli/run.d.ts +2 -0
  36. package/dist/cli/run.d.ts.map +1 -0
  37. package/dist/cli/run.js +32 -0
  38. package/dist/cli/run.js.map +1 -0
  39. package/dist/cli/setup.d.ts +8 -0
  40. package/dist/cli/setup.d.ts.map +1 -0
  41. package/dist/cli/setup.js +238 -0
  42. package/dist/cli/setup.js.map +1 -0
  43. package/dist/config/index.d.ts +6 -0
  44. package/dist/config/index.d.ts.map +1 -0
  45. package/dist/config/index.js +40 -0
  46. package/dist/config/index.js.map +1 -0
  47. package/dist/daemon/__tests__/handlers.test.d.ts +2 -0
  48. package/dist/daemon/__tests__/handlers.test.d.ts.map +1 -0
  49. package/dist/daemon/__tests__/handlers.test.js +99 -0
  50. package/dist/daemon/__tests__/handlers.test.js.map +1 -0
  51. package/dist/daemon/__tests__/server.test.d.ts +2 -0
  52. package/dist/daemon/__tests__/server.test.d.ts.map +1 -0
  53. package/dist/daemon/__tests__/server.test.js +118 -0
  54. package/dist/daemon/__tests__/server.test.js.map +1 -0
  55. package/dist/daemon/handlers.d.ts +4 -0
  56. package/dist/daemon/handlers.d.ts.map +1 -0
  57. package/dist/daemon/handlers.js +153 -0
  58. package/dist/daemon/handlers.js.map +1 -0
  59. package/dist/daemon/index.d.ts +7 -0
  60. package/dist/daemon/index.d.ts.map +1 -0
  61. package/dist/daemon/index.js +83 -0
  62. package/dist/daemon/index.js.map +1 -0
  63. package/dist/daemon/server.d.ts +11 -0
  64. package/dist/daemon/server.d.ts.map +1 -0
  65. package/dist/daemon/server.js +115 -0
  66. package/dist/daemon/server.js.map +1 -0
  67. package/dist/hooks/index.d.ts +3 -0
  68. package/dist/hooks/index.d.ts.map +1 -0
  69. package/dist/hooks/index.js +172 -0
  70. package/dist/hooks/index.js.map +1 -0
  71. package/dist/index.d.ts +4 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +3 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/injectors/__tests__/tmux.test.d.ts +2 -0
  76. package/dist/injectors/__tests__/tmux.test.d.ts.map +1 -0
  77. package/dist/injectors/__tests__/tmux.test.js +38 -0
  78. package/dist/injectors/__tests__/tmux.test.js.map +1 -0
  79. package/dist/injectors/factory.d.ts +3 -0
  80. package/dist/injectors/factory.d.ts.map +1 -0
  81. package/dist/injectors/factory.js +22 -0
  82. package/dist/injectors/factory.js.map +1 -0
  83. package/dist/injectors/injector.d.ts +7 -0
  84. package/dist/injectors/injector.d.ts.map +1 -0
  85. package/dist/injectors/injector.js +3 -0
  86. package/dist/injectors/injector.js.map +1 -0
  87. package/dist/injectors/tmux/injector.d.ts +9 -0
  88. package/dist/injectors/tmux/injector.d.ts.map +1 -0
  89. package/dist/injectors/tmux/injector.js +55 -0
  90. package/dist/injectors/tmux/injector.js.map +1 -0
  91. package/dist/injectors/xdotool/injector.d.ts +9 -0
  92. package/dist/injectors/xdotool/injector.d.ts.map +1 -0
  93. package/dist/injectors/xdotool/injector.js +59 -0
  94. package/dist/injectors/xdotool/injector.js.map +1 -0
  95. package/dist/sessions/__tests__/events.test.d.ts +2 -0
  96. package/dist/sessions/__tests__/events.test.d.ts.map +1 -0
  97. package/dist/sessions/__tests__/events.test.js +103 -0
  98. package/dist/sessions/__tests__/events.test.js.map +1 -0
  99. package/dist/sessions/__tests__/tracker.test.d.ts +2 -0
  100. package/dist/sessions/__tests__/tracker.test.d.ts.map +1 -0
  101. package/dist/sessions/__tests__/tracker.test.js +24 -0
  102. package/dist/sessions/__tests__/tracker.test.js.map +1 -0
  103. package/dist/sessions/events.d.ts +11 -0
  104. package/dist/sessions/events.d.ts.map +1 -0
  105. package/dist/sessions/events.js +73 -0
  106. package/dist/sessions/events.js.map +1 -0
  107. package/dist/sessions/tracker.d.ts +7 -0
  108. package/dist/sessions/tracker.d.ts.map +1 -0
  109. package/dist/sessions/tracker.js +83 -0
  110. package/dist/sessions/tracker.js.map +1 -0
  111. package/dist/types.d.ts +55 -0
  112. package/dist/types.d.ts.map +1 -0
  113. package/dist/types.js +3 -0
  114. package/dist/types.js.map +1 -0
  115. package/dist/utils/__tests__/html.test.d.ts +2 -0
  116. package/dist/utils/__tests__/html.test.d.ts.map +1 -0
  117. package/dist/utils/__tests__/html.test.js +42 -0
  118. package/dist/utils/__tests__/html.test.js.map +1 -0
  119. package/dist/utils/__tests__/json.test.d.ts +2 -0
  120. package/dist/utils/__tests__/json.test.d.ts.map +1 -0
  121. package/dist/utils/__tests__/json.test.js +27 -0
  122. package/dist/utils/__tests__/json.test.js.map +1 -0
  123. package/dist/utils/__tests__/validation.test.d.ts +2 -0
  124. package/dist/utils/__tests__/validation.test.d.ts.map +1 -0
  125. package/dist/utils/__tests__/validation.test.js +38 -0
  126. package/dist/utils/__tests__/validation.test.js.map +1 -0
  127. package/dist/utils/html.d.ts +3 -0
  128. package/dist/utils/html.d.ts.map +1 -0
  129. package/dist/utils/html.js +43 -0
  130. package/dist/utils/html.js.map +1 -0
  131. package/dist/utils/json.d.ts +2 -0
  132. package/dist/utils/json.d.ts.map +1 -0
  133. package/dist/utils/json.js +13 -0
  134. package/dist/utils/json.js.map +1 -0
  135. package/dist/utils/validation.d.ts +4 -0
  136. package/dist/utils/validation.d.ts.map +1 -0
  137. package/dist/utils/validation.js +16 -0
  138. package/dist/utils/validation.js.map +1 -0
  139. package/dist/voice/transcribe.d.ts +7 -0
  140. package/dist/voice/transcribe.d.ts.map +1 -0
  141. package/dist/voice/transcribe.js +66 -0
  142. package/dist/voice/transcribe.js.map +1 -0
  143. package/package.json +50 -0
@@ -0,0 +1,38 @@
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
+ const node_test_1 = require("node:test");
7
+ const strict_1 = __importDefault(require("node:assert/strict"));
8
+ const injector_js_1 = require("../tmux/injector.js");
9
+ const SESSION = {
10
+ sessionId: 'test-1',
11
+ pid: 1234,
12
+ tty: '',
13
+ cwd: '/tmp',
14
+ tmuxPane: '%99',
15
+ timestamp: Date.now(),
16
+ };
17
+ (0, node_test_1.describe)('TmuxInjector', () => {
18
+ (0, node_test_1.it)('should have name "tmux"', () => {
19
+ const injector = new injector_js_1.TmuxInjector();
20
+ strict_1.default.equal(injector.name, 'tmux');
21
+ });
22
+ (0, node_test_1.it)('should return false for resolve when no tmuxPane', async () => {
23
+ const injector = new injector_js_1.TmuxInjector();
24
+ const noPane = { ...SESSION, tmuxPane: undefined };
25
+ strict_1.default.equal(await injector.resolve(noPane), false);
26
+ });
27
+ (0, node_test_1.it)('should return false for sendResponse when no tmuxPane', async () => {
28
+ const injector = new injector_js_1.TmuxInjector();
29
+ const noPane = { ...SESSION, tmuxPane: undefined };
30
+ strict_1.default.equal(await injector.sendResponse(noPane, 'allow', 'permission_prompt'), false);
31
+ });
32
+ (0, node_test_1.it)('should return false for resolve on non-existent pane', async () => {
33
+ const injector = new injector_js_1.TmuxInjector();
34
+ const fakePaneSession = { ...SESSION, tmuxPane: '%99999' };
35
+ strict_1.default.equal(await injector.resolve(fakePaneSession), false);
36
+ });
37
+ });
38
+ //# sourceMappingURL=tmux.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux.test.js","sourceRoot":"","sources":["../../../src/injectors/__tests__/tmux.test.ts"],"names":[],"mappings":";;;;;AAAA,yCAAyC;AACzC,gEAAwC;AACxC,qDAAmD;AAGnD,MAAM,OAAO,GAAgB;IAC3B,SAAS,EAAE,QAAQ;IACnB,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,EAAE;IACP,GAAG,EAAE,MAAM;IACX,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;CACtB,CAAC;AAEF,IAAA,oBAAQ,EAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,IAAA,cAAE,EAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,QAAQ,GAAG,IAAI,0BAAY,EAAE,CAAC;QACpC,gBAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,QAAQ,GAAG,IAAI,0BAAY,EAAE,CAAC;QACpC,MAAM,MAAM,GAAgB,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;QAChE,gBAAM,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,QAAQ,GAAG,IAAI,0BAAY,EAAE,CAAC;QACpC,MAAM,MAAM,GAAgB,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;QAChE,gBAAM,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,mBAAmB,CAAC,EAAE,KAAK,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,QAAQ,GAAG,IAAI,0BAAY,EAAE,CAAC;QACpC,MAAM,eAAe,GAAgB,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;QACxE,gBAAM,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,KAAK,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { InputInjector } from './injector.js';
2
+ export declare function createInjector(type: 'auto' | 'tmux' | 'xdotool' | 'applescript'): InputInjector;
3
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/injectors/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAInD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,CAe/F"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createInjector = createInjector;
4
+ const injector_js_1 = require("./tmux/injector.js");
5
+ const injector_js_2 = require("./xdotool/injector.js");
6
+ function createInjector(type) {
7
+ switch (type) {
8
+ case 'tmux':
9
+ return new injector_js_1.TmuxInjector();
10
+ case 'xdotool':
11
+ return new injector_js_2.XdotoolInjector();
12
+ case 'auto':
13
+ // Prefer tmux if available, fallback to xdotool
14
+ if (process.platform === 'linux') {
15
+ return new injector_js_1.TmuxInjector();
16
+ }
17
+ throw new Error(`No injector available for platform: ${process.platform}`);
18
+ default:
19
+ throw new Error(`Unknown injector type: ${type}`);
20
+ }
21
+ }
22
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/injectors/factory.ts"],"names":[],"mappings":";;AAIA,wCAeC;AAlBD,oDAAkD;AAClD,uDAAwD;AAExD,SAAgB,cAAc,CAAC,IAAiD;IAC9E,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,MAAM;YACT,OAAO,IAAI,0BAAY,EAAE,CAAC;QAC5B,KAAK,SAAS;YACZ,OAAO,IAAI,6BAAe,EAAE,CAAC;QAC/B,KAAK,MAAM;YACT,gDAAgD;YAChD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBACjC,OAAO,IAAI,0BAAY,EAAE,CAAC;YAC5B,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC7E;YACE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { EventType, SessionInfo } from '../types.js';
2
+ export interface InputInjector {
3
+ readonly name: string;
4
+ resolve(session: SessionInfo): Promise<boolean>;
5
+ sendResponse(session: SessionInfo, text: string, eventType: EventType): Promise<boolean>;
6
+ }
7
+ //# sourceMappingURL=injector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injector.d.ts","sourceRoot":"","sources":["../../src/injectors/injector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhD,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1F"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=injector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injector.js","sourceRoot":"","sources":["../../src/injectors/injector.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import type { InputInjector } from '../injector.js';
2
+ import type { EventType, SessionInfo } from '../../types.js';
3
+ export declare class TmuxInjector implements InputInjector {
4
+ readonly name = "tmux";
5
+ resolve(session: SessionInfo): Promise<boolean>;
6
+ sendResponse(session: SessionInfo, text: string, eventType: EventType): Promise<boolean>;
7
+ private handlePermissionPrompt;
8
+ }
9
+ //# sourceMappingURL=injector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injector.d.ts","sourceRoot":"","sources":["../../../src/injectors/tmux/injector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAI7D,qBAAa,YAAa,YAAW,aAAa;IAChD,QAAQ,CAAC,IAAI,UAAU;IAEjB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAU/C,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;YAiBhF,sBAAsB;CAerC"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TmuxInjector = void 0;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const node_util_1 = require("node:util");
6
+ const exec = (0, node_util_1.promisify)(node_child_process_1.execFile);
7
+ class TmuxInjector {
8
+ name = 'tmux';
9
+ async resolve(session) {
10
+ if (!session.tmuxPane)
11
+ return false;
12
+ try {
13
+ await exec('tmux', ['has-session', '-t', session.tmuxPane]);
14
+ return true;
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ async sendResponse(session, text, eventType) {
21
+ if (!session.tmuxPane)
22
+ return false;
23
+ const pane = session.tmuxPane;
24
+ try {
25
+ if (eventType === 'permission_prompt') {
26
+ return await this.handlePermissionPrompt(pane, text);
27
+ }
28
+ // For other prompts (idle_prompt, etc.), type the text + Enter
29
+ await exec('tmux', ['send-keys', '-t', pane, text, 'Enter']);
30
+ return true;
31
+ }
32
+ catch (err) {
33
+ console.error('[tmux] sendResponse error:', err);
34
+ return false;
35
+ }
36
+ }
37
+ async handlePermissionPrompt(pane, text) {
38
+ const lower = text.toLowerCase().trim();
39
+ if (['allow', 'yes', 'y'].includes(lower)) {
40
+ // Option 1 "Yes" is always first and already selected — just press Enter
41
+ await exec('tmux', ['send-keys', '-t', pane, 'Enter']);
42
+ }
43
+ else if (['deny', 'no', 'n'].includes(lower)) {
44
+ // "No" is always the last option — End jumps to it
45
+ await exec('tmux', ['send-keys', '-t', pane, 'End', 'Enter']);
46
+ }
47
+ else {
48
+ // Free text — type it and press Enter
49
+ await exec('tmux', ['send-keys', '-t', pane, text, 'Enter']);
50
+ }
51
+ return true;
52
+ }
53
+ }
54
+ exports.TmuxInjector = TmuxInjector;
55
+ //# sourceMappingURL=injector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injector.js","sourceRoot":"","sources":["../../../src/injectors/tmux/injector.ts"],"names":[],"mappings":";;;AAAA,2DAA8C;AAC9C,yCAAsC;AAItC,MAAM,IAAI,GAAG,IAAA,qBAAS,EAAC,6BAAQ,CAAC,CAAC;AAEjC,MAAa,YAAY;IACd,IAAI,GAAG,MAAM,CAAC;IAEvB,KAAK,CAAC,OAAO,CAAC,OAAoB;QAChC,IAAI,CAAC,OAAO,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAAoB,EAAE,IAAY,EAAE,SAAoB;QACzE,IAAI,CAAC,OAAO,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QACpC,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC;QAE9B,IAAI,CAAC;YACH,IAAI,SAAS,KAAK,mBAAmB,EAAE,CAAC;gBACtC,OAAO,MAAM,IAAI,CAAC,sBAAsB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACvD,CAAC;YACD,+DAA+D;YAC/D,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;YAC7D,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;YACjD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,sBAAsB,CAAC,IAAY,EAAE,IAAY;QAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QAExC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1C,yEAAyE;YACzE,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QACzD,CAAC;aAAM,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,mDAAmD;YACnD,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QAChE,CAAC;aAAM,CAAC;YACN,sCAAsC;YACtC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AA7CD,oCA6CC"}
@@ -0,0 +1,9 @@
1
+ import type { InputInjector } from '../injector.js';
2
+ import type { EventType, SessionInfo } from '../../types.js';
3
+ export declare class XdotoolInjector implements InputInjector {
4
+ readonly name = "xdotool";
5
+ resolve(session: SessionInfo): Promise<boolean>;
6
+ sendResponse(session: SessionInfo, text: string, eventType: EventType): Promise<boolean>;
7
+ private findWindow;
8
+ }
9
+ //# sourceMappingURL=injector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injector.d.ts","sourceRoot":"","sources":["../../../src/injectors/xdotool/injector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAI7D,qBAAa,eAAgB,YAAW,aAAa;IACnD,QAAQ,CAAC,IAAI,aAAa;IAEpB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAI/C,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;YA6BhF,UAAU;CAWzB"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.XdotoolInjector = void 0;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const node_util_1 = require("node:util");
6
+ const exec = (0, node_util_1.promisify)(node_child_process_1.execFile);
7
+ class XdotoolInjector {
8
+ name = 'xdotool';
9
+ async resolve(session) {
10
+ return (await this.findWindow(session)) !== null;
11
+ }
12
+ async sendResponse(session, text, eventType) {
13
+ const windowId = await this.findWindow(session);
14
+ if (!windowId)
15
+ return false;
16
+ try {
17
+ await exec('xdotool', ['windowactivate', '--sync', String(windowId)]);
18
+ await new Promise(r => setTimeout(r, 100));
19
+ if (eventType === 'permission_prompt') {
20
+ const lower = text.toLowerCase().trim();
21
+ if (['allow', 'yes', 'y'].includes(lower)) {
22
+ await exec('xdotool', ['key', '--window', String(windowId), 'Return']);
23
+ }
24
+ else if (['deny', 'no', 'n'].includes(lower)) {
25
+ await exec('xdotool', ['key', '--window', String(windowId), 'End', 'Return']);
26
+ }
27
+ else {
28
+ await exec('xdotool', ['type', '--window', String(windowId), '--clearmodifiers', text]);
29
+ await exec('xdotool', ['key', '--window', String(windowId), 'Return']);
30
+ }
31
+ }
32
+ else {
33
+ await exec('xdotool', ['type', '--window', String(windowId), '--clearmodifiers', text]);
34
+ await exec('xdotool', ['key', '--window', String(windowId), 'Return']);
35
+ }
36
+ return true;
37
+ }
38
+ catch (err) {
39
+ console.error('[xdotool] sendResponse error:', err);
40
+ return false;
41
+ }
42
+ }
43
+ async findWindow(session) {
44
+ if (session.windowId)
45
+ return session.windowId;
46
+ try {
47
+ const { stdout } = await exec('xdotool', ['search', '--pid', String(session.pid)]);
48
+ const ids = stdout.trim().split('\n').filter(Boolean);
49
+ if (ids.length === 0)
50
+ return null;
51
+ return parseInt(ids[ids.length - 1], 10);
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ }
58
+ exports.XdotoolInjector = XdotoolInjector;
59
+ //# sourceMappingURL=injector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injector.js","sourceRoot":"","sources":["../../../src/injectors/xdotool/injector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=events.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.test.d.ts","sourceRoot":"","sources":["../../../src/sessions/__tests__/events.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,103 @@
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
+ const node_test_1 = require("node:test");
7
+ const strict_1 = __importDefault(require("node:assert/strict"));
8
+ const events_js_1 = require("../events.js");
9
+ function makeEvent(id, overrides) {
10
+ return {
11
+ id,
12
+ sessionId: 'session-1',
13
+ type: 'permission_prompt',
14
+ message: 'Allow Bash(git status)?',
15
+ project: '/home/user/dev/myproject',
16
+ timestamp: Date.now(),
17
+ ...overrides,
18
+ };
19
+ }
20
+ (0, node_test_1.describe)('event store', () => {
21
+ (0, node_test_1.beforeEach)(() => {
22
+ for (const q of (0, events_js_1.listPending)()) {
23
+ (0, events_js_1.removePending)(q.event.id);
24
+ }
25
+ });
26
+ (0, node_test_1.it)('should add and retrieve a pending question', () => {
27
+ const event = makeEvent('evt-1');
28
+ const shortId = (0, events_js_1.addPending)(event, 'msg-123');
29
+ const q = (0, events_js_1.getPending)('evt-1');
30
+ strict_1.default.ok(q);
31
+ strict_1.default.equal(q.event.id, 'evt-1');
32
+ strict_1.default.equal(q.channelMessageId, 'msg-123');
33
+ strict_1.default.ok(q.shortId);
34
+ strict_1.default.ok(shortId);
35
+ });
36
+ (0, node_test_1.it)('should return undefined for unknown event', () => {
37
+ strict_1.default.equal((0, events_js_1.getPending)('nonexistent'), undefined);
38
+ });
39
+ (0, node_test_1.it)('should list all pending questions', () => {
40
+ (0, events_js_1.addPending)(makeEvent('evt-1'));
41
+ (0, events_js_1.addPending)(makeEvent('evt-2'));
42
+ (0, events_js_1.addPending)(makeEvent('evt-3'));
43
+ strict_1.default.equal((0, events_js_1.listPending)().length, 3);
44
+ });
45
+ (0, node_test_1.it)('should remove a pending question', () => {
46
+ (0, events_js_1.addPending)(makeEvent('evt-1'));
47
+ strict_1.default.ok((0, events_js_1.getPending)('evt-1'));
48
+ (0, events_js_1.removePending)('evt-1');
49
+ strict_1.default.equal((0, events_js_1.getPending)('evt-1'), undefined);
50
+ });
51
+ (0, node_test_1.describe)('resolveResponse', () => {
52
+ (0, node_test_1.it)('should return null when no pending questions', () => {
53
+ strict_1.default.equal((0, events_js_1.resolveResponse)('allow'), null);
54
+ });
55
+ (0, node_test_1.it)('should route any text to the single pending question', () => {
56
+ (0, events_js_1.addPending)(makeEvent('evt-1'));
57
+ const result = (0, events_js_1.resolveResponse)('allow');
58
+ strict_1.default.ok(result);
59
+ strict_1.default.equal(result.question.event.id, 'evt-1');
60
+ strict_1.default.equal(result.response, 'allow');
61
+ });
62
+ (0, node_test_1.it)('should route free text to single pending question', () => {
63
+ (0, events_js_1.addPending)(makeEvent('evt-1', { type: 'idle_prompt' }));
64
+ const result = (0, events_js_1.resolveResponse)('yes go ahead and fix the tests');
65
+ strict_1.default.ok(result);
66
+ strict_1.default.equal(result.question.event.id, 'evt-1');
67
+ strict_1.default.equal(result.response, 'yes go ahead and fix the tests');
68
+ });
69
+ (0, node_test_1.it)('should route allow/deny to most recent permission_prompt when multiple pending', () => {
70
+ (0, events_js_1.addPending)(makeEvent('evt-1', { type: 'idle_prompt' }));
71
+ (0, events_js_1.addPending)(makeEvent('evt-2', { type: 'permission_prompt' }));
72
+ (0, events_js_1.addPending)(makeEvent('evt-3', { type: 'permission_prompt' }));
73
+ const result = (0, events_js_1.resolveResponse)('allow');
74
+ strict_1.default.ok(result);
75
+ strict_1.default.equal(result.question.event.id, 'evt-3');
76
+ strict_1.default.equal(result.response, 'allow');
77
+ });
78
+ (0, node_test_1.it)('should route numbered response to the correct question', () => {
79
+ const shortId1 = (0, events_js_1.addPending)(makeEvent('evt-1'));
80
+ (0, events_js_1.addPending)(makeEvent('evt-2'));
81
+ const result = (0, events_js_1.resolveResponse)(`#${shortId1} deny`);
82
+ strict_1.default.ok(result);
83
+ strict_1.default.equal(result.question.event.id, 'evt-1');
84
+ strict_1.default.equal(result.response, 'deny');
85
+ });
86
+ (0, node_test_1.it)('should route numbered response without # prefix', () => {
87
+ const shortId1 = (0, events_js_1.addPending)(makeEvent('evt-1'));
88
+ (0, events_js_1.addPending)(makeEvent('evt-2'));
89
+ const result = (0, events_js_1.resolveResponse)(`${shortId1} deny`);
90
+ strict_1.default.ok(result);
91
+ strict_1.default.equal(result.question.event.id, 'evt-1');
92
+ strict_1.default.equal(result.response, 'deny');
93
+ });
94
+ (0, node_test_1.it)('should fallback to most recent for ambiguous free text', () => {
95
+ (0, events_js_1.addPending)(makeEvent('evt-1', { type: 'idle_prompt' }));
96
+ (0, events_js_1.addPending)(makeEvent('evt-2', { type: 'idle_prompt' }));
97
+ const result = (0, events_js_1.resolveResponse)('do the thing');
98
+ strict_1.default.ok(result);
99
+ strict_1.default.equal(result.question.event.id, 'evt-2');
100
+ });
101
+ });
102
+ });
103
+ //# sourceMappingURL=events.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.test.js","sourceRoot":"","sources":["../../../src/sessions/__tests__/events.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tracker.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.test.d.ts","sourceRoot":"","sources":["../../../src/sessions/__tests__/tracker.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
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
+ const node_test_1 = require("node:test");
7
+ const strict_1 = __importDefault(require("node:assert/strict"));
8
+ async function loadTracker() {
9
+ const { isProcessAlive } = await import('../tracker.js');
10
+ return { isProcessAlive };
11
+ }
12
+ (0, node_test_1.describe)('session tracker', () => {
13
+ (0, node_test_1.describe)('isProcessAlive', () => {
14
+ (0, node_test_1.it)('should return true for current process', async () => {
15
+ const { isProcessAlive } = await loadTracker();
16
+ strict_1.default.equal(isProcessAlive(process.pid), true);
17
+ });
18
+ (0, node_test_1.it)('should return false for non-existent PID', async () => {
19
+ const { isProcessAlive } = await loadTracker();
20
+ strict_1.default.equal(isProcessAlive(99999999), false);
21
+ });
22
+ });
23
+ });
24
+ //# sourceMappingURL=tracker.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.test.js","sourceRoot":"","sources":["../../../src/sessions/__tests__/tracker.test.ts"],"names":[],"mappings":";;;;;AAAA,yCAAyC;AACzC,gEAAwC;AAExC,KAAK,UAAU,WAAW;IACxB,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;IACzD,OAAO,EAAE,cAAc,EAAE,CAAC;AAC5B,CAAC;AAED,IAAA,oBAAQ,EAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,IAAA,oBAAQ,EAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,IAAA,cAAE,EAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,WAAW,EAAE,CAAC;YAC/C,gBAAM,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,IAAA,cAAE,EAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;YACxD,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,WAAW,EAAE,CAAC;YAC/C,gBAAM,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { PendingQuestion, RelayEvent } from '../types.js';
2
+ export declare function addPending(event: RelayEvent, channelMessageId?: string): string;
3
+ export declare function getPending(eventId: string): PendingQuestion | undefined;
4
+ export declare function removePending(eventId: string): void;
5
+ export declare function listPending(): PendingQuestion[];
6
+ export interface ResolvedResponse {
7
+ question: PendingQuestion;
8
+ response: string;
9
+ }
10
+ export declare function resolveResponse(rawText: string): ResolvedResponse | null;
11
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/sessions/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAM/D,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAU/E;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEvE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEnD;AAID,wBAAgB,WAAW,IAAI,eAAe,EAAE,CAS/C;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAsCxE"}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addPending = addPending;
4
+ exports.getPending = getPending;
5
+ exports.removePending = removePending;
6
+ exports.listPending = listPending;
7
+ exports.resolveResponse = resolveResponse;
8
+ const pending = new Map();
9
+ let nextShortId = (Date.now() % 10000) + 1;
10
+ let insertionOrder = 0;
11
+ function addPending(event, channelMessageId) {
12
+ const shortId = String(nextShortId++);
13
+ pending.set(event.id, {
14
+ event,
15
+ notifiedAt: Date.now(),
16
+ channelMessageId,
17
+ shortId,
18
+ order: insertionOrder++,
19
+ });
20
+ return shortId;
21
+ }
22
+ function getPending(eventId) {
23
+ return pending.get(eventId);
24
+ }
25
+ function removePending(eventId) {
26
+ pending.delete(eventId);
27
+ }
28
+ const PENDING_TTL_MS = 5 * 60 * 1000; // 5 minutes
29
+ function listPending() {
30
+ // Expire old questions
31
+ const now = Date.now();
32
+ for (const [id, q] of pending) {
33
+ if (now - q.notifiedAt > PENDING_TTL_MS) {
34
+ pending.delete(id);
35
+ }
36
+ }
37
+ return Array.from(pending.values());
38
+ }
39
+ function resolveResponse(rawText) {
40
+ const all = listPending();
41
+ if (all.length === 0)
42
+ return null;
43
+ const text = rawText.trim();
44
+ // Try "#<id> response" format — id can be a shortId (number) or event UUID
45
+ const prefixed = text.match(/^#?([\w-]+)\s+(.+)$/s);
46
+ if (prefixed) {
47
+ const id = prefixed[1];
48
+ const response = prefixed[2].trim();
49
+ // Match by shortId (ntfy) or event ID (telegram)
50
+ const match = all.find(q => q.shortId === id || q.event.id === id);
51
+ if (match) {
52
+ return { question: match, response };
53
+ }
54
+ }
55
+ // Single pending → any text goes to it
56
+ if (all.length === 1) {
57
+ return { question: all[0], response: text };
58
+ }
59
+ // Multiple pending: route "allow"/"deny"/"yes"/"no" to most recent permission_prompt
60
+ const lower = text.toLowerCase();
61
+ if (['allow', 'deny', 'yes', 'no', 'y', 'n'].includes(lower)) {
62
+ const permissionQuestions = all
63
+ .filter(q => q.event.type === 'permission_prompt')
64
+ .sort((a, b) => b.order - a.order);
65
+ if (permissionQuestions.length > 0) {
66
+ return { question: permissionQuestions[0], response: text };
67
+ }
68
+ }
69
+ // Fallback: route to most recent pending
70
+ const mostRecent = all.sort((a, b) => b.order - a.order)[0];
71
+ return { question: mostRecent, response: text };
72
+ }
73
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/sessions/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { SessionInfo } from '../types.js';
2
+ export declare function registerSession(info: SessionInfo): void;
3
+ export declare function getSession(sessionId: string): SessionInfo | null;
4
+ export declare function listSessions(): SessionInfo[];
5
+ export declare function isProcessAlive(pid: number): boolean;
6
+ export declare function cleanDeadSessions(): number;
7
+ //# sourceMappingURL=tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/sessions/tracker.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAQvD;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAKhE;AAED,wBAAgB,YAAY,IAAI,WAAW,EAAE,CAO5C;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOnD;AAmBD,wBAAgB,iBAAiB,IAAI,MAAM,CAc1C"}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerSession = registerSession;
4
+ exports.getSession = getSession;
5
+ exports.listSessions = listSessions;
6
+ exports.isProcessAlive = isProcessAlive;
7
+ exports.cleanDeadSessions = cleanDeadSessions;
8
+ const node_fs_1 = require("node:fs");
9
+ const node_path_1 = require("node:path");
10
+ const node_child_process_1 = require("node:child_process");
11
+ const index_js_1 = require("../config/index.js");
12
+ const json_js_1 = require("../utils/json.js");
13
+ const validation_js_1 = require("../utils/validation.js");
14
+ function sessionsDir() {
15
+ return (0, node_path_1.join)((0, index_js_1.getDataDir)(), 'sessions');
16
+ }
17
+ function registerSession(info) {
18
+ if (!(0, validation_js_1.isValidSessionId)(info.sessionId)) {
19
+ console.debug('[tracker] Rejected invalid sessionId:', info.sessionId);
20
+ return;
21
+ }
22
+ (0, index_js_1.ensureDataDir)();
23
+ const file = (0, node_path_1.join)(sessionsDir(), `${info.sessionId}.json`);
24
+ (0, node_fs_1.writeFileSync)(file, JSON.stringify(info, null, 2) + '\n');
25
+ }
26
+ function getSession(sessionId) {
27
+ if (!(0, validation_js_1.isValidSessionId)(sessionId))
28
+ return null;
29
+ const file = (0, node_path_1.join)(sessionsDir(), `${sessionId}.json`);
30
+ if (!(0, node_fs_1.existsSync)(file))
31
+ return null;
32
+ return (0, json_js_1.safeJsonParse)((0, node_fs_1.readFileSync)(file, 'utf-8'), null);
33
+ }
34
+ function listSessions() {
35
+ const dir = sessionsDir();
36
+ if (!(0, node_fs_1.existsSync)(dir))
37
+ return [];
38
+ return (0, node_fs_1.readdirSync)(dir)
39
+ .filter(f => f.endsWith('.json'))
40
+ .map(f => (0, json_js_1.safeJsonParse)((0, node_fs_1.readFileSync)((0, node_path_1.join)(dir, f), 'utf-8'), null))
41
+ .filter((s) => s !== null);
42
+ }
43
+ function isProcessAlive(pid) {
44
+ try {
45
+ process.kill(pid, 0);
46
+ return true;
47
+ }
48
+ catch {
49
+ return false;
50
+ }
51
+ }
52
+ function isTmuxPaneAlive(pane) {
53
+ try {
54
+ (0, node_child_process_1.execFileSync)('tmux', ['has-session', '-t', pane], { timeout: 2000 });
55
+ return true;
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
61
+ function isSessionAlive(info) {
62
+ // If we have a tmux pane, check that instead of the PID
63
+ if (info.tmuxPane) {
64
+ return isTmuxPaneAlive(info.tmuxPane);
65
+ }
66
+ return isProcessAlive(info.pid);
67
+ }
68
+ function cleanDeadSessions() {
69
+ let cleaned = 0;
70
+ const dir = sessionsDir();
71
+ if (!(0, node_fs_1.existsSync)(dir))
72
+ return 0;
73
+ for (const file of (0, node_fs_1.readdirSync)(dir).filter(f => f.endsWith('.json'))) {
74
+ const path = (0, node_path_1.join)(dir, file);
75
+ const info = (0, json_js_1.safeJsonParse)((0, node_fs_1.readFileSync)(path, 'utf-8'), null);
76
+ if (!info || !isSessionAlive(info)) {
77
+ (0, node_fs_1.unlinkSync)(path);
78
+ cleaned++;
79
+ }
80
+ }
81
+ return cleaned;
82
+ }
83
+ //# sourceMappingURL=tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/sessions/tracker.ts"],"names":[],"mappings":"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"}