github-issue-tower-defence-management 1.115.0 → 1.115.2
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.
- package/CHANGELOG.md +14 -0
- package/README.md +2 -3
- package/bin/adapter/entry-points/console/ui-dist/assets/index-B8K2luHn.css +1 -0
- package/bin/adapter/entry-points/console/ui-dist/index.html +2 -2
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +2 -17
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js +2 -4
- package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js.map +1 -1
- package/bin/adapter/repositories/TmuxSilentSessionNotificationRepository.js +1 -26
- package/bin/adapter/repositories/TmuxSilentSessionNotificationRepository.js.map +1 -1
- package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js +1 -10
- package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/console/ui/src/index.css +1 -7
- package/src/adapter/entry-points/console/ui-dist/assets/index-B8K2luHn.css +1 -0
- package/src/adapter/entry-points/console/ui-dist/index.html +2 -2
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +0 -21
- package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.test.ts +5 -77
- package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts +1 -12
- package/src/adapter/repositories/TmuxSilentSessionNotificationRepository.test.ts +2 -98
- package/src/adapter/repositories/TmuxSilentSessionNotificationRepository.ts +1 -45
- package/src/domain/usecases/NotifySilentLiveSessionsUseCase.test.ts +33 -10
- package/src/domain/usecases/NotifySilentLiveSessionsUseCase.ts +0 -22
- package/src/domain/usecases/adapter-interfaces/SilentSessionNotificationRepository.ts +0 -5
- package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts +0 -4
- package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts.map +1 -1
- package/types/adapter/repositories/TmuxSilentSessionNotificationRepository.d.ts +1 -6
- package/types/adapter/repositories/TmuxSilentSessionNotificationRepository.d.ts.map +1 -1
- package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts +0 -2
- package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts.map +1 -1
- package/types/domain/usecases/adapter-interfaces/SilentSessionNotificationRepository.d.ts +0 -2
- package/types/domain/usecases/adapter-interfaces/SilentSessionNotificationRepository.d.ts.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-Blb_xqIx.css +0 -1
- package/src/adapter/entry-points/console/ui-dist/assets/index-Blb_xqIx.css +0 -1
- /package/bin/adapter/entry-points/console/ui-dist/assets/{index-DQyZ8KpG.js → index-BNFY_kIF.js} +0 -0
- /package/src/adapter/entry-points/console/ui-dist/assets/{index-DQyZ8KpG.js → index-BNFY_kIF.js} +0 -0
|
@@ -65,15 +65,6 @@ import {
|
|
|
65
65
|
|
|
66
66
|
const DEFAULT_DASHBOARD_DATA_DIR: string | null = null;
|
|
67
67
|
|
|
68
|
-
// The silent-session notification inspects the single, global set of live tmux
|
|
69
|
-
// sessions, but the scheduled handler runs once per project. If its cooldown
|
|
70
|
-
// were stored in the per-project cache (`./tmp/cache/<projectName>`), the same
|
|
71
|
-
// session would get an independent cooldown record per project and be notified
|
|
72
|
-
// once per enabled project within a single cooldown window. The cooldown must
|
|
73
|
-
// therefore live in a single project-independent cache scope so it is shared
|
|
74
|
-
// across every per-project pass.
|
|
75
|
-
const SILENT_SESSION_NOTIFICATION_CACHE_PATH = './tmp/cache/shared';
|
|
76
|
-
|
|
77
68
|
const readSilentSeconds = (
|
|
78
69
|
configValue: number | undefined,
|
|
79
70
|
envValue: string | undefined,
|
|
@@ -125,7 +116,6 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
125
116
|
mainSilentThresholdSeconds?: number;
|
|
126
117
|
subAgentSilentThresholdSeconds?: number;
|
|
127
118
|
subAgentRunningThresholdSeconds?: number;
|
|
128
|
-
silentNotificationCooldownSeconds?: number;
|
|
129
119
|
silentNotificationStaggerSeconds?: number;
|
|
130
120
|
activeHubTaskStatus?: string;
|
|
131
121
|
silentMainStalledMessage?: string;
|
|
@@ -591,15 +581,9 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
591
581
|
mergedInput.subAgentTranscriptRootDirectory ??
|
|
592
582
|
process.env.TDPM_SUBAGENT_TRANSCRIPT_ROOT_DIRECTORY ??
|
|
593
583
|
null;
|
|
594
|
-
const silentSessionNotificationCacheRepository =
|
|
595
|
-
new LocalStorageCacheRepository(
|
|
596
|
-
localStorageRepository,
|
|
597
|
-
SILENT_SESSION_NOTIFICATION_CACHE_PATH,
|
|
598
|
-
);
|
|
599
584
|
await notifySilentTmuxSessions({
|
|
600
585
|
enabled: silentNotificationEnabled,
|
|
601
586
|
localCommandRunner: nodeLocalCommandRunner,
|
|
602
|
-
cacheRepository: silentSessionNotificationCacheRepository,
|
|
603
587
|
ownerCallMarker,
|
|
604
588
|
subAgentOutputRootDirectory,
|
|
605
589
|
subAgentProcessMatchPattern,
|
|
@@ -619,11 +603,6 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
619
603
|
process.env.TDPM_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
|
|
620
604
|
DEFAULT_NOTIFY_SILENT_TMUX_SESSIONS_PARAMS.subAgentRunningThresholdSeconds,
|
|
621
605
|
),
|
|
622
|
-
cooldownSeconds: readSilentSeconds(
|
|
623
|
-
mergedInput.silentNotificationCooldownSeconds,
|
|
624
|
-
process.env.TDPM_SILENT_NOTIFICATION_COOLDOWN_SECONDS,
|
|
625
|
-
DEFAULT_NOTIFY_SILENT_TMUX_SESSIONS_PARAMS.cooldownSeconds,
|
|
626
|
-
),
|
|
627
606
|
staggerSeconds: readSilentSeconds(
|
|
628
607
|
mergedInput.silentNotificationStaggerSeconds,
|
|
629
608
|
process.env.TDPM_SILENT_NOTIFICATION_STAGGER_SECONDS,
|
|
@@ -3,8 +3,6 @@ import * as os from 'os';
|
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import { LocalCommandRunner } from '../../../domain/usecases/adapter-interfaces/LocalCommandRunner';
|
|
5
5
|
import { ProcessEnvironReader } from '../../../domain/usecases/adapter-interfaces/ProcessEnvironReader';
|
|
6
|
-
import { LocalStorageCacheRepository } from '../../repositories/LocalStorageCacheRepository';
|
|
7
|
-
import { LocalStorageRepository } from '../../repositories/LocalStorageRepository';
|
|
8
6
|
import { SilentSessionMessageTemplates } from '../../repositories/ConfigurableSilentSessionMessageComposer';
|
|
9
7
|
import { Issue } from '../../../domain/entities/Issue';
|
|
10
8
|
import { SILENT_SESSION_REMINDER_SENTINEL } from '../../../domain/usecases/silentSessionReminderSentinel';
|
|
@@ -38,18 +36,15 @@ const createMockRunner = (): Mocked<LocalCommandRunner> => ({
|
|
|
38
36
|
|
|
39
37
|
describe('notifySilentTmuxSessions', () => {
|
|
40
38
|
let configDir: string;
|
|
41
|
-
let cacheDirectory: string;
|
|
42
39
|
|
|
43
40
|
beforeEach(() => {
|
|
44
41
|
jest.spyOn(console, 'log').mockImplementation(() => undefined);
|
|
45
42
|
configDir = fs.mkdtempSync(path.join(os.tmpdir(), 'silent-config-'));
|
|
46
|
-
cacheDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'silent-cache-'));
|
|
47
43
|
});
|
|
48
44
|
|
|
49
45
|
afterEach(() => {
|
|
50
46
|
jest.restoreAllMocks();
|
|
51
47
|
fs.rmSync(configDir, { force: true, recursive: true });
|
|
52
|
-
fs.rmSync(cacheDirectory, { force: true, recursive: true });
|
|
53
48
|
});
|
|
54
49
|
|
|
55
50
|
const writeTranscript = (lines: object[]): void => {
|
|
@@ -78,17 +73,6 @@ describe('notifySilentTmuxSessions', () => {
|
|
|
78
73
|
]);
|
|
79
74
|
};
|
|
80
75
|
|
|
81
|
-
const makeCacheRepository = (): LocalStorageCacheRepository =>
|
|
82
|
-
new LocalStorageCacheRepository(
|
|
83
|
-
new LocalStorageRepository(),
|
|
84
|
-
cacheDirectory,
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
const makeCacheRepositoryAt = (
|
|
88
|
-
basePath: string,
|
|
89
|
-
): LocalStorageCacheRepository =>
|
|
90
|
-
new LocalStorageCacheRepository(new LocalStorageRepository(), basePath);
|
|
91
|
-
|
|
92
76
|
const makeEnvironReader = (): ProcessEnvironReader => ({
|
|
93
77
|
readEnviron: (pid: number) =>
|
|
94
78
|
pid === CLAUDE_PID
|
|
@@ -126,7 +110,6 @@ describe('notifySilentTmuxSessions', () => {
|
|
|
126
110
|
enabled: true,
|
|
127
111
|
localCommandRunner: runner,
|
|
128
112
|
processEnvironReader: makeEnvironReader(),
|
|
129
|
-
cacheRepository: makeCacheRepository(),
|
|
130
113
|
ownerCallMarker: null,
|
|
131
114
|
subAgentOutputRootDirectory: null,
|
|
132
115
|
subAgentProcessMatchPattern: null,
|
|
@@ -219,54 +202,27 @@ describe('notifySilentTmuxSessions', () => {
|
|
|
219
202
|
expect(sendCall).toBeUndefined();
|
|
220
203
|
});
|
|
221
204
|
|
|
222
|
-
it('
|
|
205
|
+
it('re-notifies the same silent session on the next cycle with no cooldown suppression', async () => {
|
|
223
206
|
silentAssistantTranscript();
|
|
224
|
-
const cacheRepository = makeCacheRepository();
|
|
225
207
|
const firstRunner = liveSessionRunner();
|
|
226
208
|
|
|
227
|
-
await notifySilentTmuxSessions(
|
|
228
|
-
...baseParams(firstRunner),
|
|
229
|
-
cacheRepository,
|
|
230
|
-
});
|
|
209
|
+
await notifySilentTmuxSessions(baseParams(firstRunner));
|
|
231
210
|
|
|
232
|
-
const
|
|
233
|
-
await notifySilentTmuxSessions({
|
|
234
|
-
...baseParams(secondRunner),
|
|
235
|
-
cacheRepository,
|
|
236
|
-
now: new Date(NOW.getTime() + 60 * 1000),
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
const secondSendCall = secondRunner.runCommand.mock.calls.find(
|
|
211
|
+
const firstSendCall = firstRunner.runCommand.mock.calls.find(
|
|
240
212
|
(call) => call[0] === 'tmux' && call[1][0] === 'send-keys',
|
|
241
213
|
);
|
|
242
|
-
expect(
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
it('shares the cooldown across project passes when a single project-independent cache scope is used', async () => {
|
|
246
|
-
silentAssistantTranscript();
|
|
247
|
-
// The handler runs once per project over the same global set of tmux
|
|
248
|
-
// sessions. When the silent-session cooldown lives in one shared cache
|
|
249
|
-
// scope, a second per-project pass for the same session within the cooldown
|
|
250
|
-
// window must NOT re-send, even though it is a different project pass.
|
|
251
|
-
const sharedCacheBasePath = path.join(cacheDirectory, 'shared');
|
|
252
|
-
const firstRunner = liveSessionRunner();
|
|
253
|
-
|
|
254
|
-
await notifySilentTmuxSessions({
|
|
255
|
-
...baseParams(firstRunner),
|
|
256
|
-
cacheRepository: makeCacheRepositoryAt(sharedCacheBasePath),
|
|
257
|
-
});
|
|
214
|
+
expect(firstSendCall?.[1][2]).toBe(SESSION_NAME);
|
|
258
215
|
|
|
259
216
|
const secondRunner = liveSessionRunner();
|
|
260
217
|
await notifySilentTmuxSessions({
|
|
261
218
|
...baseParams(secondRunner),
|
|
262
|
-
cacheRepository: makeCacheRepositoryAt(sharedCacheBasePath),
|
|
263
219
|
now: new Date(NOW.getTime() + 60 * 1000),
|
|
264
220
|
});
|
|
265
221
|
|
|
266
222
|
const secondSendCall = secondRunner.runCommand.mock.calls.find(
|
|
267
223
|
(call) => call[0] === 'tmux' && call[1][0] === 'send-keys',
|
|
268
224
|
);
|
|
269
|
-
expect(secondSendCall).
|
|
225
|
+
expect(secondSendCall?.[1][2]).toBe(SESSION_NAME);
|
|
270
226
|
});
|
|
271
227
|
|
|
272
228
|
const HUB_TASK_SESSION_NAME =
|
|
@@ -385,32 +341,4 @@ describe('notifySilentTmuxSessions', () => {
|
|
|
385
341
|
);
|
|
386
342
|
expect(sendCall?.[1][2]).toBe(HUB_TASK_SESSION_NAME);
|
|
387
343
|
});
|
|
388
|
-
|
|
389
|
-
it('re-sends within the cooldown window when each project pass uses its own cache scope', async () => {
|
|
390
|
-
silentAssistantTranscript();
|
|
391
|
-
// This reproduces the per-project cooldown defect: when each project pass
|
|
392
|
-
// stores its cooldown under its own project-scoped cache path, the same
|
|
393
|
-
// session is notified once per project within the cooldown window.
|
|
394
|
-
const firstRunner = liveSessionRunner();
|
|
395
|
-
await notifySilentTmuxSessions({
|
|
396
|
-
...baseParams(firstRunner),
|
|
397
|
-
cacheRepository: makeCacheRepositoryAt(
|
|
398
|
-
path.join(cacheDirectory, 'umino'),
|
|
399
|
-
),
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
const secondRunner = liveSessionRunner();
|
|
403
|
-
await notifySilentTmuxSessions({
|
|
404
|
-
...baseParams(secondRunner),
|
|
405
|
-
cacheRepository: makeCacheRepositoryAt(
|
|
406
|
-
path.join(cacheDirectory, 'xmile'),
|
|
407
|
-
),
|
|
408
|
-
now: new Date(NOW.getTime() + 60 * 1000),
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
const secondSendCall = secondRunner.runCommand.mock.calls.find(
|
|
412
|
-
(call) => call[0] === 'tmux' && call[1][0] === 'send-keys',
|
|
413
|
-
);
|
|
414
|
-
expect(secondSendCall?.[1][2]).toBe(SESSION_NAME);
|
|
415
|
-
});
|
|
416
344
|
});
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
|
|
9
9
|
DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
|
|
10
10
|
DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
|
|
11
|
-
DEFAULT_NOTIFICATION_COOLDOWN_SECONDS,
|
|
12
11
|
DEFAULT_NOTIFICATION_STAGGER_SECONDS,
|
|
13
12
|
} from '../../../domain/usecases/NotifySilentLiveSessionsUseCase';
|
|
14
13
|
import { DefaultSilentSessionMessageComposer } from '../../../domain/usecases/DefaultSilentSessionMessageComposer';
|
|
@@ -17,7 +16,6 @@ import { ProcFsProcessEnvironReader } from '../../repositories/ProcFsProcessEnvi
|
|
|
17
16
|
import { FileSystemInteractiveLiveSessionTranscriptResolver } from '../../repositories/FileSystemInteractiveLiveSessionTranscriptResolver';
|
|
18
17
|
import { FileSystemSessionOutputActivityRepository } from '../../repositories/FileSystemSessionOutputActivityRepository';
|
|
19
18
|
import { TmuxSilentSessionNotificationRepository } from '../../repositories/TmuxSilentSessionNotificationRepository';
|
|
20
|
-
import { LocalStorageCacheRepository } from '../../repositories/LocalStorageCacheRepository';
|
|
21
19
|
import { NoUnansweredOwnerCallStatusProvider } from '../../repositories/NoUnansweredOwnerCallStatusProvider';
|
|
22
20
|
import { TranscriptOwnerCallStatusProvider } from '../../repositories/TranscriptOwnerCallStatusProvider';
|
|
23
21
|
import { ProcessListSessionSubAgentActivityRepository } from '../../repositories/ProcessListSessionSubAgentActivityRepository';
|
|
@@ -35,7 +33,6 @@ export type NotifySilentTmuxSessionsParams = {
|
|
|
35
33
|
enabled: boolean;
|
|
36
34
|
localCommandRunner: LocalCommandRunner;
|
|
37
35
|
processEnvironReader?: ProcessEnvironReader;
|
|
38
|
-
cacheRepository: Pick<LocalStorageCacheRepository, 'getLatest' | 'set'>;
|
|
39
36
|
ownerCallMarker: string | null;
|
|
40
37
|
subAgentOutputRootDirectory: string | null;
|
|
41
38
|
subAgentProcessMatchPattern: string | null;
|
|
@@ -43,7 +40,6 @@ export type NotifySilentTmuxSessionsParams = {
|
|
|
43
40
|
mainSilentThresholdSeconds: number;
|
|
44
41
|
subAgentSilentThresholdSeconds: number;
|
|
45
42
|
subAgentRunningThresholdSeconds: number;
|
|
46
|
-
cooldownSeconds: number;
|
|
47
43
|
staggerSeconds: number;
|
|
48
44
|
activeHubTaskStatus: string | null;
|
|
49
45
|
hubTaskStatusResolver: HubTaskStatusResolver | null;
|
|
@@ -92,7 +88,6 @@ export const notifySilentTmuxSessions = async (
|
|
|
92
88
|
enabled,
|
|
93
89
|
localCommandRunner,
|
|
94
90
|
processEnvironReader,
|
|
95
|
-
cacheRepository,
|
|
96
91
|
ownerCallMarker,
|
|
97
92
|
subAgentOutputRootDirectory,
|
|
98
93
|
subAgentProcessMatchPattern,
|
|
@@ -100,7 +95,6 @@ export const notifySilentTmuxSessions = async (
|
|
|
100
95
|
mainSilentThresholdSeconds,
|
|
101
96
|
subAgentSilentThresholdSeconds,
|
|
102
97
|
subAgentRunningThresholdSeconds,
|
|
103
|
-
cooldownSeconds,
|
|
104
98
|
staggerSeconds,
|
|
105
99
|
activeHubTaskStatus,
|
|
106
100
|
hubTaskStatusResolver,
|
|
@@ -132,10 +126,7 @@ export const notifySilentTmuxSessions = async (
|
|
|
132
126
|
now,
|
|
133
127
|
),
|
|
134
128
|
createOwnerCallStatusProvider(ownerCallMarker),
|
|
135
|
-
new TmuxSilentSessionNotificationRepository(
|
|
136
|
-
localCommandRunner,
|
|
137
|
-
cacheRepository,
|
|
138
|
-
),
|
|
129
|
+
new TmuxSilentSessionNotificationRepository(localCommandRunner),
|
|
139
130
|
messageComposer,
|
|
140
131
|
new RealSleeper(),
|
|
141
132
|
hubTaskStatusResolver,
|
|
@@ -144,7 +135,6 @@ export const notifySilentTmuxSessions = async (
|
|
|
144
135
|
mainSilentThresholdSeconds,
|
|
145
136
|
subAgentSilentThresholdSeconds,
|
|
146
137
|
subAgentRunningThresholdSeconds,
|
|
147
|
-
cooldownSeconds,
|
|
148
138
|
staggerSeconds,
|
|
149
139
|
activeHubTaskStatus,
|
|
150
140
|
now,
|
|
@@ -155,6 +145,5 @@ export const DEFAULT_NOTIFY_SILENT_TMUX_SESSIONS_PARAMS = {
|
|
|
155
145
|
mainSilentThresholdSeconds: DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
|
|
156
146
|
subAgentSilentThresholdSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
|
|
157
147
|
subAgentRunningThresholdSeconds: DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
|
|
158
|
-
cooldownSeconds: DEFAULT_NOTIFICATION_COOLDOWN_SECONDS,
|
|
159
148
|
staggerSeconds: DEFAULT_NOTIFICATION_STAGGER_SECONDS,
|
|
160
149
|
} as const;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { LocalCommandRunner } from '../../domain/usecases/adapter-interfaces/LocalCommandRunner';
|
|
2
|
-
import { LocalStorageCacheRepository } from './LocalStorageCacheRepository';
|
|
3
2
|
import { TmuxSilentSessionNotificationRepository } from './TmuxSilentSessionNotificationRepository';
|
|
4
3
|
|
|
5
4
|
type Mocked<T> = jest.Mocked<T> & jest.MockedObject<T>;
|
|
@@ -12,22 +11,11 @@ const createMockRunner = (): Mocked<LocalCommandRunner> => ({
|
|
|
12
11
|
}),
|
|
13
12
|
});
|
|
14
13
|
|
|
15
|
-
const createMockCacheRepository = (): Mocked<
|
|
16
|
-
Pick<LocalStorageCacheRepository, 'getLatest' | 'set'>
|
|
17
|
-
> => ({
|
|
18
|
-
getLatest: jest.fn().mockResolvedValue(null),
|
|
19
|
-
set: jest.fn().mockResolvedValue(undefined),
|
|
20
|
-
});
|
|
21
|
-
|
|
22
14
|
describe('TmuxSilentSessionNotificationRepository', () => {
|
|
23
15
|
describe('sendSelfCheckNotification', () => {
|
|
24
16
|
it('sends the message literally then submits it with Enter', async () => {
|
|
25
17
|
const runner = createMockRunner();
|
|
26
|
-
const
|
|
27
|
-
const repository = new TmuxSilentSessionNotificationRepository(
|
|
28
|
-
runner,
|
|
29
|
-
cache,
|
|
30
|
-
);
|
|
18
|
+
const repository = new TmuxSilentSessionNotificationRepository(runner);
|
|
31
19
|
|
|
32
20
|
await repository.sendSelfCheckNotification(
|
|
33
21
|
'https_//github_com/owner/repo/issues/9',
|
|
@@ -57,11 +45,7 @@ describe('TmuxSilentSessionNotificationRepository', () => {
|
|
|
57
45
|
stderr: "can't find session",
|
|
58
46
|
exitCode: 1,
|
|
59
47
|
});
|
|
60
|
-
const
|
|
61
|
-
const repository = new TmuxSilentSessionNotificationRepository(
|
|
62
|
-
runner,
|
|
63
|
-
cache,
|
|
64
|
-
);
|
|
48
|
+
const repository = new TmuxSilentSessionNotificationRepository(runner);
|
|
65
49
|
|
|
66
50
|
await expect(
|
|
67
51
|
repository.sendSelfCheckNotification('missing_session', 'message'),
|
|
@@ -70,84 +54,4 @@ describe('TmuxSilentSessionNotificationRepository', () => {
|
|
|
70
54
|
);
|
|
71
55
|
});
|
|
72
56
|
});
|
|
73
|
-
|
|
74
|
-
describe('getLastNotifiedEpochSeconds', () => {
|
|
75
|
-
it('returns the cached epoch seconds for a session', async () => {
|
|
76
|
-
const runner = createMockRunner();
|
|
77
|
-
const cache = createMockCacheRepository();
|
|
78
|
-
cache.getLatest.mockResolvedValue({
|
|
79
|
-
value: { epochSeconds: 1700000000 },
|
|
80
|
-
timestamp: new Date(),
|
|
81
|
-
});
|
|
82
|
-
const repository = new TmuxSilentSessionNotificationRepository(
|
|
83
|
-
runner,
|
|
84
|
-
cache,
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
const result = await repository.getLastNotifiedEpochSeconds(
|
|
88
|
-
'https_//github_com/owner/repo/issues/9',
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
expect(result).toBe(1700000000);
|
|
92
|
-
expect(cache.getLatest).toHaveBeenCalledWith(
|
|
93
|
-
'silent-session-notification/https___github_com_owner_repo_issues_9',
|
|
94
|
-
);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('returns null when no cache entry exists', async () => {
|
|
98
|
-
const runner = createMockRunner();
|
|
99
|
-
const cache = createMockCacheRepository();
|
|
100
|
-
cache.getLatest.mockResolvedValue(null);
|
|
101
|
-
const repository = new TmuxSilentSessionNotificationRepository(
|
|
102
|
-
runner,
|
|
103
|
-
cache,
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
const result = await repository.getLastNotifiedEpochSeconds(
|
|
107
|
-
'https_//github_com/owner/repo/issues/9',
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
expect(result).toBeNull();
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('returns null when the cached value has no numeric epoch', async () => {
|
|
114
|
-
const runner = createMockRunner();
|
|
115
|
-
const cache = createMockCacheRepository();
|
|
116
|
-
cache.getLatest.mockResolvedValue({
|
|
117
|
-
value: {},
|
|
118
|
-
timestamp: new Date(),
|
|
119
|
-
});
|
|
120
|
-
const repository = new TmuxSilentSessionNotificationRepository(
|
|
121
|
-
runner,
|
|
122
|
-
cache,
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
const result = await repository.getLastNotifiedEpochSeconds(
|
|
126
|
-
'https_//github_com/owner/repo/issues/9',
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
expect(result).toBeNull();
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
describe('setLastNotifiedEpochSeconds', () => {
|
|
134
|
-
it('persists the epoch seconds keyed by the sanitized session name', async () => {
|
|
135
|
-
const runner = createMockRunner();
|
|
136
|
-
const cache = createMockCacheRepository();
|
|
137
|
-
const repository = new TmuxSilentSessionNotificationRepository(
|
|
138
|
-
runner,
|
|
139
|
-
cache,
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
await repository.setLastNotifiedEpochSeconds(
|
|
143
|
-
'https_//github_com/owner/repo/issues/9',
|
|
144
|
-
1700000000,
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
expect(cache.set).toHaveBeenCalledWith(
|
|
148
|
-
'silent-session-notification/https___github_com_owner_repo_issues_9',
|
|
149
|
-
{ epochSeconds: 1700000000 },
|
|
150
|
-
);
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
57
|
});
|
|
@@ -1,49 +1,8 @@
|
|
|
1
1
|
import { SilentSessionNotificationRepository } from '../../domain/usecases/adapter-interfaces/SilentSessionNotificationRepository';
|
|
2
2
|
import { LocalCommandRunner } from '../../domain/usecases/adapter-interfaces/LocalCommandRunner';
|
|
3
|
-
import { LocalStorageCacheRepository } from './LocalStorageCacheRepository';
|
|
4
|
-
|
|
5
|
-
const CACHE_KEY_PREFIX = 'silent-session-notification';
|
|
6
|
-
|
|
7
|
-
const readEpochSeconds = (value: object): number | null => {
|
|
8
|
-
if (!('epochSeconds' in value)) {
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
const candidate = value.epochSeconds;
|
|
12
|
-
if (typeof candidate !== 'number') {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
return candidate;
|
|
16
|
-
};
|
|
17
3
|
|
|
18
4
|
export class TmuxSilentSessionNotificationRepository implements SilentSessionNotificationRepository {
|
|
19
|
-
constructor(
|
|
20
|
-
private readonly localCommandRunner: LocalCommandRunner,
|
|
21
|
-
private readonly cacheRepository: Pick<
|
|
22
|
-
LocalStorageCacheRepository,
|
|
23
|
-
'getLatest' | 'set'
|
|
24
|
-
>,
|
|
25
|
-
) {}
|
|
26
|
-
|
|
27
|
-
getLastNotifiedEpochSeconds = async (
|
|
28
|
-
sessionName: string,
|
|
29
|
-
): Promise<number | null> => {
|
|
30
|
-
const cached = await this.cacheRepository.getLatest(
|
|
31
|
-
this.toCacheKey(sessionName),
|
|
32
|
-
);
|
|
33
|
-
if (cached === null) {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
return readEpochSeconds(cached.value);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
setLastNotifiedEpochSeconds = async (
|
|
40
|
-
sessionName: string,
|
|
41
|
-
epochSeconds: number,
|
|
42
|
-
): Promise<void> => {
|
|
43
|
-
await this.cacheRepository.set(this.toCacheKey(sessionName), {
|
|
44
|
-
epochSeconds,
|
|
45
|
-
});
|
|
46
|
-
};
|
|
5
|
+
constructor(private readonly localCommandRunner: LocalCommandRunner) {}
|
|
47
6
|
|
|
48
7
|
sendSelfCheckNotification = async (
|
|
49
8
|
sessionName: string,
|
|
@@ -77,7 +36,4 @@ export class TmuxSilentSessionNotificationRepository implements SilentSessionNot
|
|
|
77
36
|
);
|
|
78
37
|
}
|
|
79
38
|
};
|
|
80
|
-
|
|
81
|
-
private toCacheKey = (sessionName: string): string =>
|
|
82
|
-
`${CACHE_KEY_PREFIX}/${sessionName.replace(/\//g, '_')}`;
|
|
83
39
|
}
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
|
|
6
6
|
DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
|
|
7
7
|
DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
|
|
8
|
-
DEFAULT_NOTIFICATION_COOLDOWN_SECONDS,
|
|
9
8
|
DEFAULT_NOTIFICATION_STAGGER_SECONDS,
|
|
10
9
|
} from './NotifySilentLiveSessionsUseCase';
|
|
11
10
|
import { Issue } from '../entities/Issue';
|
|
@@ -46,7 +45,6 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
46
45
|
mainSilentThresholdSeconds: number;
|
|
47
46
|
subAgentSilentThresholdSeconds: number;
|
|
48
47
|
subAgentRunningThresholdSeconds: number;
|
|
49
|
-
cooldownSeconds: number;
|
|
50
48
|
staggerSeconds: number;
|
|
51
49
|
activeHubTaskStatus: string | null;
|
|
52
50
|
now: Date;
|
|
@@ -54,7 +52,6 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
54
52
|
mainSilentThresholdSeconds: DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
|
|
55
53
|
subAgentSilentThresholdSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
|
|
56
54
|
subAgentRunningThresholdSeconds: DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
|
|
57
|
-
cooldownSeconds: DEFAULT_NOTIFICATION_COOLDOWN_SECONDS,
|
|
58
55
|
staggerSeconds: DEFAULT_NOTIFICATION_STAGGER_SECONDS,
|
|
59
56
|
activeHubTaskStatus: null,
|
|
60
57
|
now,
|
|
@@ -127,8 +124,6 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
127
124
|
.mockResolvedValue(new Set<string>()),
|
|
128
125
|
};
|
|
129
126
|
mockNotificationRepository = {
|
|
130
|
-
getLastNotifiedEpochSeconds: jest.fn().mockResolvedValue(null),
|
|
131
|
-
setLastNotifiedEpochSeconds: jest.fn().mockResolvedValue(undefined),
|
|
132
127
|
sendSelfCheckNotification: jest.fn().mockResolvedValue(undefined),
|
|
133
128
|
};
|
|
134
129
|
mockMessageComposer = {
|
|
@@ -210,7 +205,6 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
210
205
|
expect(DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS).toBe(600);
|
|
211
206
|
expect(DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS).toBe(300);
|
|
212
207
|
expect(DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS).toBe(900);
|
|
213
|
-
expect(DEFAULT_NOTIFICATION_COOLDOWN_SECONDS).toBe(30 * 60);
|
|
214
208
|
expect(DEFAULT_NOTIFICATION_STAGGER_SECONDS).toBe(25);
|
|
215
209
|
});
|
|
216
210
|
|
|
@@ -379,7 +373,7 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
379
373
|
).not.toHaveBeenCalled();
|
|
380
374
|
});
|
|
381
375
|
|
|
382
|
-
it('
|
|
376
|
+
it('re-notifies a session on every consecutive cycle while it remains a valid silent target', async () => {
|
|
383
377
|
setupLiveInteractiveSession('workbench');
|
|
384
378
|
mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
|
|
385
379
|
[
|
|
@@ -390,15 +384,44 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
390
384
|
},
|
|
391
385
|
],
|
|
392
386
|
);
|
|
393
|
-
|
|
394
|
-
|
|
387
|
+
|
|
388
|
+
await useCase.run(runParams());
|
|
389
|
+
await useCase.run(runParams());
|
|
390
|
+
|
|
391
|
+
expect(
|
|
392
|
+
mockNotificationRepository.sendSelfCheckNotification,
|
|
393
|
+
).toHaveBeenCalledTimes(2);
|
|
394
|
+
expect(
|
|
395
|
+
mockNotificationRepository.sendSelfCheckNotification,
|
|
396
|
+
).toHaveBeenNthCalledWith(1, 'workbench', MAIN_STALLED_SECTION);
|
|
397
|
+
expect(
|
|
398
|
+
mockNotificationRepository.sendSelfCheckNotification,
|
|
399
|
+
).toHaveBeenNthCalledWith(2, 'workbench', MAIN_STALLED_SECTION);
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
it('notifies on every repeated cycle at the same instant without reading any cooldown state', async () => {
|
|
403
|
+
setupLiveInteractiveSession('workbench');
|
|
404
|
+
mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
|
|
405
|
+
[
|
|
406
|
+
{
|
|
407
|
+
sessionName: 'workbench',
|
|
408
|
+
lastOutputEpochSeconds:
|
|
409
|
+
nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
|
|
410
|
+
},
|
|
411
|
+
],
|
|
395
412
|
);
|
|
396
413
|
|
|
414
|
+
await useCase.run(runParams());
|
|
415
|
+
await useCase.run(runParams());
|
|
397
416
|
await useCase.run(runParams());
|
|
398
417
|
|
|
399
418
|
expect(
|
|
400
419
|
mockNotificationRepository.sendSelfCheckNotification,
|
|
401
|
-
).
|
|
420
|
+
).toHaveBeenCalledTimes(3);
|
|
421
|
+
expect(Object.keys(mockNotificationRepository)).toEqual([
|
|
422
|
+
'sendSelfCheckNotification',
|
|
423
|
+
]);
|
|
424
|
+
expect(runParams()).not.toHaveProperty('cooldownSeconds');
|
|
402
425
|
});
|
|
403
426
|
|
|
404
427
|
it('sends to multiple sessions sequentially with a stagger delay between sends', async () => {
|
|
@@ -14,7 +14,6 @@ import { ResolveInteractiveLiveSessionsUseCase } from './ResolveInteractiveLiveS
|
|
|
14
14
|
export const DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS = 10 * 60;
|
|
15
15
|
export const DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS = 5 * 60;
|
|
16
16
|
export const DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS = 15 * 60;
|
|
17
|
-
export const DEFAULT_NOTIFICATION_COOLDOWN_SECONDS = 30 * 60;
|
|
18
17
|
export const DEFAULT_NOTIFICATION_STAGGER_SECONDS = 25;
|
|
19
18
|
|
|
20
19
|
const GITHUB_ISSUE_URL_PATTERN =
|
|
@@ -53,7 +52,6 @@ export class NotifySilentLiveSessionsUseCase {
|
|
|
53
52
|
mainSilentThresholdSeconds: number;
|
|
54
53
|
subAgentSilentThresholdSeconds: number;
|
|
55
54
|
subAgentRunningThresholdSeconds: number;
|
|
56
|
-
cooldownSeconds: number;
|
|
57
55
|
staggerSeconds: number;
|
|
58
56
|
activeHubTaskStatus: string | null;
|
|
59
57
|
now: Date;
|
|
@@ -92,24 +90,8 @@ export class NotifySilentLiveSessionsUseCase {
|
|
|
92
90
|
`Silent live session notification: ${candidates.length} candidate(s) of ${interactiveSessions.length} interactive session(s).`,
|
|
93
91
|
);
|
|
94
92
|
|
|
95
|
-
const nowEpochSeconds = Math.floor(params.now.getTime() / 1000);
|
|
96
93
|
let sentCount = 0;
|
|
97
94
|
for (const candidate of candidates) {
|
|
98
|
-
const lastNotifiedEpochSeconds =
|
|
99
|
-
await this.notificationRepository.getLastNotifiedEpochSeconds(
|
|
100
|
-
candidate.sessionName,
|
|
101
|
-
);
|
|
102
|
-
if (
|
|
103
|
-
lastNotifiedEpochSeconds !== null &&
|
|
104
|
-
nowEpochSeconds - lastNotifiedEpochSeconds < params.cooldownSeconds
|
|
105
|
-
) {
|
|
106
|
-
console.log(
|
|
107
|
-
`Skipping ${candidate.sessionName}: notified ${
|
|
108
|
-
nowEpochSeconds - lastNotifiedEpochSeconds
|
|
109
|
-
} seconds ago, within cooldown ${params.cooldownSeconds} seconds.`,
|
|
110
|
-
);
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
95
|
if (
|
|
114
96
|
!(await this.isHubTaskActive(
|
|
115
97
|
candidate.sessionName,
|
|
@@ -125,10 +107,6 @@ export class NotifySilentLiveSessionsUseCase {
|
|
|
125
107
|
candidate.sessionName,
|
|
126
108
|
candidate.message,
|
|
127
109
|
);
|
|
128
|
-
await this.notificationRepository.setLastNotifiedEpochSeconds(
|
|
129
|
-
candidate.sessionName,
|
|
130
|
-
nowEpochSeconds,
|
|
131
|
-
);
|
|
132
110
|
sentCount += 1;
|
|
133
111
|
console.log(`Notified ${candidate.sessionName}.`);
|
|
134
112
|
}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
export interface SilentSessionNotificationRepository {
|
|
2
|
-
getLastNotifiedEpochSeconds: (sessionName: string) => Promise<number | null>;
|
|
3
|
-
setLastNotifiedEpochSeconds: (
|
|
4
|
-
sessionName: string,
|
|
5
|
-
epochSeconds: number,
|
|
6
|
-
) => Promise<void>;
|
|
7
2
|
sendSelfCheckNotification: (
|
|
8
3
|
sessionName: string,
|
|
9
4
|
message: string,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AAkCA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AAkCA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAiD3D,qBAAa,kCAAkC;IAC7C,MAAM,GACJ,gBAAgB,MAAM,EACtB,UAAU,OAAO,KAChB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,EAAE,IAAI,EAAE,CAAC;KACzB,GAAG,IAAI,CAAC,CAmiBP;CACH"}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { LocalCommandRunner } from '../../../domain/usecases/adapter-interfaces/LocalCommandRunner';
|
|
2
2
|
import { ProcessEnvironReader } from '../../../domain/usecases/adapter-interfaces/ProcessEnvironReader';
|
|
3
3
|
import { HubTaskStatusResolver } from '../../../domain/usecases/NotifySilentLiveSessionsUseCase';
|
|
4
|
-
import { LocalStorageCacheRepository } from '../../repositories/LocalStorageCacheRepository';
|
|
5
4
|
import { SilentSessionMessageTemplates } from '../../repositories/ConfigurableSilentSessionMessageComposer';
|
|
6
5
|
export type NotifySilentTmuxSessionsParams = {
|
|
7
6
|
enabled: boolean;
|
|
8
7
|
localCommandRunner: LocalCommandRunner;
|
|
9
8
|
processEnvironReader?: ProcessEnvironReader;
|
|
10
|
-
cacheRepository: Pick<LocalStorageCacheRepository, 'getLatest' | 'set'>;
|
|
11
9
|
ownerCallMarker: string | null;
|
|
12
10
|
subAgentOutputRootDirectory: string | null;
|
|
13
11
|
subAgentProcessMatchPattern: string | null;
|
|
@@ -15,7 +13,6 @@ export type NotifySilentTmuxSessionsParams = {
|
|
|
15
13
|
mainSilentThresholdSeconds: number;
|
|
16
14
|
subAgentSilentThresholdSeconds: number;
|
|
17
15
|
subAgentRunningThresholdSeconds: number;
|
|
18
|
-
cooldownSeconds: number;
|
|
19
16
|
staggerSeconds: number;
|
|
20
17
|
activeHubTaskStatus: string | null;
|
|
21
18
|
hubTaskStatusResolver: HubTaskStatusResolver | null;
|
|
@@ -27,7 +24,6 @@ export declare const DEFAULT_NOTIFY_SILENT_TMUX_SESSIONS_PARAMS: {
|
|
|
27
24
|
readonly mainSilentThresholdSeconds: number;
|
|
28
25
|
readonly subAgentSilentThresholdSeconds: number;
|
|
29
26
|
readonly subAgentRunningThresholdSeconds: number;
|
|
30
|
-
readonly cooldownSeconds: number;
|
|
31
27
|
readonly staggerSeconds: 25;
|
|
32
28
|
};
|
|
33
29
|
//# sourceMappingURL=notifySilentTmuxSessions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifySilentTmuxSessions.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gEAAgE,CAAC;AAGpG,OAAO,EAAE,oBAAoB,EAAE,MAAM,kEAAkE,CAAC;AACxG,OAAO,EAEL,qBAAqB,
|
|
1
|
+
{"version":3,"file":"notifySilentTmuxSessions.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gEAAgE,CAAC;AAGpG,OAAO,EAAE,oBAAoB,EAAE,MAAM,kEAAkE,CAAC;AACxG,OAAO,EAEL,qBAAqB,EAKtB,MAAM,0DAA0D,CAAC;AAclE,OAAO,EAEL,6BAA6B,EAC9B,MAAM,6DAA6D,CAAC;AAGrE,MAAM,MAAM,8BAA8B,GAAG;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,+BAA+B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,0BAA0B,EAAE,MAAM,CAAC;IACnC,8BAA8B,EAAE,MAAM,CAAC;IACvC,+BAA+B,EAAE,MAAM,CAAC;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,qBAAqB,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACpD,gBAAgB,EAAE,6BAA6B,CAAC;IAChD,GAAG,EAAE,IAAI,CAAC;CACX,CAAC;AAoCF,eAAO,MAAM,wBAAwB,GACnC,QAAQ,8BAA8B,KACrC,OAAO,CAAC,IAAI,CAwDd,CAAC;AAEF,eAAO,MAAM,0CAA0C;;;;;CAK7C,CAAC"}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import { SilentSessionNotificationRepository } from '../../domain/usecases/adapter-interfaces/SilentSessionNotificationRepository';
|
|
2
2
|
import { LocalCommandRunner } from '../../domain/usecases/adapter-interfaces/LocalCommandRunner';
|
|
3
|
-
import { LocalStorageCacheRepository } from './LocalStorageCacheRepository';
|
|
4
3
|
export declare class TmuxSilentSessionNotificationRepository implements SilentSessionNotificationRepository {
|
|
5
4
|
private readonly localCommandRunner;
|
|
6
|
-
|
|
7
|
-
constructor(localCommandRunner: LocalCommandRunner, cacheRepository: Pick<LocalStorageCacheRepository, 'getLatest' | 'set'>);
|
|
8
|
-
getLastNotifiedEpochSeconds: (sessionName: string) => Promise<number | null>;
|
|
9
|
-
setLastNotifiedEpochSeconds: (sessionName: string, epochSeconds: number) => Promise<void>;
|
|
5
|
+
constructor(localCommandRunner: LocalCommandRunner);
|
|
10
6
|
sendSelfCheckNotification: (sessionName: string, message: string) => Promise<void>;
|
|
11
|
-
private toCacheKey;
|
|
12
7
|
}
|
|
13
8
|
//# sourceMappingURL=TmuxSilentSessionNotificationRepository.d.ts.map
|