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,104 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { mkdirSync, writeFileSync, rmSync } from 'fs';
4
+ import { join } from 'path';
5
+ import { tmpdir } from 'os';
6
+ import { randomUUID } from 'crypto';
7
+ import { loadNotificationConfig, notify } from '../notifier.js';
8
+ describe('loadNotificationConfig', () => {
9
+ it('returns null when config file does not exist', async () => {
10
+ const fakePath = join(tmpdir(), `omx-test-${randomUUID()}`);
11
+ const config = await loadNotificationConfig(fakePath);
12
+ assert.equal(config, null);
13
+ });
14
+ it('returns parsed config when file exists', async () => {
15
+ const tmpDir = join(tmpdir(), `omx-test-${randomUUID()}`);
16
+ const omxDir = join(tmpDir, '.omx');
17
+ mkdirSync(omxDir, { recursive: true });
18
+ const configData = {
19
+ desktop: true,
20
+ discord: { webhookUrl: 'https://discord.com/api/webhooks/test' },
21
+ telegram: { botToken: '123:abc', chatId: '456' },
22
+ };
23
+ writeFileSync(join(omxDir, 'notifications.json'), JSON.stringify(configData));
24
+ try {
25
+ const config = await loadNotificationConfig(tmpDir);
26
+ assert.ok(config);
27
+ assert.equal(config.desktop, true);
28
+ assert.equal(config.discord?.webhookUrl, 'https://discord.com/api/webhooks/test');
29
+ assert.equal(config.telegram?.botToken, '123:abc');
30
+ assert.equal(config.telegram?.chatId, '456');
31
+ }
32
+ finally {
33
+ rmSync(tmpDir, { recursive: true, force: true });
34
+ }
35
+ });
36
+ it('returns null for invalid JSON', async () => {
37
+ const tmpDir = join(tmpdir(), `omx-test-${randomUUID()}`);
38
+ const omxDir = join(tmpDir, '.omx');
39
+ mkdirSync(omxDir, { recursive: true });
40
+ writeFileSync(join(omxDir, 'notifications.json'), 'not-json');
41
+ try {
42
+ const config = await loadNotificationConfig(tmpDir);
43
+ assert.equal(config, null);
44
+ }
45
+ finally {
46
+ rmSync(tmpDir, { recursive: true, force: true });
47
+ }
48
+ });
49
+ });
50
+ describe('notify', () => {
51
+ const basePayload = {
52
+ title: 'Test',
53
+ message: 'Test message',
54
+ type: 'info',
55
+ mode: 'test',
56
+ };
57
+ it('does nothing when config is null', async () => {
58
+ // Should not throw
59
+ await notify(basePayload, null);
60
+ });
61
+ it('does nothing when all channels are disabled', async () => {
62
+ const config = {};
63
+ // Should not throw
64
+ await notify(basePayload, config);
65
+ });
66
+ it('accepts all notification types', async () => {
67
+ const types = ['info', 'success', 'warning', 'error'];
68
+ for (const type of types) {
69
+ // Should not throw
70
+ await notify({ ...basePayload, type }, {});
71
+ }
72
+ });
73
+ });
74
+ describe('NotificationPayload type', () => {
75
+ it('requires title, message, and type', () => {
76
+ const payload = {
77
+ title: 'Test Title',
78
+ message: 'Test message body',
79
+ type: 'success',
80
+ };
81
+ assert.equal(payload.title, 'Test Title');
82
+ assert.equal(payload.message, 'Test message body');
83
+ assert.equal(payload.type, 'success');
84
+ });
85
+ it('supports optional mode', () => {
86
+ const payload = {
87
+ title: 'Test',
88
+ message: 'msg',
89
+ type: 'info',
90
+ mode: 'ralph',
91
+ };
92
+ assert.equal(payload.mode, 'ralph');
93
+ });
94
+ it('supports optional projectPath', () => {
95
+ const payload = {
96
+ title: 'Test',
97
+ message: 'msg',
98
+ type: 'warning',
99
+ projectPath: '/home/user/project',
100
+ };
101
+ assert.equal(payload.projectPath, '/home/user/project');
102
+ });
103
+ });
104
+ //# sourceMappingURL=notifier.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifier.test.js","sourceRoot":"","sources":["../../../src/notifications/__tests__/notifier.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=profiles.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.test.d.ts","sourceRoot":"","sources":["../../../src/notifications/__tests__/profiles.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,404 @@
1
+ import { describe, it, beforeEach, afterEach } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ /**
4
+ * Notification Profiles Tests
5
+ *
6
+ * Tests named notification profiles: resolution priority, default fallback,
7
+ * env var selection, backward compatibility with flat config, and edge cases.
8
+ *
9
+ * Config is read from disk via readRawConfig(), so we mock the fs module
10
+ * to inject test configs without touching the filesystem.
11
+ */
12
+ // We need to mock fs before importing config, so we use dynamic imports
13
+ // after setting up mocks per test.
14
+ const PROFILE_ENV_KEY = "OMX_NOTIFY_PROFILE";
15
+ function clearProfileEnv() {
16
+ delete process.env[PROFILE_ENV_KEY];
17
+ delete process.env.OMX_DISCORD_NOTIFIER_BOT_TOKEN;
18
+ delete process.env.OMX_DISCORD_NOTIFIER_CHANNEL;
19
+ delete process.env.OMX_DISCORD_WEBHOOK_URL;
20
+ delete process.env.OMX_DISCORD_MENTION;
21
+ delete process.env.OMX_TELEGRAM_BOT_TOKEN;
22
+ delete process.env.OMX_TELEGRAM_CHAT_ID;
23
+ delete process.env.OMX_SLACK_WEBHOOK_URL;
24
+ }
25
+ // ---------- resolveProfileConfig (pure function, no fs needed) ----------
26
+ describe("resolveProfileConfig", () => {
27
+ let resolveProfileConfig;
28
+ beforeEach(async () => {
29
+ clearProfileEnv();
30
+ const mod = await import("../config.js");
31
+ resolveProfileConfig = mod.resolveProfileConfig;
32
+ });
33
+ afterEach(() => {
34
+ clearProfileEnv();
35
+ });
36
+ it("returns null when no profiles defined", () => {
37
+ const result = resolveProfileConfig({
38
+ enabled: true,
39
+ telegram: { enabled: true, botToken: "t", chatId: "c" },
40
+ });
41
+ assert.equal(result, null);
42
+ });
43
+ it("returns null when profiles object is empty", () => {
44
+ const result = resolveProfileConfig({
45
+ enabled: true,
46
+ profiles: {},
47
+ });
48
+ assert.equal(result, null);
49
+ });
50
+ it("resolves explicit profileName argument", () => {
51
+ const workProfile = {
52
+ enabled: true,
53
+ telegram: { enabled: true, botToken: "work-token", chatId: "work-chat" },
54
+ };
55
+ const result = resolveProfileConfig({
56
+ enabled: true,
57
+ profiles: {
58
+ work: workProfile,
59
+ personal: {
60
+ enabled: true,
61
+ telegram: {
62
+ enabled: true,
63
+ botToken: "personal-token",
64
+ chatId: "personal-chat",
65
+ },
66
+ },
67
+ },
68
+ }, "work");
69
+ assert.deepEqual(result, workProfile);
70
+ });
71
+ it("resolves OMX_NOTIFY_PROFILE env var when no explicit name", () => {
72
+ process.env[PROFILE_ENV_KEY] = "personal";
73
+ const personalProfile = {
74
+ enabled: true,
75
+ telegram: {
76
+ enabled: true,
77
+ botToken: "personal-token",
78
+ chatId: "personal-chat",
79
+ },
80
+ };
81
+ const result = resolveProfileConfig({
82
+ enabled: true,
83
+ profiles: {
84
+ work: { enabled: true },
85
+ personal: personalProfile,
86
+ },
87
+ });
88
+ assert.deepEqual(result, personalProfile);
89
+ });
90
+ it("explicit profileName takes priority over env var", () => {
91
+ process.env[PROFILE_ENV_KEY] = "personal";
92
+ const workProfile = {
93
+ enabled: true,
94
+ "discord-bot": {
95
+ enabled: true,
96
+ botToken: "bot-t",
97
+ channelId: "ch-1",
98
+ },
99
+ };
100
+ const result = resolveProfileConfig({
101
+ enabled: true,
102
+ profiles: {
103
+ work: workProfile,
104
+ personal: { enabled: true },
105
+ },
106
+ }, "work");
107
+ assert.deepEqual(result, workProfile);
108
+ });
109
+ it("falls back to defaultProfile when no explicit name or env var", () => {
110
+ const defaultProfile = {
111
+ enabled: true,
112
+ slack: {
113
+ enabled: true,
114
+ webhookUrl: "https://hooks.slack.com/services/default",
115
+ },
116
+ };
117
+ const result = resolveProfileConfig({
118
+ enabled: true,
119
+ defaultProfile: "main",
120
+ profiles: {
121
+ main: defaultProfile,
122
+ secondary: { enabled: true },
123
+ },
124
+ });
125
+ assert.deepEqual(result, defaultProfile);
126
+ });
127
+ it("returns null when selected profile name does not exist", () => {
128
+ const result = resolveProfileConfig({
129
+ enabled: true,
130
+ profiles: {
131
+ work: { enabled: true },
132
+ },
133
+ }, "nonexistent");
134
+ assert.equal(result, null);
135
+ });
136
+ it("returns null when no profile selected and no defaultProfile", () => {
137
+ const result = resolveProfileConfig({
138
+ enabled: true,
139
+ profiles: {
140
+ work: { enabled: true },
141
+ personal: { enabled: true },
142
+ },
143
+ });
144
+ assert.equal(result, null);
145
+ });
146
+ it("profile with enabled=false is returned as-is", () => {
147
+ const silentProfile = { enabled: false };
148
+ const result = resolveProfileConfig({
149
+ enabled: true,
150
+ profiles: {
151
+ silent: silentProfile,
152
+ loud: { enabled: true },
153
+ },
154
+ }, "silent");
155
+ assert.deepEqual(result, silentProfile);
156
+ });
157
+ it("profile with per-event config is preserved", () => {
158
+ const profile = {
159
+ enabled: true,
160
+ telegram: { enabled: true, botToken: "t", chatId: "c" },
161
+ events: {
162
+ "session-end": {
163
+ enabled: true,
164
+ messageTemplate: "Done: {{summary}}",
165
+ },
166
+ "session-start": { enabled: false },
167
+ },
168
+ };
169
+ const result = resolveProfileConfig({
170
+ enabled: true,
171
+ profiles: { custom: profile },
172
+ }, "custom");
173
+ assert.deepEqual(result.events, profile.events);
174
+ });
175
+ it("priority order: explicit > env > defaultProfile", () => {
176
+ process.env[PROFILE_ENV_KEY] = "env-profile";
177
+ const config = {
178
+ enabled: true,
179
+ defaultProfile: "default-profile",
180
+ profiles: {
181
+ "explicit-profile": {
182
+ enabled: true,
183
+ telegram: { enabled: true, botToken: "explicit", chatId: "e" },
184
+ },
185
+ "env-profile": {
186
+ enabled: true,
187
+ telegram: { enabled: true, botToken: "env", chatId: "e" },
188
+ },
189
+ "default-profile": {
190
+ enabled: true,
191
+ telegram: { enabled: true, botToken: "default", chatId: "d" },
192
+ },
193
+ },
194
+ };
195
+ // Explicit wins over env and default
196
+ const r1 = resolveProfileConfig(config, "explicit-profile");
197
+ assert.equal(r1.telegram.botToken, "explicit");
198
+ // Env wins over default when no explicit
199
+ const r2 = resolveProfileConfig(config);
200
+ assert.equal(r2.telegram.botToken, "env");
201
+ // Default used when no explicit and no env
202
+ delete process.env[PROFILE_ENV_KEY];
203
+ const r3 = resolveProfileConfig(config);
204
+ assert.equal(r3.telegram.botToken, "default");
205
+ });
206
+ });
207
+ // ---------- getNotificationConfig with profiles ----------
208
+ describe("getNotificationConfig with profiles", () => {
209
+ // We test through the public API by manipulating env vars
210
+ // and relying on the fact that env-only config doesn't use profiles.
211
+ // For file-based tests we need to test resolveProfileConfig integration.
212
+ beforeEach(() => {
213
+ clearProfileEnv();
214
+ });
215
+ afterEach(() => {
216
+ clearProfileEnv();
217
+ });
218
+ it("env-only config still works without profiles", async () => {
219
+ process.env.OMX_TELEGRAM_BOT_TOKEN = "123:abc";
220
+ process.env.OMX_TELEGRAM_CHAT_ID = "999";
221
+ const { getNotificationConfig } = await import("../config.js");
222
+ const config = getNotificationConfig();
223
+ assert.ok(config);
224
+ assert.equal(config.enabled, true);
225
+ assert.equal(config.telegram.botToken, "123:abc");
226
+ });
227
+ it("getNotificationConfig passes profileName to resolver", async () => {
228
+ // When no file config exists and only env, profileName is a no-op
229
+ // but should not break anything
230
+ process.env.OMX_TELEGRAM_BOT_TOKEN = "123:abc";
231
+ process.env.OMX_TELEGRAM_CHAT_ID = "999";
232
+ const { getNotificationConfig } = await import("../config.js");
233
+ const config = getNotificationConfig("nonexistent");
234
+ assert.ok(config);
235
+ assert.equal(config.telegram.botToken, "123:abc");
236
+ });
237
+ });
238
+ // ---------- listProfiles / getActiveProfileName ----------
239
+ describe("listProfiles", () => {
240
+ beforeEach(() => {
241
+ clearProfileEnv();
242
+ });
243
+ afterEach(() => {
244
+ clearProfileEnv();
245
+ });
246
+ it("returns empty array when no config file", async () => {
247
+ const { listProfiles } = await import("../config.js");
248
+ // Without a config file, should return empty
249
+ const profiles = listProfiles();
250
+ assert.ok(Array.isArray(profiles));
251
+ });
252
+ });
253
+ describe("getActiveProfileName", () => {
254
+ beforeEach(() => {
255
+ clearProfileEnv();
256
+ });
257
+ afterEach(() => {
258
+ clearProfileEnv();
259
+ });
260
+ it("returns env var value when OMX_NOTIFY_PROFILE is set", async () => {
261
+ process.env[PROFILE_ENV_KEY] = "my-profile";
262
+ const { getActiveProfileName } = await import("../config.js");
263
+ const name = getActiveProfileName();
264
+ assert.equal(name, "my-profile");
265
+ });
266
+ it("returns null when no env var and no config file", async () => {
267
+ const { getActiveProfileName } = await import("../config.js");
268
+ const name = getActiveProfileName();
269
+ // Without a config file with profiles, should be null
270
+ assert.ok(name === null || typeof name === "string");
271
+ });
272
+ });
273
+ // ---------- NotificationsBlock type compatibility ----------
274
+ describe("NotificationsBlock type compatibility", () => {
275
+ it("flat config (no profiles) is assignable to NotificationsBlock", async () => {
276
+ const { resolveProfileConfig } = await import("../config.js");
277
+ // A flat config with no profiles should work with resolveProfileConfig
278
+ const flat = {
279
+ enabled: true,
280
+ discord: {
281
+ enabled: true,
282
+ webhookUrl: "https://discord.com/api/webhooks/test",
283
+ },
284
+ };
285
+ const result = resolveProfileConfig(flat);
286
+ assert.equal(result, null); // no profiles = null, use flat
287
+ });
288
+ it("profiled config works with resolveProfileConfig", async () => {
289
+ const { resolveProfileConfig } = await import("../config.js");
290
+ const profiled = {
291
+ enabled: true,
292
+ defaultProfile: "work",
293
+ profiles: {
294
+ work: {
295
+ enabled: true,
296
+ discord: {
297
+ enabled: true,
298
+ webhookUrl: "https://discord.com/api/webhooks/work",
299
+ },
300
+ },
301
+ personal: {
302
+ enabled: true,
303
+ telegram: {
304
+ enabled: true,
305
+ botToken: "123:abc",
306
+ chatId: "456",
307
+ },
308
+ },
309
+ },
310
+ };
311
+ const result = resolveProfileConfig(profiled);
312
+ assert.ok(result);
313
+ assert.equal(result.discord.webhookUrl, "https://discord.com/api/webhooks/work");
314
+ });
315
+ });
316
+ // ---------- Edge cases ----------
317
+ describe("profile edge cases", () => {
318
+ beforeEach(() => {
319
+ clearProfileEnv();
320
+ });
321
+ afterEach(() => {
322
+ clearProfileEnv();
323
+ });
324
+ it("profile can have multiple platforms configured", async () => {
325
+ const { resolveProfileConfig } = await import("../config.js");
326
+ const profile = {
327
+ enabled: true,
328
+ discord: {
329
+ enabled: true,
330
+ webhookUrl: "https://discord.com/api/webhooks/multi",
331
+ },
332
+ telegram: { enabled: true, botToken: "t", chatId: "c" },
333
+ slack: {
334
+ enabled: true,
335
+ webhookUrl: "https://hooks.slack.com/services/multi",
336
+ },
337
+ };
338
+ const result = resolveProfileConfig({
339
+ enabled: true,
340
+ profiles: { multi: profile },
341
+ }, "multi");
342
+ assert.ok(result.discord);
343
+ assert.ok(result.telegram);
344
+ assert.ok(result.slack);
345
+ });
346
+ it("env vars merge into selected profile config", async () => {
347
+ process.env.OMX_TELEGRAM_BOT_TOKEN = "env-token";
348
+ process.env.OMX_TELEGRAM_CHAT_ID = "env-chat";
349
+ const { buildConfigFromEnv, resolveProfileConfig } = await import("../config.js");
350
+ // Simulate what getNotificationConfig does: resolve profile, then merge env
351
+ const profile = {
352
+ enabled: true,
353
+ discord: {
354
+ enabled: true,
355
+ webhookUrl: "https://discord.com/api/webhooks/test",
356
+ },
357
+ };
358
+ const resolved = resolveProfileConfig({ enabled: true, profiles: { work: profile } }, "work");
359
+ assert.ok(resolved);
360
+ assert.equal(resolved.discord.enabled, true);
361
+ // Env config should be buildable separately
362
+ const envConfig = buildConfigFromEnv();
363
+ assert.ok(envConfig);
364
+ assert.equal(envConfig.telegram.botToken, "env-token");
365
+ });
366
+ it("profile names are case-sensitive", async () => {
367
+ const { resolveProfileConfig } = await import("../config.js");
368
+ const config = {
369
+ enabled: true,
370
+ profiles: {
371
+ Work: { enabled: true },
372
+ work: {
373
+ enabled: true,
374
+ telegram: { enabled: true, botToken: "lower", chatId: "c" },
375
+ },
376
+ },
377
+ };
378
+ const upper = resolveProfileConfig(config, "Work");
379
+ const lower = resolveProfileConfig(config, "work");
380
+ assert.ok(upper);
381
+ assert.ok(lower);
382
+ assert.equal(upper.telegram, undefined);
383
+ assert.equal(lower.telegram.botToken, "lower");
384
+ });
385
+ it("profile names can contain hyphens and dots", async () => {
386
+ const { resolveProfileConfig } = await import("../config.js");
387
+ const config = {
388
+ enabled: true,
389
+ profiles: {
390
+ "my-work.profile": {
391
+ enabled: true,
392
+ slack: {
393
+ enabled: true,
394
+ webhookUrl: "https://hooks.slack.com/services/hp",
395
+ },
396
+ },
397
+ },
398
+ };
399
+ const result = resolveProfileConfig(config, "my-work.profile");
400
+ assert.ok(result);
401
+ assert.ok(result.slack);
402
+ });
403
+ });
404
+ //# sourceMappingURL=profiles.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.test.js","sourceRoot":"","sources":["../../../src/notifications/__tests__/profiles.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=reply-listener.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reply-listener.test.d.ts","sourceRoot":"","sources":["../../../src/notifications/__tests__/reply-listener.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,58 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { sanitizeReplyInput } from '../reply-listener.js';
4
+ describe('sanitizeReplyInput', () => {
5
+ it('passes through normal text', () => {
6
+ assert.equal(sanitizeReplyInput('hello world'), 'hello world');
7
+ });
8
+ it('strips control characters', () => {
9
+ assert.equal(sanitizeReplyInput('hello\x00world'), 'helloworld');
10
+ assert.equal(sanitizeReplyInput('test\x07bell'), 'testbell');
11
+ assert.equal(sanitizeReplyInput('test\x1bescseq'), 'testescseq');
12
+ });
13
+ it('replaces newlines with spaces', () => {
14
+ assert.equal(sanitizeReplyInput('line1\nline2'), 'line1 line2');
15
+ assert.equal(sanitizeReplyInput('line1\r\nline2'), 'line1 line2');
16
+ });
17
+ it('escapes backslashes', () => {
18
+ assert.equal(sanitizeReplyInput('path\\to\\file'), 'path\\\\to\\\\file');
19
+ });
20
+ it('escapes backticks', () => {
21
+ assert.equal(sanitizeReplyInput('run `cmd`'), 'run \\`cmd\\`');
22
+ });
23
+ it('escapes $( command substitution', () => {
24
+ assert.equal(sanitizeReplyInput('$(whoami)'), '\\$(whoami)');
25
+ });
26
+ it('escapes ${ variable expansion', () => {
27
+ assert.equal(sanitizeReplyInput('${HOME}'), '\\${HOME}');
28
+ });
29
+ it('trims whitespace', () => {
30
+ assert.equal(sanitizeReplyInput(' hello '), 'hello');
31
+ });
32
+ it('handles empty string', () => {
33
+ assert.equal(sanitizeReplyInput(''), '');
34
+ });
35
+ it('handles whitespace-only string', () => {
36
+ assert.equal(sanitizeReplyInput(' '), '');
37
+ });
38
+ it('handles combined dangerous patterns', () => {
39
+ const input = '$(rm -rf /) && `evil` ${PATH}\nmore';
40
+ const result = sanitizeReplyInput(input);
41
+ // Should not contain unescaped backticks or newlines
42
+ assert.ok(!result.includes('\n'));
43
+ // $( should be escaped to \$(
44
+ assert.ok(result.includes('\\$('));
45
+ // ${ should be escaped to \${
46
+ assert.ok(result.includes('\\${'));
47
+ // backticks should be escaped
48
+ assert.ok(result.includes('\\`'));
49
+ });
50
+ it('preserves normal special characters', () => {
51
+ assert.equal(sanitizeReplyInput('hello! @user #tag'), 'hello! @user #tag');
52
+ });
53
+ it('handles unicode text', () => {
54
+ const result = sanitizeReplyInput('Hello world');
55
+ assert.ok(result.length > 0);
56
+ });
57
+ });
58
+ //# sourceMappingURL=reply-listener.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reply-listener.test.js","sourceRoot":"","sources":["../../../src/notifications/__tests__/reply-listener.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=session-registry.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-registry.test.d.ts","sourceRoot":"","sources":["../../../src/notifications/__tests__/session-registry.test.ts"],"names":[],"mappings":""}