oh-my-codex 0.3.9 → 0.4.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 (184) hide show
  1. package/README.md +25 -0
  2. package/dist/cli/__tests__/doctor-team.test.js +58 -0
  3. package/dist/cli/__tests__/doctor-team.test.js.map +1 -1
  4. package/dist/cli/__tests__/index.test.js +9 -3
  5. package/dist/cli/__tests__/index.test.js.map +1 -1
  6. package/dist/cli/__tests__/lifecycle-notifications.test.d.ts +2 -0
  7. package/dist/cli/__tests__/lifecycle-notifications.test.d.ts.map +1 -0
  8. package/dist/cli/__tests__/lifecycle-notifications.test.js +48 -0
  9. package/dist/cli/__tests__/lifecycle-notifications.test.js.map +1 -0
  10. package/dist/cli/doctor.js +28 -0
  11. package/dist/cli/doctor.js.map +1 -1
  12. package/dist/cli/hooks.d.ts +4 -0
  13. package/dist/cli/hooks.d.ts.map +1 -0
  14. package/dist/cli/hooks.js +201 -0
  15. package/dist/cli/hooks.js.map +1 -0
  16. package/dist/cli/index.d.ts +1 -1
  17. package/dist/cli/index.d.ts.map +1 -1
  18. package/dist/cli/index.js +181 -2
  19. package/dist/cli/index.js.map +1 -1
  20. package/dist/config/__tests__/models.test.d.ts +2 -0
  21. package/dist/config/__tests__/models.test.d.ts.map +1 -0
  22. package/dist/config/__tests__/models.test.js +69 -0
  23. package/dist/config/__tests__/models.test.js.map +1 -0
  24. package/dist/config/models.d.ts +24 -0
  25. package/dist/config/models.d.ts.map +1 -0
  26. package/dist/config/models.js +53 -0
  27. package/dist/config/models.js.map +1 -0
  28. package/dist/hooks/__tests__/notify-hook-linked-sync.test.js +6 -0
  29. package/dist/hooks/__tests__/notify-hook-linked-sync.test.js.map +1 -1
  30. package/dist/hooks/__tests__/notify-hook-session-scope.test.js +6 -0
  31. package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
  32. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +224 -36
  33. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  34. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +4 -0
  35. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  36. package/dist/hooks/__tests__/tmux-hook-engine.test.js +1 -1
  37. package/dist/hooks/__tests__/tmux-hook-engine.test.js.map +1 -1
  38. package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.d.ts +2 -0
  39. package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.d.ts.map +1 -0
  40. package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.js +153 -0
  41. package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.js.map +1 -0
  42. package/dist/hooks/extensibility/dispatcher.d.ts +4 -0
  43. package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -0
  44. package/dist/hooks/extensibility/dispatcher.js +223 -0
  45. package/dist/hooks/extensibility/dispatcher.js.map +1 -0
  46. package/dist/hooks/extensibility/events.d.ts +18 -0
  47. package/dist/hooks/extensibility/events.d.ts.map +1 -0
  48. package/dist/hooks/extensibility/events.js +53 -0
  49. package/dist/hooks/extensibility/events.js.map +1 -0
  50. package/dist/hooks/extensibility/index.d.ts +6 -0
  51. package/dist/hooks/extensibility/index.d.ts.map +1 -0
  52. package/dist/hooks/extensibility/index.js +6 -0
  53. package/dist/hooks/extensibility/index.js.map +1 -0
  54. package/dist/hooks/extensibility/loader.d.ts +14 -0
  55. package/dist/hooks/extensibility/loader.d.ts.map +1 -0
  56. package/dist/hooks/extensibility/loader.js +102 -0
  57. package/dist/hooks/extensibility/loader.js.map +1 -0
  58. package/dist/hooks/extensibility/logging.d.ts +4 -0
  59. package/dist/hooks/extensibility/logging.d.ts.map +1 -0
  60. package/dist/hooks/extensibility/logging.js +16 -0
  61. package/dist/hooks/extensibility/logging.js.map +1 -0
  62. package/dist/hooks/extensibility/plugin-runner.d.ts +2 -0
  63. package/dist/hooks/extensibility/plugin-runner.d.ts.map +1 -0
  64. package/dist/hooks/extensibility/plugin-runner.js +69 -0
  65. package/dist/hooks/extensibility/plugin-runner.js.map +1 -0
  66. package/dist/hooks/extensibility/runtime.d.ts +3 -0
  67. package/dist/hooks/extensibility/runtime.d.ts.map +1 -0
  68. package/dist/hooks/extensibility/runtime.js +29 -0
  69. package/dist/hooks/extensibility/runtime.js.map +1 -0
  70. package/dist/hooks/extensibility/sdk.d.ts +11 -0
  71. package/dist/hooks/extensibility/sdk.d.ts.map +1 -0
  72. package/dist/hooks/extensibility/sdk.js +240 -0
  73. package/dist/hooks/extensibility/sdk.js.map +1 -0
  74. package/dist/hooks/extensibility/types.d.ts +122 -0
  75. package/dist/hooks/extensibility/types.d.ts.map +1 -0
  76. package/dist/hooks/extensibility/types.js +2 -0
  77. package/dist/hooks/extensibility/types.js.map +1 -0
  78. package/dist/mcp/__tests__/state-paths.test.js +21 -1
  79. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  80. package/dist/mcp/__tests__/state-server-team-tools.test.js +53 -1
  81. package/dist/mcp/__tests__/state-server-team-tools.test.js.map +1 -1
  82. package/dist/mcp/state-paths.d.ts +1 -0
  83. package/dist/mcp/state-paths.d.ts.map +1 -1
  84. package/dist/mcp/state-paths.js +34 -1
  85. package/dist/mcp/state-paths.js.map +1 -1
  86. package/dist/mcp/state-server.d.ts.map +1 -1
  87. package/dist/mcp/state-server.js +46 -11
  88. package/dist/mcp/state-server.js.map +1 -1
  89. package/dist/notifications/__tests__/config.test.d.ts +2 -0
  90. package/dist/notifications/__tests__/config.test.d.ts.map +1 -0
  91. package/dist/notifications/__tests__/config.test.js +186 -0
  92. package/dist/notifications/__tests__/config.test.js.map +1 -0
  93. package/dist/notifications/__tests__/dispatcher.test.d.ts +2 -0
  94. package/dist/notifications/__tests__/dispatcher.test.d.ts.map +1 -0
  95. package/dist/notifications/__tests__/dispatcher.test.js +202 -0
  96. package/dist/notifications/__tests__/dispatcher.test.js.map +1 -0
  97. package/dist/notifications/__tests__/formatter.test.d.ts +2 -0
  98. package/dist/notifications/__tests__/formatter.test.d.ts.map +1 -0
  99. package/dist/notifications/__tests__/formatter.test.js +103 -0
  100. package/dist/notifications/__tests__/formatter.test.js.map +1 -0
  101. package/dist/notifications/__tests__/notifier.test.d.ts +2 -0
  102. package/dist/notifications/__tests__/notifier.test.d.ts.map +1 -0
  103. package/dist/notifications/__tests__/notifier.test.js +104 -0
  104. package/dist/notifications/__tests__/notifier.test.js.map +1 -0
  105. package/dist/notifications/__tests__/profiles.test.d.ts +2 -0
  106. package/dist/notifications/__tests__/profiles.test.d.ts.map +1 -0
  107. package/dist/notifications/__tests__/profiles.test.js +404 -0
  108. package/dist/notifications/__tests__/profiles.test.js.map +1 -0
  109. package/dist/notifications/__tests__/reply-listener.test.d.ts +2 -0
  110. package/dist/notifications/__tests__/reply-listener.test.d.ts.map +1 -0
  111. package/dist/notifications/__tests__/reply-listener.test.js +58 -0
  112. package/dist/notifications/__tests__/reply-listener.test.js.map +1 -0
  113. package/dist/notifications/__tests__/session-registry.test.d.ts +2 -0
  114. package/dist/notifications/__tests__/session-registry.test.d.ts.map +1 -0
  115. package/dist/notifications/__tests__/session-registry.test.js +147 -0
  116. package/dist/notifications/__tests__/session-registry.test.js.map +1 -0
  117. package/dist/notifications/__tests__/tmux-detector.test.d.ts +2 -0
  118. package/dist/notifications/__tests__/tmux-detector.test.d.ts.map +1 -0
  119. package/dist/notifications/__tests__/tmux-detector.test.js +77 -0
  120. package/dist/notifications/__tests__/tmux-detector.test.js.map +1 -0
  121. package/dist/notifications/__tests__/tmux.test.d.ts +2 -0
  122. package/dist/notifications/__tests__/tmux.test.d.ts.map +1 -0
  123. package/dist/notifications/__tests__/tmux.test.js +90 -0
  124. package/dist/notifications/__tests__/tmux.test.js.map +1 -0
  125. package/dist/notifications/config.d.ts +44 -0
  126. package/dist/notifications/config.d.ts.map +1 -0
  127. package/dist/notifications/config.js +407 -0
  128. package/dist/notifications/config.js.map +1 -0
  129. package/dist/notifications/dispatcher.d.ts +15 -0
  130. package/dist/notifications/dispatcher.d.ts.map +1 -0
  131. package/dist/notifications/dispatcher.js +410 -0
  132. package/dist/notifications/dispatcher.js.map +1 -0
  133. package/dist/notifications/formatter.d.ts +14 -0
  134. package/dist/notifications/formatter.d.ts.map +1 -0
  135. package/dist/notifications/formatter.js +134 -0
  136. package/dist/notifications/formatter.js.map +1 -0
  137. package/dist/notifications/index.d.ts +32 -0
  138. package/dist/notifications/index.d.ts.map +1 -0
  139. package/dist/notifications/index.js +93 -0
  140. package/dist/notifications/index.js.map +1 -0
  141. package/dist/notifications/reply-listener.d.ts +47 -0
  142. package/dist/notifications/reply-listener.d.ts.map +1 -0
  143. package/dist/notifications/reply-listener.js +656 -0
  144. package/dist/notifications/reply-listener.js.map +1 -0
  145. package/dist/notifications/session-registry.d.ts +26 -0
  146. package/dist/notifications/session-registry.d.ts.map +1 -0
  147. package/dist/notifications/session-registry.js +275 -0
  148. package/dist/notifications/session-registry.js.map +1 -0
  149. package/dist/notifications/tmux-detector.d.ts +17 -0
  150. package/dist/notifications/tmux-detector.d.ts.map +1 -0
  151. package/dist/notifications/tmux-detector.js +82 -0
  152. package/dist/notifications/tmux-detector.js.map +1 -0
  153. package/dist/notifications/tmux.d.ts +28 -0
  154. package/dist/notifications/tmux.d.ts.map +1 -0
  155. package/dist/notifications/tmux.js +210 -0
  156. package/dist/notifications/tmux.js.map +1 -0
  157. package/dist/notifications/types.d.ts +181 -0
  158. package/dist/notifications/types.d.ts.map +1 -0
  159. package/dist/notifications/types.js +9 -0
  160. package/dist/notifications/types.js.map +1 -0
  161. package/dist/team/__tests__/runtime.test.js +54 -2
  162. package/dist/team/__tests__/runtime.test.js.map +1 -1
  163. package/dist/team/__tests__/state.test.js +30 -0
  164. package/dist/team/__tests__/state.test.js.map +1 -1
  165. package/dist/team/__tests__/worker-bootstrap.test.js +2 -0
  166. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  167. package/dist/team/runtime.d.ts +2 -2
  168. package/dist/team/runtime.d.ts.map +1 -1
  169. package/dist/team/runtime.js +19 -12
  170. package/dist/team/runtime.js.map +1 -1
  171. package/dist/team/state.d.ts +1 -1
  172. package/dist/team/state.d.ts.map +1 -1
  173. package/dist/team/state.js +5 -0
  174. package/dist/team/state.js.map +1 -1
  175. package/dist/team/tmux-session.d.ts.map +1 -1
  176. package/dist/team/tmux-session.js +59 -15
  177. package/dist/team/tmux-session.js.map +1 -1
  178. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  179. package/dist/team/worker-bootstrap.js +4 -0
  180. package/dist/team/worker-bootstrap.js.map +1 -1
  181. package/package.json +1 -1
  182. package/scripts/hook-derived-watcher.js +335 -0
  183. package/scripts/notify-hook.js +168 -7
  184. package/scripts/tmux-hook-engine.js +3 -2
@@ -0,0 +1,147 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { randomUUID } from 'crypto';
4
+ // The session-registry module uses hardcoded paths under ~/.omx/state/.
5
+ // We test the data shapes and logic patterns rather than filesystem integration
6
+ // to avoid polluting the real state directory.
7
+ function createMockMapping(overrides) {
8
+ return {
9
+ platform: 'discord-bot',
10
+ messageId: randomUUID(),
11
+ sessionId: randomUUID(),
12
+ tmuxPaneId: '%0',
13
+ tmuxSessionName: 'test-session',
14
+ event: 'session-idle',
15
+ createdAt: new Date().toISOString(),
16
+ projectPath: '/tmp/test',
17
+ ...overrides,
18
+ };
19
+ }
20
+ describe('SessionMapping shape', () => {
21
+ it('creates valid mapping with all required fields', () => {
22
+ const mapping = createMockMapping();
23
+ assert.ok(mapping.platform);
24
+ assert.ok(mapping.messageId);
25
+ assert.ok(mapping.sessionId);
26
+ assert.ok(mapping.tmuxPaneId);
27
+ assert.ok(mapping.tmuxSessionName !== undefined);
28
+ assert.ok(mapping.event);
29
+ assert.ok(mapping.createdAt);
30
+ });
31
+ it('supports discord-bot platform', () => {
32
+ const mapping = createMockMapping({ platform: 'discord-bot' });
33
+ assert.equal(mapping.platform, 'discord-bot');
34
+ });
35
+ it('supports telegram platform', () => {
36
+ const mapping = createMockMapping({ platform: 'telegram' });
37
+ assert.equal(mapping.platform, 'telegram');
38
+ });
39
+ it('serializes to valid JSON', () => {
40
+ const mapping = createMockMapping();
41
+ const json = JSON.stringify(mapping);
42
+ const parsed = JSON.parse(json);
43
+ assert.equal(parsed.platform, mapping.platform);
44
+ assert.equal(parsed.messageId, mapping.messageId);
45
+ assert.equal(parsed.sessionId, mapping.sessionId);
46
+ });
47
+ it('supports optional projectPath', () => {
48
+ const withPath = createMockMapping({ projectPath: '/test/path' });
49
+ assert.equal(withPath.projectPath, '/test/path');
50
+ const withoutPath = createMockMapping();
51
+ delete withoutPath.projectPath;
52
+ const json = JSON.stringify(withoutPath);
53
+ const parsed = JSON.parse(json);
54
+ assert.equal(parsed.projectPath, undefined);
55
+ });
56
+ });
57
+ describe('JSONL format', () => {
58
+ it('produces valid JSONL lines from mappings', () => {
59
+ const mappings = [
60
+ createMockMapping({ messageId: 'msg-1' }),
61
+ createMockMapping({ messageId: 'msg-2' }),
62
+ createMockMapping({ messageId: 'msg-3' }),
63
+ ];
64
+ const jsonl = mappings.map(m => JSON.stringify(m)).join('\n') + '\n';
65
+ const lines = jsonl.split('\n').filter(line => line.trim());
66
+ assert.equal(lines.length, 3);
67
+ for (const line of lines) {
68
+ const parsed = JSON.parse(line);
69
+ assert.ok(parsed.messageId);
70
+ assert.ok(parsed.platform);
71
+ }
72
+ });
73
+ it('can lookup mapping by messageId from parsed JSONL', () => {
74
+ const target = createMockMapping({ messageId: 'target-msg', platform: 'telegram' });
75
+ const mappings = [
76
+ createMockMapping({ messageId: 'other-1' }),
77
+ target,
78
+ createMockMapping({ messageId: 'other-2' }),
79
+ ];
80
+ const found = mappings.find(m => m.platform === 'telegram' && m.messageId === 'target-msg');
81
+ assert.ok(found);
82
+ assert.equal(found.messageId, 'target-msg');
83
+ assert.equal(found.platform, 'telegram');
84
+ });
85
+ it('can filter mappings by sessionId', () => {
86
+ const sessionId = 'session-to-remove';
87
+ const mappings = [
88
+ createMockMapping({ sessionId }),
89
+ createMockMapping({ sessionId: 'other-session' }),
90
+ createMockMapping({ sessionId }),
91
+ ];
92
+ const filtered = mappings.filter(m => m.sessionId !== sessionId);
93
+ assert.equal(filtered.length, 1);
94
+ assert.equal(filtered[0].sessionId, 'other-session');
95
+ });
96
+ it('can filter mappings by paneId', () => {
97
+ const mappings = [
98
+ createMockMapping({ tmuxPaneId: '%0' }),
99
+ createMockMapping({ tmuxPaneId: '%1' }),
100
+ createMockMapping({ tmuxPaneId: '%0' }),
101
+ ];
102
+ const filtered = mappings.filter(m => m.tmuxPaneId !== '%0');
103
+ assert.equal(filtered.length, 1);
104
+ assert.equal(filtered[0].tmuxPaneId, '%1');
105
+ });
106
+ it('can prune stale entries by age', () => {
107
+ const now = Date.now();
108
+ const maxAgeMs = 24 * 60 * 60 * 1000;
109
+ const mappings = [
110
+ createMockMapping({ createdAt: new Date(now - maxAgeMs - 1000).toISOString() }), // stale
111
+ createMockMapping({ createdAt: new Date(now - 1000).toISOString() }), // fresh
112
+ createMockMapping({ createdAt: new Date(now - maxAgeMs + 60000).toISOString() }), // just within
113
+ ];
114
+ const filtered = mappings.filter(m => {
115
+ const age = now - new Date(m.createdAt).getTime();
116
+ return age < maxAgeMs;
117
+ });
118
+ assert.equal(filtered.length, 2);
119
+ });
120
+ });
121
+ describe('session-registry module exports', () => {
122
+ it('exports registerMessage function', async () => {
123
+ const mod = await import('../session-registry.js');
124
+ assert.equal(typeof mod.registerMessage, 'function');
125
+ });
126
+ it('exports loadAllMappings function', async () => {
127
+ const mod = await import('../session-registry.js');
128
+ assert.equal(typeof mod.loadAllMappings, 'function');
129
+ });
130
+ it('exports lookupByMessageId function', async () => {
131
+ const mod = await import('../session-registry.js');
132
+ assert.equal(typeof mod.lookupByMessageId, 'function');
133
+ });
134
+ it('exports removeSession function', async () => {
135
+ const mod = await import('../session-registry.js');
136
+ assert.equal(typeof mod.removeSession, 'function');
137
+ });
138
+ it('exports removeMessagesByPane function', async () => {
139
+ const mod = await import('../session-registry.js');
140
+ assert.equal(typeof mod.removeMessagesByPane, 'function');
141
+ });
142
+ it('exports pruneStale function', async () => {
143
+ const mod = await import('../session-registry.js');
144
+ assert.equal(typeof mod.pruneStale, 'function');
145
+ });
146
+ });
147
+ //# sourceMappingURL=session-registry.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-registry.test.js","sourceRoot":"","sources":["../../../src/notifications/__tests__/session-registry.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tmux-detector.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux-detector.test.d.ts","sourceRoot":"","sources":["../../../src/notifications/__tests__/tmux-detector.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { analyzePaneContent } from '../tmux-detector.js';
4
+ describe('analyzePaneContent', () => {
5
+ it('returns zero confidence for empty content', () => {
6
+ const result = analyzePaneContent('');
7
+ assert.equal(result.hasCodex, false);
8
+ assert.equal(result.hasRateLimitMessage, false);
9
+ assert.equal(result.isBlocked, false);
10
+ assert.equal(result.confidence, 0);
11
+ });
12
+ it('detects "codex" keyword', () => {
13
+ const result = analyzePaneContent('Running Codex agent...');
14
+ assert.equal(result.hasCodex, true);
15
+ assert.ok(result.confidence >= 0.5);
16
+ });
17
+ it('detects "omx" keyword', () => {
18
+ const result = analyzePaneContent('omx session started');
19
+ assert.equal(result.hasCodex, true);
20
+ });
21
+ it('detects "oh-my-codex" keyword', () => {
22
+ const result = analyzePaneContent('oh-my-codex v1.0');
23
+ assert.equal(result.hasCodex, true);
24
+ });
25
+ it('detects "openai" keyword', () => {
26
+ const result = analyzePaneContent('openai api call');
27
+ assert.equal(result.hasCodex, true);
28
+ });
29
+ it('is case insensitive', () => {
30
+ const result = analyzePaneContent('CODEX RUNNING');
31
+ assert.equal(result.hasCodex, true);
32
+ });
33
+ it('detects rate limit messages', () => {
34
+ const result = analyzePaneContent('Error: rate limit exceeded');
35
+ assert.equal(result.hasRateLimitMessage, true);
36
+ });
37
+ it('detects rate-limit with hyphen', () => {
38
+ const result = analyzePaneContent('rate-limit error');
39
+ assert.equal(result.hasRateLimitMessage, true);
40
+ });
41
+ it('detects 429 status code', () => {
42
+ const result = analyzePaneContent('HTTP 429 Too Many Requests');
43
+ assert.equal(result.hasRateLimitMessage, true);
44
+ });
45
+ it('detects blocked/waiting state', () => {
46
+ const result = analyzePaneContent('Waiting for user input...');
47
+ assert.equal(result.isBlocked, true);
48
+ });
49
+ it('detects paused state', () => {
50
+ const result = analyzePaneContent('Agent paused');
51
+ assert.equal(result.isBlocked, true);
52
+ });
53
+ it('adds confidence for prompt characters', () => {
54
+ const result = analyzePaneContent('$ some command\n> next line');
55
+ assert.ok(result.confidence >= 0.2);
56
+ });
57
+ it('adds confidence for agent/task keywords', () => {
58
+ const result = analyzePaneContent('agent running task 1');
59
+ assert.ok(result.confidence >= 0.1);
60
+ });
61
+ it('gives high confidence for codex content with prompt chars', () => {
62
+ const result = analyzePaneContent('Codex > Running agent task...');
63
+ assert.equal(result.hasCodex, true);
64
+ // codex=0.5, >=0.1, agent/task=0.1, non-empty=0.1 = 0.8
65
+ assert.ok(result.confidence >= 0.7, `Expected confidence >= 0.7, got ${result.confidence}`);
66
+ });
67
+ it('caps confidence at 1.0', () => {
68
+ const result = analyzePaneContent('Codex $ > agent task running omx');
69
+ assert.ok(result.confidence <= 1.0);
70
+ });
71
+ it('gives some confidence for non-empty non-codex content', () => {
72
+ const result = analyzePaneContent('some random text here');
73
+ assert.equal(result.hasCodex, false);
74
+ assert.ok(result.confidence > 0);
75
+ });
76
+ });
77
+ //# sourceMappingURL=tmux-detector.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux-detector.test.js","sourceRoot":"","sources":["../../../src/notifications/__tests__/tmux-detector.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tmux.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux.test.d.ts","sourceRoot":"","sources":["../../../src/notifications/__tests__/tmux.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,90 @@
1
+ import { describe, it, afterEach } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { getCurrentTmuxSession, getCurrentTmuxPaneId, formatTmuxInfo, getTeamTmuxSessions, } from '../tmux.js';
4
+ describe('getCurrentTmuxSession', () => {
5
+ const originalTmux = process.env.TMUX;
6
+ afterEach(() => {
7
+ if (originalTmux !== undefined) {
8
+ process.env.TMUX = originalTmux;
9
+ }
10
+ else {
11
+ delete process.env.TMUX;
12
+ }
13
+ });
14
+ it('handles missing TMUX env without throwing', () => {
15
+ delete process.env.TMUX;
16
+ const value = getCurrentTmuxSession();
17
+ assert.ok(value === null || typeof value === 'string');
18
+ });
19
+ });
20
+ describe('getCurrentTmuxPaneId', () => {
21
+ const originalTmux = process.env.TMUX;
22
+ const originalPane = process.env.TMUX_PANE;
23
+ afterEach(() => {
24
+ if (originalTmux !== undefined) {
25
+ process.env.TMUX = originalTmux;
26
+ }
27
+ else {
28
+ delete process.env.TMUX;
29
+ }
30
+ if (originalPane !== undefined) {
31
+ process.env.TMUX_PANE = originalPane;
32
+ }
33
+ else {
34
+ delete process.env.TMUX_PANE;
35
+ }
36
+ });
37
+ it('handles missing TMUX env without throwing', () => {
38
+ delete process.env.TMUX;
39
+ delete process.env.TMUX_PANE;
40
+ const value = getCurrentTmuxPaneId();
41
+ assert.ok(value === null || /^%\d+$/.test(value));
42
+ });
43
+ it('returns TMUX_PANE when valid format', () => {
44
+ process.env.TMUX = '/tmp/tmux-1000/default,12345,0';
45
+ process.env.TMUX_PANE = '%0';
46
+ assert.equal(getCurrentTmuxPaneId(), '%0');
47
+ });
48
+ it('returns TMUX_PANE for multi-digit pane id', () => {
49
+ process.env.TMUX = '/tmp/tmux-1000/default,12345,0';
50
+ process.env.TMUX_PANE = '%42';
51
+ assert.equal(getCurrentTmuxPaneId(), '%42');
52
+ });
53
+ it('ignores invalid TMUX_PANE format', () => {
54
+ process.env.TMUX = '/tmp/tmux-1000/default,12345,0';
55
+ process.env.TMUX_PANE = 'invalid';
56
+ // Falls back to tmux command, which may or may not work
57
+ const result = getCurrentTmuxPaneId();
58
+ assert.ok(result === null || /^%\d+$/.test(result));
59
+ });
60
+ });
61
+ describe('formatTmuxInfo', () => {
62
+ const originalTmux = process.env.TMUX;
63
+ afterEach(() => {
64
+ if (originalTmux !== undefined) {
65
+ process.env.TMUX = originalTmux;
66
+ }
67
+ else {
68
+ delete process.env.TMUX;
69
+ }
70
+ });
71
+ it('handles missing TMUX env without throwing', () => {
72
+ delete process.env.TMUX;
73
+ const value = formatTmuxInfo();
74
+ assert.ok(value === null || value.startsWith('tmux: '));
75
+ });
76
+ });
77
+ describe('getTeamTmuxSessions', () => {
78
+ it('returns empty array for empty team name', () => {
79
+ assert.deepEqual(getTeamTmuxSessions(''), []);
80
+ });
81
+ it('returns empty array for special-character-only team name', () => {
82
+ assert.deepEqual(getTeamTmuxSessions('!@#$'), []);
83
+ });
84
+ it('sanitizes team name (strips non-alphanumeric except hyphens)', () => {
85
+ // Should not throw even with weird input
86
+ const result = getTeamTmuxSessions('test<script>');
87
+ assert.ok(Array.isArray(result));
88
+ });
89
+ });
90
+ //# sourceMappingURL=tmux.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux.test.js","sourceRoot":"","sources":["../../../src/notifications/__tests__/tmux.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Notification Configuration Reader
3
+ *
4
+ * Reads notification config from .omx-config.json and provides
5
+ * backward compatibility with the old stopHookCallbacks format.
6
+ */
7
+ import type { FullNotificationConfig, NotificationsBlock, NotificationEvent, NotificationPlatform } from "./types.js";
8
+ export declare function validateMention(raw: string | undefined): string | undefined;
9
+ export declare function parseMentionAllowedMentions(mention: string | undefined): {
10
+ users?: string[];
11
+ roles?: string[];
12
+ };
13
+ export declare function buildConfigFromEnv(): FullNotificationConfig | null;
14
+ /**
15
+ * Resolve a named profile from the notifications block.
16
+ *
17
+ * Priority:
18
+ * 1. Explicit `profileName` argument
19
+ * 2. OMX_NOTIFY_PROFILE environment variable
20
+ * 3. `defaultProfile` field in config
21
+ * 4. null (no profile selected → fall back to flat config)
22
+ */
23
+ export declare function resolveProfileConfig(notifications: NotificationsBlock, profileName?: string): FullNotificationConfig | null;
24
+ /**
25
+ * List available profile names from the config file.
26
+ */
27
+ export declare function listProfiles(): string[];
28
+ /**
29
+ * Get the active profile name based on resolution priority.
30
+ * Returns null if no profile is active (flat config mode).
31
+ */
32
+ export declare function getActiveProfileName(): string | null;
33
+ export declare function getNotificationConfig(profileName?: string): FullNotificationConfig | null;
34
+ export declare function isEventEnabled(config: FullNotificationConfig, event: NotificationEvent): boolean;
35
+ export declare function getEnabledPlatforms(config: FullNotificationConfig, event: NotificationEvent): NotificationPlatform[];
36
+ export declare function getReplyListenerPlatformConfig(config: FullNotificationConfig | null): {
37
+ telegramBotToken?: string;
38
+ telegramChatId?: string;
39
+ discordBotToken?: string;
40
+ discordChannelId?: string;
41
+ discordMention?: string;
42
+ };
43
+ export declare function getReplyConfig(): import("./types.js").ReplyConfig | null;
44
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/notifications/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EACV,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EAKrB,MAAM,YAAY,CAAC;AAuDpB,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAO3E;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B;IAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAOxC;AAED,wBAAgB,kBAAkB,IAAI,sBAAsB,GAAG,IAAI,CAyDlE;AAmDD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,kBAAkB,EACjC,WAAW,CAAC,EAAE,MAAM,GACnB,sBAAsB,GAAG,IAAI,CAwB/B;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAMvC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,IAAI,CAWpD;AAED,wBAAgB,qBAAqB,CACnC,WAAW,CAAC,EAAE,MAAM,GACnB,sBAAsB,GAAG,IAAI,CAkD/B;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,sBAAsB,EAC9B,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAkCT;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,sBAAsB,EAC9B,KAAK,EAAE,iBAAiB,GACvB,oBAAoB,EAAE,CAwCxB;AAqCD,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,sBAAsB,GAAG,IAAI,GACpC;IACD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAwBA;AAuBD,wBAAgB,cAAc,IAAI,OAAO,YAAY,EAAE,WAAW,GAAG,IAAI,CAwCxE"}