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,186 @@
1
+ import { describe, it, beforeEach, afterEach } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { validateMention, parseMentionAllowedMentions, buildConfigFromEnv, } from '../config.js';
4
+ const ENV_KEYS = [
5
+ 'OMX_DISCORD_NOTIFIER_BOT_TOKEN',
6
+ 'OMX_DISCORD_NOTIFIER_CHANNEL',
7
+ 'OMX_DISCORD_WEBHOOK_URL',
8
+ 'OMX_DISCORD_MENTION',
9
+ 'OMX_TELEGRAM_BOT_TOKEN',
10
+ 'OMX_TELEGRAM_NOTIFIER_BOT_TOKEN',
11
+ 'OMX_TELEGRAM_CHAT_ID',
12
+ 'OMX_TELEGRAM_NOTIFIER_CHAT_ID',
13
+ 'OMX_TELEGRAM_NOTIFIER_UID',
14
+ 'OMX_SLACK_WEBHOOK_URL',
15
+ ];
16
+ function clearEnvVars() {
17
+ for (const key of ENV_KEYS) {
18
+ delete process.env[key];
19
+ }
20
+ }
21
+ describe('validateMention', () => {
22
+ it('accepts valid user mention', () => {
23
+ assert.equal(validateMention('<@12345678901234567>'), '<@12345678901234567>');
24
+ });
25
+ it('accepts valid user mention with exclamation (nickname)', () => {
26
+ assert.equal(validateMention('<@!12345678901234567>'), '<@!12345678901234567>');
27
+ });
28
+ it('accepts valid role mention', () => {
29
+ assert.equal(validateMention('<@&12345678901234567>'), '<@&12345678901234567>');
30
+ });
31
+ it('accepts 20-digit IDs', () => {
32
+ assert.equal(validateMention('<@12345678901234567890>'), '<@12345678901234567890>');
33
+ });
34
+ it('rejects @everyone', () => {
35
+ assert.equal(validateMention('@everyone'), undefined);
36
+ });
37
+ it('rejects @here', () => {
38
+ assert.equal(validateMention('@here'), undefined);
39
+ });
40
+ it('rejects arbitrary text', () => {
41
+ assert.equal(validateMention('hello world'), undefined);
42
+ });
43
+ it('rejects mention with trailing text', () => {
44
+ assert.equal(validateMention('<@123456789012345678> extra'), undefined);
45
+ });
46
+ it('rejects too-short ID', () => {
47
+ assert.equal(validateMention('<@1234>'), undefined);
48
+ });
49
+ it('returns undefined for empty string', () => {
50
+ assert.equal(validateMention(''), undefined);
51
+ });
52
+ it('returns undefined for undefined', () => {
53
+ assert.equal(validateMention(undefined), undefined);
54
+ });
55
+ it('trims whitespace and validates', () => {
56
+ assert.equal(validateMention(' <@12345678901234567> '), '<@12345678901234567>');
57
+ });
58
+ it('rejects whitespace-only string', () => {
59
+ assert.equal(validateMention(' '), undefined);
60
+ });
61
+ });
62
+ describe('parseMentionAllowedMentions', () => {
63
+ it('parses user mention', () => {
64
+ assert.deepEqual(parseMentionAllowedMentions('<@12345678901234567>'), { users: ['12345678901234567'] });
65
+ });
66
+ it('parses nickname user mention', () => {
67
+ assert.deepEqual(parseMentionAllowedMentions('<@!12345678901234567>'), { users: ['12345678901234567'] });
68
+ });
69
+ it('parses role mention', () => {
70
+ assert.deepEqual(parseMentionAllowedMentions('<@&12345678901234567>'), { roles: ['12345678901234567'] });
71
+ });
72
+ it('returns empty for undefined', () => {
73
+ assert.deepEqual(parseMentionAllowedMentions(undefined), {});
74
+ });
75
+ it('returns empty for invalid mention', () => {
76
+ assert.deepEqual(parseMentionAllowedMentions('@everyone'), {});
77
+ });
78
+ });
79
+ describe('buildConfigFromEnv', () => {
80
+ beforeEach(() => {
81
+ clearEnvVars();
82
+ });
83
+ afterEach(() => {
84
+ clearEnvVars();
85
+ });
86
+ it('returns null when no env vars set', () => {
87
+ assert.equal(buildConfigFromEnv(), null);
88
+ });
89
+ it('builds discord-bot config from env vars', () => {
90
+ process.env.OMX_DISCORD_NOTIFIER_BOT_TOKEN = 'test-token';
91
+ process.env.OMX_DISCORD_NOTIFIER_CHANNEL = '123456';
92
+ const config = buildConfigFromEnv();
93
+ assert.ok(config);
94
+ assert.equal(config.enabled, true);
95
+ assert.deepEqual(config['discord-bot'], {
96
+ enabled: true,
97
+ botToken: 'test-token',
98
+ channelId: '123456',
99
+ mention: undefined,
100
+ });
101
+ });
102
+ it('includes validated mention in discord-bot config', () => {
103
+ process.env.OMX_DISCORD_NOTIFIER_BOT_TOKEN = 'test-token';
104
+ process.env.OMX_DISCORD_NOTIFIER_CHANNEL = '123456';
105
+ process.env.OMX_DISCORD_MENTION = '<@12345678901234567>';
106
+ const config = buildConfigFromEnv();
107
+ assert.ok(config);
108
+ assert.equal(config['discord-bot'].mention, '<@12345678901234567>');
109
+ });
110
+ it('rejects invalid mention in env var', () => {
111
+ process.env.OMX_DISCORD_NOTIFIER_BOT_TOKEN = 'test-token';
112
+ process.env.OMX_DISCORD_NOTIFIER_CHANNEL = '123456';
113
+ process.env.OMX_DISCORD_MENTION = '@everyone';
114
+ const config = buildConfigFromEnv();
115
+ assert.ok(config);
116
+ assert.equal(config['discord-bot'].mention, undefined);
117
+ });
118
+ it('builds discord webhook config from env var', () => {
119
+ process.env.OMX_DISCORD_WEBHOOK_URL = 'https://discord.com/api/webhooks/test';
120
+ const config = buildConfigFromEnv();
121
+ assert.ok(config);
122
+ assert.deepEqual(config.discord, {
123
+ enabled: true,
124
+ webhookUrl: 'https://discord.com/api/webhooks/test',
125
+ mention: undefined,
126
+ });
127
+ });
128
+ it('builds telegram config from env vars', () => {
129
+ process.env.OMX_TELEGRAM_BOT_TOKEN = '123:abc';
130
+ process.env.OMX_TELEGRAM_CHAT_ID = '999';
131
+ const config = buildConfigFromEnv();
132
+ assert.ok(config);
133
+ assert.deepEqual(config.telegram, {
134
+ enabled: true,
135
+ botToken: '123:abc',
136
+ chatId: '999',
137
+ });
138
+ });
139
+ it('builds slack config from env var', () => {
140
+ process.env.OMX_SLACK_WEBHOOK_URL = 'https://hooks.slack.com/services/test';
141
+ const config = buildConfigFromEnv();
142
+ assert.ok(config);
143
+ assert.deepEqual(config.slack, {
144
+ enabled: true,
145
+ webhookUrl: 'https://hooks.slack.com/services/test',
146
+ });
147
+ });
148
+ it('uses OMX_TELEGRAM_NOTIFIER_BOT_TOKEN as fallback', () => {
149
+ process.env.OMX_TELEGRAM_NOTIFIER_BOT_TOKEN = '123:fallback';
150
+ process.env.OMX_TELEGRAM_CHAT_ID = '999';
151
+ const config = buildConfigFromEnv();
152
+ assert.ok(config);
153
+ assert.equal(config.telegram.botToken, '123:fallback');
154
+ });
155
+ it('uses OMX_TELEGRAM_NOTIFIER_UID as fallback for chat ID', () => {
156
+ process.env.OMX_TELEGRAM_BOT_TOKEN = '123:abc';
157
+ process.env.OMX_TELEGRAM_NOTIFIER_UID = 'uid-999';
158
+ const config = buildConfigFromEnv();
159
+ assert.ok(config);
160
+ assert.equal(config.telegram.chatId, 'uid-999');
161
+ });
162
+ it('builds config with multiple platforms from env', () => {
163
+ process.env.OMX_DISCORD_NOTIFIER_BOT_TOKEN = 'bot-token';
164
+ process.env.OMX_DISCORD_NOTIFIER_CHANNEL = 'channel-123';
165
+ process.env.OMX_TELEGRAM_BOT_TOKEN = '456:tg';
166
+ process.env.OMX_TELEGRAM_CHAT_ID = 'chat-789';
167
+ process.env.OMX_SLACK_WEBHOOK_URL = 'https://hooks.slack.com/services/test';
168
+ const config = buildConfigFromEnv();
169
+ assert.ok(config);
170
+ assert.equal(config.enabled, true);
171
+ assert.equal(config['discord-bot'].enabled, true);
172
+ assert.equal(config.telegram.enabled, true);
173
+ assert.equal(config.slack.enabled, true);
174
+ });
175
+ it('mention from env is shared across discord-bot and discord webhook', () => {
176
+ process.env.OMX_DISCORD_NOTIFIER_BOT_TOKEN = 'bot-token';
177
+ process.env.OMX_DISCORD_NOTIFIER_CHANNEL = 'channel-123';
178
+ process.env.OMX_DISCORD_WEBHOOK_URL = 'https://discord.com/api/webhooks/test';
179
+ process.env.OMX_DISCORD_MENTION = '<@12345678901234567>';
180
+ const config = buildConfigFromEnv();
181
+ assert.ok(config);
182
+ assert.equal(config['discord-bot'].mention, '<@12345678901234567>');
183
+ assert.equal(config.discord.mention, '<@12345678901234567>');
184
+ });
185
+ });
186
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../../src/notifications/__tests__/config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dispatcher.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.test.d.ts","sourceRoot":"","sources":["../../../src/notifications/__tests__/dispatcher.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,202 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { sendDiscord, sendDiscordBot, sendSlack, sendWebhook, dispatchNotifications, } from '../dispatcher.js';
4
+ const basePayload = {
5
+ event: 'session-idle',
6
+ sessionId: 'test-session-123',
7
+ message: 'Test notification message',
8
+ timestamp: new Date('2025-01-15T12:00:00Z').toISOString(),
9
+ projectPath: '/home/user/project',
10
+ projectName: 'project',
11
+ };
12
+ // ---------------------------------------------------------------------------
13
+ // sendDiscord
14
+ // ---------------------------------------------------------------------------
15
+ describe('sendDiscord', () => {
16
+ it('returns error when not enabled', async () => {
17
+ const config = { enabled: false, webhookUrl: '' };
18
+ const result = await sendDiscord(config, basePayload);
19
+ assert.equal(result.success, false);
20
+ assert.equal(result.platform, 'discord');
21
+ assert.ok(result.error?.includes('Not configured'));
22
+ });
23
+ it('returns error when webhookUrl is empty', async () => {
24
+ const config = { enabled: true, webhookUrl: '' };
25
+ const result = await sendDiscord(config, basePayload);
26
+ assert.equal(result.success, false);
27
+ });
28
+ it('rejects invalid webhook URL (non-discord host)', async () => {
29
+ const config = {
30
+ enabled: true,
31
+ webhookUrl: 'https://evil.com/webhook',
32
+ };
33
+ const result = await sendDiscord(config, basePayload);
34
+ assert.equal(result.success, false);
35
+ assert.equal(result.error, 'Invalid webhook URL');
36
+ });
37
+ it('rejects http:// webhook URL', async () => {
38
+ const config = {
39
+ enabled: true,
40
+ webhookUrl: 'http://discord.com/api/webhooks/123/abc',
41
+ };
42
+ const result = await sendDiscord(config, basePayload);
43
+ assert.equal(result.success, false);
44
+ assert.equal(result.error, 'Invalid webhook URL');
45
+ });
46
+ it('rejects malformed URL', async () => {
47
+ const config = {
48
+ enabled: true,
49
+ webhookUrl: 'not-a-url',
50
+ };
51
+ const result = await sendDiscord(config, basePayload);
52
+ assert.equal(result.success, false);
53
+ assert.equal(result.error, 'Invalid webhook URL');
54
+ });
55
+ });
56
+ // ---------------------------------------------------------------------------
57
+ // sendDiscordBot
58
+ // ---------------------------------------------------------------------------
59
+ describe('sendDiscordBot', () => {
60
+ it('returns error when not enabled', async () => {
61
+ const config = { enabled: false };
62
+ const result = await sendDiscordBot(config, basePayload);
63
+ assert.equal(result.success, false);
64
+ assert.equal(result.platform, 'discord-bot');
65
+ assert.ok(result.error?.includes('Not enabled'));
66
+ });
67
+ it('returns error when missing botToken', async () => {
68
+ const config = {
69
+ enabled: true,
70
+ channelId: '123456',
71
+ };
72
+ const result = await sendDiscordBot(config, basePayload);
73
+ assert.equal(result.success, false);
74
+ assert.ok(result.error?.includes('Missing botToken or channelId'));
75
+ });
76
+ it('returns error when missing channelId', async () => {
77
+ const config = {
78
+ enabled: true,
79
+ botToken: 'token',
80
+ };
81
+ const result = await sendDiscordBot(config, basePayload);
82
+ assert.equal(result.success, false);
83
+ assert.ok(result.error?.includes('Missing botToken or channelId'));
84
+ });
85
+ });
86
+ // ---------------------------------------------------------------------------
87
+ // sendSlack
88
+ // ---------------------------------------------------------------------------
89
+ describe('sendSlack', () => {
90
+ it('returns error when not enabled', async () => {
91
+ const config = { enabled: false, webhookUrl: '' };
92
+ const result = await sendSlack(config, basePayload);
93
+ assert.equal(result.success, false);
94
+ assert.equal(result.platform, 'slack');
95
+ });
96
+ it('rejects invalid slack webhook URL', async () => {
97
+ const config = {
98
+ enabled: true,
99
+ webhookUrl: 'https://evil.com/services/hook',
100
+ };
101
+ const result = await sendSlack(config, basePayload);
102
+ assert.equal(result.success, false);
103
+ assert.equal(result.error, 'Invalid webhook URL');
104
+ });
105
+ it('rejects http:// slack webhook URL', async () => {
106
+ const config = {
107
+ enabled: true,
108
+ webhookUrl: 'http://hooks.slack.com/services/test',
109
+ };
110
+ const result = await sendSlack(config, basePayload);
111
+ assert.equal(result.success, false);
112
+ assert.equal(result.error, 'Invalid webhook URL');
113
+ });
114
+ });
115
+ // ---------------------------------------------------------------------------
116
+ // sendWebhook
117
+ // ---------------------------------------------------------------------------
118
+ describe('sendWebhook', () => {
119
+ it('returns error when not enabled', async () => {
120
+ const config = { enabled: false, url: '' };
121
+ const result = await sendWebhook(config, basePayload);
122
+ assert.equal(result.success, false);
123
+ assert.equal(result.platform, 'webhook');
124
+ });
125
+ it('rejects http:// URL (requires HTTPS)', async () => {
126
+ const config = {
127
+ enabled: true,
128
+ url: 'http://example.com/hook',
129
+ };
130
+ const result = await sendWebhook(config, basePayload);
131
+ assert.equal(result.success, false);
132
+ assert.equal(result.error, 'Invalid URL (HTTPS required)');
133
+ });
134
+ it('rejects malformed URL', async () => {
135
+ const config = {
136
+ enabled: true,
137
+ url: 'not-a-url',
138
+ };
139
+ const result = await sendWebhook(config, basePayload);
140
+ assert.equal(result.success, false);
141
+ assert.equal(result.error, 'Invalid URL (HTTPS required)');
142
+ });
143
+ });
144
+ // ---------------------------------------------------------------------------
145
+ // dispatchNotifications
146
+ // ---------------------------------------------------------------------------
147
+ describe('dispatchNotifications', () => {
148
+ it('returns empty results when no platforms enabled', async () => {
149
+ const config = { enabled: true };
150
+ const result = await dispatchNotifications(config, 'session-idle', basePayload);
151
+ assert.equal(result.event, 'session-idle');
152
+ assert.equal(result.results.length, 0);
153
+ assert.equal(result.anySuccess, false);
154
+ });
155
+ it('returns empty when config disabled', async () => {
156
+ const config = {
157
+ enabled: true,
158
+ discord: { enabled: false, webhookUrl: '' },
159
+ };
160
+ const result = await dispatchNotifications(config, 'session-end', basePayload);
161
+ assert.equal(result.results.length, 0);
162
+ assert.equal(result.anySuccess, false);
163
+ });
164
+ it('dispatches to enabled platforms and collects results', async () => {
165
+ const config = {
166
+ enabled: true,
167
+ discord: { enabled: true, webhookUrl: 'not-valid' },
168
+ slack: { enabled: true, webhookUrl: 'not-valid' },
169
+ };
170
+ const result = await dispatchNotifications(config, 'session-end', basePayload);
171
+ assert.ok(result.results.length > 0);
172
+ // Both should fail (invalid URLs)
173
+ assert.equal(result.anySuccess, false);
174
+ });
175
+ it('uses event-level platform config when present', async () => {
176
+ const config = {
177
+ enabled: true,
178
+ events: {
179
+ 'session-end': {
180
+ enabled: true,
181
+ discord: { enabled: true, webhookUrl: 'invalid-url' },
182
+ },
183
+ },
184
+ };
185
+ const result = await dispatchNotifications(config, 'session-end', basePayload);
186
+ assert.ok(result.results.length > 0);
187
+ assert.equal(result.results[0].platform, 'discord');
188
+ });
189
+ it('falls back to top-level config when event has no platform override', async () => {
190
+ const config = {
191
+ enabled: true,
192
+ discord: { enabled: true, webhookUrl: 'invalid-url' },
193
+ events: {
194
+ 'session-start': { enabled: true },
195
+ },
196
+ };
197
+ const result = await dispatchNotifications(config, 'session-start', basePayload);
198
+ assert.ok(result.results.length > 0);
199
+ assert.equal(result.results[0].platform, 'discord');
200
+ });
201
+ });
202
+ //# sourceMappingURL=dispatcher.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher.test.js","sourceRoot":"","sources":["../../../src/notifications/__tests__/dispatcher.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=formatter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.test.d.ts","sourceRoot":"","sources":["../../../src/notifications/__tests__/formatter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,103 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { formatSessionIdle, formatSessionStart, formatSessionEnd, formatSessionStop, formatAskUserQuestion, formatNotification, } from '../formatter.js';
4
+ const basePayload = {
5
+ event: 'session-idle',
6
+ sessionId: 'test-session-123',
7
+ message: '',
8
+ timestamp: new Date('2025-01-15T12:00:00Z').toISOString(),
9
+ projectPath: '/home/user/my-project',
10
+ projectName: 'my-project',
11
+ };
12
+ describe('formatSessionIdle', () => {
13
+ it('should include idle header and waiting message', () => {
14
+ const result = formatSessionIdle(basePayload);
15
+ assert.ok(result.includes('# Session Idle'));
16
+ assert.ok(result.includes('Codex has finished and is waiting for input.'));
17
+ });
18
+ it('should include project info in footer', () => {
19
+ const result = formatSessionIdle(basePayload);
20
+ assert.ok(result.includes('`my-project`'));
21
+ });
22
+ it('should include reason when provided', () => {
23
+ const result = formatSessionIdle({ ...basePayload, reason: 'task_complete' });
24
+ assert.ok(result.includes('**Reason:** task_complete'));
25
+ });
26
+ it('should include modes when provided', () => {
27
+ const result = formatSessionIdle({ ...basePayload, modesUsed: ['ultrawork', 'ralph'] });
28
+ assert.ok(result.includes('**Modes:** ultrawork, ralph'));
29
+ });
30
+ it('should include tmux session in footer when available', () => {
31
+ const result = formatSessionIdle({ ...basePayload, tmuxSession: 'dev-session' });
32
+ assert.ok(result.includes('`dev-session`'));
33
+ });
34
+ });
35
+ describe('formatSessionStart', () => {
36
+ it('should include start header and session info', () => {
37
+ const result = formatSessionStart({ ...basePayload, event: 'session-start' });
38
+ assert.ok(result.includes('# Session Started'));
39
+ assert.ok(result.includes('`test-session-123`'));
40
+ assert.ok(result.includes('`my-project`'));
41
+ });
42
+ it('should include tmux session when available', () => {
43
+ const result = formatSessionStart({ ...basePayload, event: 'session-start', tmuxSession: 'main' });
44
+ assert.ok(result.includes('`main`'));
45
+ });
46
+ });
47
+ describe('formatSessionEnd', () => {
48
+ it('should include end header and duration', () => {
49
+ const result = formatSessionEnd({ ...basePayload, event: 'session-end', durationMs: 125000 });
50
+ assert.ok(result.includes('# Session Ended'));
51
+ assert.ok(result.includes('2m 5s'));
52
+ });
53
+ it('should include agents count', () => {
54
+ const result = formatSessionEnd({ ...basePayload, event: 'session-end', agentsSpawned: 5, agentsCompleted: 3 });
55
+ assert.ok(result.includes('3/5 completed'));
56
+ });
57
+ it('should include modes and summary', () => {
58
+ const result = formatSessionEnd({
59
+ ...basePayload,
60
+ event: 'session-end',
61
+ modesUsed: ['ralph'],
62
+ contextSummary: 'Fixed auth bug',
63
+ });
64
+ assert.ok(result.includes('**Modes:** ralph'));
65
+ assert.ok(result.includes('**Summary:** Fixed auth bug'));
66
+ });
67
+ });
68
+ describe('formatSessionStop', () => {
69
+ it('should include continuing header and mode info', () => {
70
+ const result = formatSessionStop({
71
+ ...basePayload,
72
+ event: 'session-stop',
73
+ activeMode: 'ralph',
74
+ iteration: 3,
75
+ maxIterations: 10,
76
+ });
77
+ assert.ok(result.includes('# Session Continuing'));
78
+ assert.ok(result.includes('**Mode:** ralph'));
79
+ assert.ok(result.includes('3/10'));
80
+ });
81
+ });
82
+ describe('formatAskUserQuestion', () => {
83
+ it('should include question text', () => {
84
+ const result = formatAskUserQuestion({
85
+ ...basePayload,
86
+ event: 'ask-user-question',
87
+ question: 'Which approach should I use?',
88
+ });
89
+ assert.ok(result.includes('# Input Needed'));
90
+ assert.ok(result.includes('Which approach should I use?'));
91
+ assert.ok(result.includes('Codex is waiting for your response.'));
92
+ });
93
+ });
94
+ describe('formatNotification routing', () => {
95
+ it('should route each event type correctly', () => {
96
+ assert.ok(formatNotification({ ...basePayload, event: 'session-idle' }).includes('# Session Idle'));
97
+ assert.ok(formatNotification({ ...basePayload, event: 'session-start' }).includes('# Session Started'));
98
+ assert.ok(formatNotification({ ...basePayload, event: 'session-end' }).includes('# Session Ended'));
99
+ assert.ok(formatNotification({ ...basePayload, event: 'session-stop' }).includes('# Session Continuing'));
100
+ assert.ok(formatNotification({ ...basePayload, event: 'ask-user-question' }).includes('# Input Needed'));
101
+ });
102
+ });
103
+ //# sourceMappingURL=formatter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.test.js","sourceRoot":"","sources":["../../../src/notifications/__tests__/formatter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=notifier.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifier.test.d.ts","sourceRoot":"","sources":["../../../src/notifications/__tests__/notifier.test.ts"],"names":[],"mappings":""}