github-issue-tower-defence-management 1.117.7 → 1.117.9
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 +5 -3
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +14 -2
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js +7 -2
- package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js.map +1 -1
- package/bin/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.js +128 -0
- package/bin/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.js.map +1 -0
- package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js +3 -0
- package/bin/adapter/repositories/issue/GraphqlProjectItemRepository.js.map +1 -1
- package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js +17 -5
- package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js.map +1 -1
- package/bin/domain/usecases/adapter-interfaces/SilentSessionCandidateStateRepository.js +3 -0
- package/bin/domain/usecases/adapter-interfaces/SilentSessionCandidateStateRepository.js.map +1 -0
- package/package.json +1 -1
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +11 -0
- package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.test.ts +37 -3
- package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts +14 -0
- package/src/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.test.ts +201 -0
- package/src/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.ts +115 -0
- package/src/adapter/repositories/issue/GraphqlProjectItemRepository.test.ts +30 -0
- package/src/adapter/repositories/issue/GraphqlProjectItemRepository.ts +4 -1
- package/src/domain/usecases/NotifySilentLiveSessionsUseCase.test.ts +149 -26
- package/src/domain/usecases/NotifySilentLiveSessionsUseCase.ts +24 -4
- package/src/domain/usecases/adapter-interfaces/SilentSessionCandidateStateRepository.ts +10 -0
- package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts +3 -0
- package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts.map +1 -1
- package/types/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.d.ts +18 -0
- package/types/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.d.ts.map +1 -0
- package/types/adapter/repositories/issue/GraphqlProjectItemRepository.d.ts.map +1 -1
- package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts +5 -1
- package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts.map +1 -1
- package/types/domain/usecases/adapter-interfaces/SilentSessionCandidateStateRepository.d.ts +11 -0
- package/types/domain/usecases/adapter-interfaces/SilentSessionCandidateStateRepository.d.ts.map +1 -0
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
|
|
8
8
|
DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
|
|
9
9
|
DEFAULT_NOTIFICATION_STAGGER_SECONDS,
|
|
10
|
+
DEFAULT_CANDIDATE_DEBOUNCE_RECENCY_WINDOW_SECONDS,
|
|
10
11
|
} from './NotifySilentLiveSessionsUseCase';
|
|
11
12
|
import { Issue } from '../entities/Issue';
|
|
12
13
|
import { LiveSessionProcessSnapshotProvider } from './adapter-interfaces/LiveSessionProcessSnapshotProvider';
|
|
@@ -15,6 +16,7 @@ import { SessionOutputActivityRepository } from './adapter-interfaces/SessionOut
|
|
|
15
16
|
import { SessionSubAgentActivityRepository } from './adapter-interfaces/SessionSubAgentActivityRepository';
|
|
16
17
|
import { OwnerCallStatusProvider } from './adapter-interfaces/OwnerCallStatusProvider';
|
|
17
18
|
import { SilentSessionNotificationRepository } from './adapter-interfaces/SilentSessionNotificationRepository';
|
|
19
|
+
import { SilentSessionCandidateStateRepository } from './adapter-interfaces/SilentSessionCandidateStateRepository';
|
|
18
20
|
import { SilentSessionMessageComposer } from './adapter-interfaces/SilentSessionMessageComposer';
|
|
19
21
|
import { Sleeper } from './adapter-interfaces/Sleeper';
|
|
20
22
|
import { SubAgentActivity } from '../entities/LiveSessionActivitySnapshot';
|
|
@@ -26,6 +28,12 @@ type Mocked<T> = jest.Mocked<T> & jest.MockedObject<T>;
|
|
|
26
28
|
const MAIN_STALLED_SECTION = 'MAIN_STALLED_SECTION';
|
|
27
29
|
const SUBAGENT_SECTION = 'SUBAGENT_SECTION';
|
|
28
30
|
|
|
31
|
+
class EveryNameRecentSet extends Set<string> {
|
|
32
|
+
override has = (): boolean => true;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const everyNameRecentSet = (): Set<string> => new EveryNameRecentSet();
|
|
36
|
+
|
|
29
37
|
describe('NotifySilentLiveSessionsUseCase', () => {
|
|
30
38
|
let useCase: NotifySilentLiveSessionsUseCase;
|
|
31
39
|
let mockSnapshotProvider: Mocked<LiveSessionProcessSnapshotProvider>;
|
|
@@ -34,6 +42,7 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
34
42
|
let mockSubAgentActivityRepository: Mocked<SessionSubAgentActivityRepository>;
|
|
35
43
|
let mockOwnerCallStatusProvider: Mocked<OwnerCallStatusProvider>;
|
|
36
44
|
let mockNotificationRepository: Mocked<SilentSessionNotificationRepository>;
|
|
45
|
+
let mockCandidateStateRepository: Mocked<SilentSessionCandidateStateRepository>;
|
|
37
46
|
let mockMessageComposer: Mocked<SilentSessionMessageComposer>;
|
|
38
47
|
let mockSleeper: Mocked<Sleeper>;
|
|
39
48
|
let mockHubTaskStatusResolver: Mocked<HubTaskStatusResolver>;
|
|
@@ -46,12 +55,16 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
46
55
|
'https_//github_com/HiromiShikata/repo/issues/200';
|
|
47
56
|
|
|
48
57
|
const runParams = (
|
|
49
|
-
overrides?: Partial<{
|
|
58
|
+
overrides?: Partial<{
|
|
59
|
+
activeHubTaskStatus: string | null;
|
|
60
|
+
candidateDebounceRecencyWindowSeconds: number;
|
|
61
|
+
}>,
|
|
50
62
|
): {
|
|
51
63
|
mainSilentThresholdSeconds: number;
|
|
52
64
|
subAgentSilentThresholdSeconds: number;
|
|
53
65
|
subAgentRunningThresholdSeconds: number;
|
|
54
66
|
staggerSeconds: number;
|
|
67
|
+
candidateDebounceRecencyWindowSeconds: number;
|
|
55
68
|
activeHubTaskStatus: string | null;
|
|
56
69
|
now: Date;
|
|
57
70
|
} => ({
|
|
@@ -59,6 +72,8 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
59
72
|
subAgentSilentThresholdSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
|
|
60
73
|
subAgentRunningThresholdSeconds: DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
|
|
61
74
|
staggerSeconds: DEFAULT_NOTIFICATION_STAGGER_SECONDS,
|
|
75
|
+
candidateDebounceRecencyWindowSeconds:
|
|
76
|
+
DEFAULT_CANDIDATE_DEBOUNCE_RECENCY_WINDOW_SECONDS,
|
|
62
77
|
activeHubTaskStatus: null,
|
|
63
78
|
now,
|
|
64
79
|
...overrides,
|
|
@@ -132,6 +147,12 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
132
147
|
mockNotificationRepository = {
|
|
133
148
|
sendSelfCheckNotification: jest.fn().mockResolvedValue(undefined),
|
|
134
149
|
};
|
|
150
|
+
mockCandidateStateRepository = {
|
|
151
|
+
loadRecentCandidateSessionNames: jest
|
|
152
|
+
.fn()
|
|
153
|
+
.mockResolvedValue(everyNameRecentSet()),
|
|
154
|
+
saveCandidateSessionNames: jest.fn().mockResolvedValue(undefined),
|
|
155
|
+
};
|
|
135
156
|
mockMessageComposer = {
|
|
136
157
|
composeMainStalledSection: jest
|
|
137
158
|
.fn()
|
|
@@ -151,6 +172,7 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
151
172
|
mockSubAgentActivityRepository,
|
|
152
173
|
mockOwnerCallStatusProvider,
|
|
153
174
|
mockNotificationRepository,
|
|
175
|
+
mockCandidateStateRepository,
|
|
154
176
|
mockMessageComposer,
|
|
155
177
|
mockSleeper,
|
|
156
178
|
mockHubTaskStatusResolver,
|
|
@@ -464,7 +486,7 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
464
486
|
).not.toHaveBeenCalled();
|
|
465
487
|
});
|
|
466
488
|
|
|
467
|
-
it('re-notifies a
|
|
489
|
+
it('re-notifies a persistent stall on every cycle once it has been a candidate in the previous cycle', async () => {
|
|
468
490
|
setupLiveInteractiveSession(GITHUB_SESSION);
|
|
469
491
|
mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
|
|
470
492
|
[
|
|
@@ -490,29 +512,102 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
490
512
|
).toHaveBeenNthCalledWith(2, GITHUB_SESSION, MAIN_STALLED_SECTION);
|
|
491
513
|
});
|
|
492
514
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
515
|
+
describe('two-consecutive-cycle debounce', () => {
|
|
516
|
+
const setupSilentGithubSession = (): void => {
|
|
517
|
+
setupLiveInteractiveSession(GITHUB_SESSION);
|
|
518
|
+
mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
|
|
519
|
+
[
|
|
520
|
+
{
|
|
521
|
+
sessionName: GITHUB_SESSION,
|
|
522
|
+
lastOutputEpochSeconds:
|
|
523
|
+
nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
|
|
524
|
+
},
|
|
525
|
+
],
|
|
526
|
+
);
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
it('does not notify a session that is a candidate in only one cycle', async () => {
|
|
530
|
+
setupSilentGithubSession();
|
|
531
|
+
mockCandidateStateRepository.loadRecentCandidateSessionNames.mockResolvedValue(
|
|
532
|
+
new Set<string>(),
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
await useCase.run(runParams());
|
|
536
|
+
|
|
537
|
+
expect(
|
|
538
|
+
mockNotificationRepository.sendSelfCheckNotification,
|
|
539
|
+
).not.toHaveBeenCalled();
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
it('records the current candidate set so a first-cycle candidate is remembered for the next cycle', async () => {
|
|
543
|
+
setupSilentGithubSession();
|
|
544
|
+
mockCandidateStateRepository.loadRecentCandidateSessionNames.mockResolvedValue(
|
|
545
|
+
new Set<string>(),
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
await useCase.run(runParams());
|
|
549
|
+
|
|
550
|
+
expect(
|
|
551
|
+
mockCandidateStateRepository.saveCandidateSessionNames,
|
|
552
|
+
).toHaveBeenCalledWith({ sessionNames: [GITHUB_SESSION], now });
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
it('notifies a session that is a candidate in two consecutive cycles on the second cycle', async () => {
|
|
556
|
+
setupSilentGithubSession();
|
|
557
|
+
const previousCandidates = new Set<string>();
|
|
558
|
+
mockCandidateStateRepository.loadRecentCandidateSessionNames.mockImplementation(
|
|
559
|
+
async () => new Set(previousCandidates),
|
|
560
|
+
);
|
|
561
|
+
mockCandidateStateRepository.saveCandidateSessionNames.mockImplementation(
|
|
562
|
+
async ({ sessionNames }) => {
|
|
563
|
+
previousCandidates.clear();
|
|
564
|
+
for (const sessionName of sessionNames) {
|
|
565
|
+
previousCandidates.add(sessionName);
|
|
566
|
+
}
|
|
501
567
|
},
|
|
502
|
-
|
|
503
|
-
);
|
|
568
|
+
);
|
|
504
569
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
570
|
+
await useCase.run(runParams());
|
|
571
|
+
expect(
|
|
572
|
+
mockNotificationRepository.sendSelfCheckNotification,
|
|
573
|
+
).not.toHaveBeenCalled();
|
|
508
574
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
575
|
+
await useCase.run(runParams());
|
|
576
|
+
expect(
|
|
577
|
+
mockNotificationRepository.sendSelfCheckNotification,
|
|
578
|
+
).toHaveBeenCalledTimes(1);
|
|
579
|
+
expect(
|
|
580
|
+
mockNotificationRepository.sendSelfCheckNotification,
|
|
581
|
+
).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
it('suppresses the owner-reply-race candidate that was not a candidate in the previous cycle', async () => {
|
|
585
|
+
setupSilentGithubSession();
|
|
586
|
+
mockCandidateStateRepository.loadRecentCandidateSessionNames.mockResolvedValue(
|
|
587
|
+
new Set<string>(),
|
|
588
|
+
);
|
|
589
|
+
|
|
590
|
+
await useCase.run(runParams());
|
|
591
|
+
|
|
592
|
+
expect(
|
|
593
|
+
mockNotificationRepository.sendSelfCheckNotification,
|
|
594
|
+
).not.toHaveBeenCalled();
|
|
595
|
+
expect(
|
|
596
|
+
mockMessageComposer.composeMainStalledSection,
|
|
597
|
+
).toHaveBeenCalledWith(DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS);
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
it('loads the previous candidate set using the configured recency window', async () => {
|
|
601
|
+
setupSilentGithubSession();
|
|
602
|
+
|
|
603
|
+
await useCase.run(
|
|
604
|
+
runParams({ candidateDebounceRecencyWindowSeconds: 900 }),
|
|
605
|
+
);
|
|
606
|
+
|
|
607
|
+
expect(
|
|
608
|
+
mockCandidateStateRepository.loadRecentCandidateSessionNames,
|
|
609
|
+
).toHaveBeenCalledWith({ now, recencyWindowSeconds: 900 });
|
|
610
|
+
});
|
|
516
611
|
});
|
|
517
612
|
|
|
518
613
|
it('sends to multiple sessions sequentially with a stagger delay between sends', async () => {
|
|
@@ -675,11 +770,14 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
675
770
|
warnSpy.mockRestore();
|
|
676
771
|
});
|
|
677
772
|
|
|
678
|
-
it('fails open
|
|
773
|
+
it('fails open without a warning when the hub task is not a resolvable tracked task', async () => {
|
|
679
774
|
setupSilentMainSession(HUB_TASK_SESSION);
|
|
680
775
|
const warnSpy = jest
|
|
681
776
|
.spyOn(console, 'warn')
|
|
682
777
|
.mockImplementation(() => undefined);
|
|
778
|
+
const logSpy = jest
|
|
779
|
+
.spyOn(console, 'log')
|
|
780
|
+
.mockImplementation(() => undefined);
|
|
683
781
|
mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(null);
|
|
684
782
|
|
|
685
783
|
await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
|
|
@@ -687,9 +785,9 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
687
785
|
expect(
|
|
688
786
|
mockNotificationRepository.sendSelfCheckNotification,
|
|
689
787
|
).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
|
|
690
|
-
expect(warnSpy).
|
|
691
|
-
|
|
692
|
-
);
|
|
788
|
+
expect(warnSpy).not.toHaveBeenCalled();
|
|
789
|
+
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('fail-open'));
|
|
790
|
+
logSpy.mockRestore();
|
|
693
791
|
warnSpy.mockRestore();
|
|
694
792
|
});
|
|
695
793
|
|
|
@@ -741,6 +839,31 @@ describe('NotifySilentLiveSessionsUseCase', () => {
|
|
|
741
839
|
).not.toHaveBeenCalled();
|
|
742
840
|
});
|
|
743
841
|
|
|
842
|
+
it('fails open without throwing or warning for a real tmux session-name form whose repository is unresolvable', async () => {
|
|
843
|
+
const REAL_TMUX_SESSION =
|
|
844
|
+
'https_//github_com/example-org/example-repo/issues/2350';
|
|
845
|
+
const CANONICAL_ISSUE_URL =
|
|
846
|
+
'https://github.com/example-org/example-repo/issues/2350';
|
|
847
|
+
setupSilentMainSession(REAL_TMUX_SESSION);
|
|
848
|
+
const warnSpy = jest
|
|
849
|
+
.spyOn(console, 'warn')
|
|
850
|
+
.mockImplementation(() => undefined);
|
|
851
|
+
mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(null);
|
|
852
|
+
|
|
853
|
+
await expect(
|
|
854
|
+
useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS })),
|
|
855
|
+
).resolves.toBeUndefined();
|
|
856
|
+
|
|
857
|
+
expect(mockHubTaskStatusResolver.getIssueByUrl).toHaveBeenCalledWith(
|
|
858
|
+
CANONICAL_ISSUE_URL,
|
|
859
|
+
);
|
|
860
|
+
expect(
|
|
861
|
+
mockNotificationRepository.sendSelfCheckNotification,
|
|
862
|
+
).toHaveBeenCalledWith(REAL_TMUX_SESSION, MAIN_STALLED_SECTION);
|
|
863
|
+
expect(warnSpy).not.toHaveBeenCalled();
|
|
864
|
+
warnSpy.mockRestore();
|
|
865
|
+
});
|
|
866
|
+
|
|
744
867
|
it('parses a clean github.com issue URL session name and rejects non-github names', () => {
|
|
745
868
|
expect(parseHubTaskIssueUrlFromSessionName(HUB_TASK_SESSION)).toBe(
|
|
746
869
|
HUB_TASK_SESSION,
|
|
@@ -7,6 +7,7 @@ import { SessionOutputActivityRepository } from './adapter-interfaces/SessionOut
|
|
|
7
7
|
import { SessionSubAgentActivityRepository } from './adapter-interfaces/SessionSubAgentActivityRepository';
|
|
8
8
|
import { SilentSessionMessageComposer } from './adapter-interfaces/SilentSessionMessageComposer';
|
|
9
9
|
import { SilentSessionNotificationRepository } from './adapter-interfaces/SilentSessionNotificationRepository';
|
|
10
|
+
import { SilentSessionCandidateStateRepository } from './adapter-interfaces/SilentSessionCandidateStateRepository';
|
|
10
11
|
import { Sleeper } from './adapter-interfaces/Sleeper';
|
|
11
12
|
import { IssueRepository } from './adapter-interfaces/IssueRepository';
|
|
12
13
|
import { ResolveInteractiveLiveSessionsUseCase } from './ResolveInteractiveLiveSessionsUseCase';
|
|
@@ -15,6 +16,7 @@ export const DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS = 10 * 60;
|
|
|
15
16
|
export const DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS = 5 * 60;
|
|
16
17
|
export const DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS = 15 * 60;
|
|
17
18
|
export const DEFAULT_NOTIFICATION_STAGGER_SECONDS = 25;
|
|
19
|
+
export const DEFAULT_CANDIDATE_DEBOUNCE_RECENCY_WINDOW_SECONDS = 15 * 60;
|
|
18
20
|
|
|
19
21
|
const GITHUB_ISSUE_OR_PULL_URL_PATTERN =
|
|
20
22
|
/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/(?:issues|pull)\/(\d+)$/;
|
|
@@ -63,6 +65,7 @@ export class NotifySilentLiveSessionsUseCase {
|
|
|
63
65
|
private readonly subAgentActivityRepository: SessionSubAgentActivityRepository,
|
|
64
66
|
private readonly ownerCallStatusProvider: OwnerCallStatusProvider,
|
|
65
67
|
private readonly notificationRepository: SilentSessionNotificationRepository,
|
|
68
|
+
private readonly candidateStateRepository: SilentSessionCandidateStateRepository,
|
|
66
69
|
private readonly messageComposer: SilentSessionMessageComposer,
|
|
67
70
|
private readonly sleeper: Sleeper,
|
|
68
71
|
private readonly hubTaskStatusResolver: HubTaskStatusResolver | null = null,
|
|
@@ -73,6 +76,7 @@ export class NotifySilentLiveSessionsUseCase {
|
|
|
73
76
|
subAgentSilentThresholdSeconds: number;
|
|
74
77
|
subAgentRunningThresholdSeconds: number;
|
|
75
78
|
staggerSeconds: number;
|
|
79
|
+
candidateDebounceRecencyWindowSeconds: number;
|
|
76
80
|
activeHubTaskStatus: string | null;
|
|
77
81
|
now: Date;
|
|
78
82
|
}): Promise<void> => {
|
|
@@ -116,12 +120,28 @@ export class NotifySilentLiveSessionsUseCase {
|
|
|
116
120
|
: 0,
|
|
117
121
|
);
|
|
118
122
|
|
|
123
|
+
const previousCandidateSessionNames =
|
|
124
|
+
await this.candidateStateRepository.loadRecentCandidateSessionNames({
|
|
125
|
+
now: params.now,
|
|
126
|
+
recencyWindowSeconds: params.candidateDebounceRecencyWindowSeconds,
|
|
127
|
+
});
|
|
128
|
+
await this.candidateStateRepository.saveCandidateSessionNames({
|
|
129
|
+
sessionNames: candidates.map((candidate) => candidate.sessionName),
|
|
130
|
+
now: params.now,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const debouncedCandidates = candidates.filter((candidate) =>
|
|
134
|
+
previousCandidateSessionNames.has(candidate.sessionName),
|
|
135
|
+
);
|
|
136
|
+
const suppressedFirstCycleCount =
|
|
137
|
+
candidates.length - debouncedCandidates.length;
|
|
138
|
+
|
|
119
139
|
console.log(
|
|
120
|
-
`Silent live session notification: ${
|
|
140
|
+
`Silent live session notification: ${debouncedCandidates.length} debounced candidate(s) of ${candidates.length} current candidate(s) across ${interactiveSessions.length} interactive session(s); ${suppressedFirstCycleCount} first-cycle candidate(s) deferred until they persist into the next cycle.`,
|
|
121
141
|
);
|
|
122
142
|
|
|
123
143
|
let sentCount = 0;
|
|
124
|
-
for (const candidate of
|
|
144
|
+
for (const candidate of debouncedCandidates) {
|
|
125
145
|
if (
|
|
126
146
|
!(await this.isHubTaskActive(
|
|
127
147
|
candidate.sessionName,
|
|
@@ -157,8 +177,8 @@ export class NotifySilentLiveSessionsUseCase {
|
|
|
157
177
|
const issue =
|
|
158
178
|
await this.hubTaskStatusResolver.getIssueByUrl(hubTaskIssueUrl);
|
|
159
179
|
if (issue === null) {
|
|
160
|
-
console.
|
|
161
|
-
`Hub task ${hubTaskIssueUrl} for session ${sessionName}
|
|
180
|
+
console.log(
|
|
181
|
+
`Hub task ${hubTaskIssueUrl} for session ${sessionName} is not a resolvable tracked task; sending notification (fail-open).`,
|
|
162
182
|
);
|
|
163
183
|
return true;
|
|
164
184
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface SilentSessionCandidateStateRepository {
|
|
2
|
+
loadRecentCandidateSessionNames: (params: {
|
|
3
|
+
now: Date;
|
|
4
|
+
recencyWindowSeconds: number;
|
|
5
|
+
}) => Promise<Set<string>>;
|
|
6
|
+
saveCandidateSessionNames: (params: {
|
|
7
|
+
sessionNames: string[];
|
|
8
|
+
now: Date;
|
|
9
|
+
}) => Promise<void>;
|
|
10
|
+
}
|
|
@@ -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;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,
|
|
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,CA8iBP;CACH"}
|
|
@@ -14,6 +14,8 @@ export type NotifySilentTmuxSessionsParams = {
|
|
|
14
14
|
subAgentSilentThresholdSeconds: number;
|
|
15
15
|
subAgentRunningThresholdSeconds: number;
|
|
16
16
|
staggerSeconds: number;
|
|
17
|
+
candidateDebounceRecencyWindowSeconds: number;
|
|
18
|
+
candidateDebounceStateFilePath: string | null;
|
|
17
19
|
activeHubTaskStatus: string | null;
|
|
18
20
|
hubTaskStatusResolver: HubTaskStatusResolver | null;
|
|
19
21
|
messageTemplates: SilentSessionMessageTemplates;
|
|
@@ -25,5 +27,6 @@ export declare const DEFAULT_NOTIFY_SILENT_TMUX_SESSIONS_PARAMS: {
|
|
|
25
27
|
readonly subAgentSilentThresholdSeconds: number;
|
|
26
28
|
readonly subAgentRunningThresholdSeconds: number;
|
|
27
29
|
readonly staggerSeconds: 25;
|
|
30
|
+
readonly candidateDebounceRecencyWindowSeconds: number;
|
|
28
31
|
};
|
|
29
32
|
//# 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,EAMtB,MAAM,0DAA0D,CAAC;AAclE,OAAO,EAEL,6BAA6B,EAC9B,MAAM,6DAA6D,CAAC;AAIrE,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,qCAAqC,EAAE,MAAM,CAAC;IAC9C,8BAA8B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,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,CAgEd,CAAC;AAEF,eAAO,MAAM,0CAA0C;;;;;;CAO7C,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SilentSessionCandidateStateRepository } from '../../domain/usecases/adapter-interfaces/SilentSessionCandidateStateRepository';
|
|
2
|
+
export declare const DEFAULT_STATE_RETENTION_WINDOW_SECONDS: number;
|
|
3
|
+
export declare class FileSystemSilentSessionCandidateStateRepository implements SilentSessionCandidateStateRepository {
|
|
4
|
+
private readonly stateFilePath;
|
|
5
|
+
private readonly retentionWindowSeconds;
|
|
6
|
+
constructor(stateFilePath?: string, retentionWindowSeconds?: number);
|
|
7
|
+
loadRecentCandidateSessionNames: (params: {
|
|
8
|
+
now: Date;
|
|
9
|
+
recencyWindowSeconds: number;
|
|
10
|
+
}) => Promise<Set<string>>;
|
|
11
|
+
saveCandidateSessionNames: (params: {
|
|
12
|
+
sessionNames: string[];
|
|
13
|
+
now: Date;
|
|
14
|
+
}) => Promise<void>;
|
|
15
|
+
private readEntries;
|
|
16
|
+
private writeEntries;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=FileSystemSilentSessionCandidateStateRepository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSystemSilentSessionCandidateStateRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qCAAqC,EAAE,MAAM,gFAAgF,CAAC;AAUvI,eAAO,MAAM,sCAAsC,QAAU,CAAC;AAO9D,qBAAa,+CAAgD,YAAW,qCAAqC;IAEzG,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,sBAAsB;gBADtB,aAAa,GAAE,MAA+B,EAC9C,sBAAsB,GAAE,MAA+C;IAG1F,+BAA+B,GAAU,QAAQ;QAC/C,GAAG,EAAE,IAAI,CAAC;QACV,oBAAoB,EAAE,MAAM,CAAC;KAC9B,KAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAYtB;IAEF,yBAAyB,GAAU,QAAQ;QACzC,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,GAAG,EAAE,IAAI,CAAC;KACX,KAAG,OAAO,CAAC,IAAI,CAAC,CAqBf;IAEF,OAAO,CAAC,WAAW,CAoCjB;IAEF,OAAO,CAAC,YAAY,CAMlB;CACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphqlProjectItemRepository.d.ts","sourceRoot":"","sources":["../../../../src/adapter/repositories/issue/GraphqlProjectItemRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB,EAAE,MAAM,EAAE,CAAC;IACpC,YAAY,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB,EAAE,CAAC;CACL,CAAC;AACF,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,qCAAqC,MAAM,CAAC;AACzD,eAAO,MAAM,oDAAoD,OAAO,CAAC;AACzE,eAAO,MAAM,sBAAsB,IAAI,CAAC;AACxC,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAC9C,eAAO,MAAM,6BAA6B,QAAQ,CAAC;AACnD,eAAO,MAAM,yBAAyB,SAAS,CAAC;AAsDhD,eAAO,MAAM,sBAAsB,GAAU,CAAC,EAC5C,SAAS,MAAM,OAAO,CAAC,CAAC,CAAC,KACxB,OAAO,CAAC,CAAC,CAyBX,CAAC;AAcF,qBAAa,4BAA6B,SAAQ,oBAAoB;IACpE,WAAW,GACT,WAAW,MAAM,EACjB,OAAO,MAAM,EACb,gBAAgB,MAAM,EACtB,aAAa,MAAM,KAClB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAoE5B;IACF,iBAAiB,GAAU,WAAW,MAAM,KAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAgZnE;IACF,gCAAgC,GAC9B,UAAU,MAAM,KACf,OAAO,CACR;QACE,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,EAAE,CACJ,CAGC;IAEF,oBAAoB,GAClB,OAAO,MAAM,EACb,gBAAgB,MAAM,EACtB,aAAa,MAAM,KAClB,OAAO,CACR;QACE,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,EAAE,CACJ,CAqJC;IACF,qBAAqB,GACnB,UAAU,MAAM,EAChB,YAAY,MAAM,KACjB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"GraphqlProjectItemRepository.d.ts","sourceRoot":"","sources":["../../../../src/adapter/repositories/issue/GraphqlProjectItemRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,12 +5,14 @@ import { SessionOutputActivityRepository } from './adapter-interfaces/SessionOut
|
|
|
5
5
|
import { SessionSubAgentActivityRepository } from './adapter-interfaces/SessionSubAgentActivityRepository';
|
|
6
6
|
import { SilentSessionMessageComposer } from './adapter-interfaces/SilentSessionMessageComposer';
|
|
7
7
|
import { SilentSessionNotificationRepository } from './adapter-interfaces/SilentSessionNotificationRepository';
|
|
8
|
+
import { SilentSessionCandidateStateRepository } from './adapter-interfaces/SilentSessionCandidateStateRepository';
|
|
8
9
|
import { Sleeper } from './adapter-interfaces/Sleeper';
|
|
9
10
|
import { IssueRepository } from './adapter-interfaces/IssueRepository';
|
|
10
11
|
export declare const DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS: number;
|
|
11
12
|
export declare const DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS: number;
|
|
12
13
|
export declare const DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS: number;
|
|
13
14
|
export declare const DEFAULT_NOTIFICATION_STAGGER_SECONDS = 25;
|
|
15
|
+
export declare const DEFAULT_CANDIDATE_DEBOUNCE_RECENCY_WINDOW_SECONDS: number;
|
|
14
16
|
export declare const parseHubTaskIssueUrlFromSessionName: (sessionName: string) => string | null;
|
|
15
17
|
export declare const isGitHubIssueOrPullRequestSessionName: (sessionName: string) => boolean;
|
|
16
18
|
export type HubTaskStatusResolver = Pick<IssueRepository, 'getIssueByUrl'>;
|
|
@@ -21,16 +23,18 @@ export declare class NotifySilentLiveSessionsUseCase {
|
|
|
21
23
|
private readonly subAgentActivityRepository;
|
|
22
24
|
private readonly ownerCallStatusProvider;
|
|
23
25
|
private readonly notificationRepository;
|
|
26
|
+
private readonly candidateStateRepository;
|
|
24
27
|
private readonly messageComposer;
|
|
25
28
|
private readonly sleeper;
|
|
26
29
|
private readonly hubTaskStatusResolver;
|
|
27
30
|
private readonly resolveInteractiveLiveSessions;
|
|
28
|
-
constructor(liveSessionProcessSnapshotProvider: LiveSessionProcessSnapshotProvider, interactiveLiveSessionTranscriptResolver: InteractiveLiveSessionTranscriptResolver, sessionOutputActivityRepository: SessionOutputActivityRepository, subAgentActivityRepository: SessionSubAgentActivityRepository, ownerCallStatusProvider: OwnerCallStatusProvider, notificationRepository: SilentSessionNotificationRepository, messageComposer: SilentSessionMessageComposer, sleeper: Sleeper, hubTaskStatusResolver?: HubTaskStatusResolver | null);
|
|
31
|
+
constructor(liveSessionProcessSnapshotProvider: LiveSessionProcessSnapshotProvider, interactiveLiveSessionTranscriptResolver: InteractiveLiveSessionTranscriptResolver, sessionOutputActivityRepository: SessionOutputActivityRepository, subAgentActivityRepository: SessionSubAgentActivityRepository, ownerCallStatusProvider: OwnerCallStatusProvider, notificationRepository: SilentSessionNotificationRepository, candidateStateRepository: SilentSessionCandidateStateRepository, messageComposer: SilentSessionMessageComposer, sleeper: Sleeper, hubTaskStatusResolver?: HubTaskStatusResolver | null);
|
|
29
32
|
run: (params: {
|
|
30
33
|
mainSilentThresholdSeconds: number;
|
|
31
34
|
subAgentSilentThresholdSeconds: number;
|
|
32
35
|
subAgentRunningThresholdSeconds: number;
|
|
33
36
|
staggerSeconds: number;
|
|
37
|
+
candidateDebounceRecencyWindowSeconds: number;
|
|
34
38
|
activeHubTaskStatus: string | null;
|
|
35
39
|
now: Date;
|
|
36
40
|
}) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotifySilentLiveSessionsUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/NotifySilentLiveSessionsUseCase.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kCAAkC,EAAE,MAAM,yDAAyD,CAAC;AAC7G,OAAO,EAAE,wCAAwC,EAAE,MAAM,+DAA+D,CAAC;AACzH,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,EAAE,+BAA+B,EAAE,MAAM,sDAAsD,CAAC;AACvG,OAAO,EAAE,iCAAiC,EAAE,MAAM,wDAAwD,CAAC;AAC3G,OAAO,EAAE,4BAA4B,EAAE,MAAM,mDAAmD,CAAC;AACjG,OAAO,EAAE,mCAAmC,EAAE,MAAM,0DAA0D,CAAC;AAC/G,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAGvE,eAAO,MAAM,qCAAqC,QAAU,CAAC;AAC7D,eAAO,MAAM,yCAAyC,QAAS,CAAC;AAChE,eAAO,MAAM,0CAA0C,QAAU,CAAC;AAClE,eAAO,MAAM,oCAAoC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"NotifySilentLiveSessionsUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/NotifySilentLiveSessionsUseCase.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kCAAkC,EAAE,MAAM,yDAAyD,CAAC;AAC7G,OAAO,EAAE,wCAAwC,EAAE,MAAM,+DAA+D,CAAC;AACzH,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,EAAE,+BAA+B,EAAE,MAAM,sDAAsD,CAAC;AACvG,OAAO,EAAE,iCAAiC,EAAE,MAAM,wDAAwD,CAAC;AAC3G,OAAO,EAAE,4BAA4B,EAAE,MAAM,mDAAmD,CAAC;AACjG,OAAO,EAAE,mCAAmC,EAAE,MAAM,0DAA0D,CAAC;AAC/G,OAAO,EAAE,qCAAqC,EAAE,MAAM,4DAA4D,CAAC;AACnH,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAGvE,eAAO,MAAM,qCAAqC,QAAU,CAAC;AAC7D,eAAO,MAAM,yCAAyC,QAAS,CAAC;AAChE,eAAO,MAAM,0CAA0C,QAAU,CAAC;AAClE,eAAO,MAAM,oCAAoC,KAAK,CAAC;AACvD,eAAO,MAAM,iDAAiD,QAAU,CAAC;AAQzE,eAAO,MAAM,mCAAmC,GAC9C,aAAa,MAAM,KAClB,MAAM,GAAG,IAWX,CAAC;AAKF,eAAO,MAAM,qCAAqC,GAChD,aAAa,MAAM,KAClB,OACkE,CAAC;AAEtE,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;AAO3E,qBAAa,+BAA+B;IAKxC,OAAO,CAAC,QAAQ,CAAC,kCAAkC;IACnD,OAAO,CAAC,QAAQ,CAAC,wCAAwC;IACzD,OAAO,CAAC,QAAQ,CAAC,+BAA+B;IAChD,OAAO,CAAC,QAAQ,CAAC,0BAA0B;IAC3C,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,wBAAwB;IACzC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAbxC,OAAO,CAAC,QAAQ,CAAC,8BAA8B,CACD;gBAG3B,kCAAkC,EAAE,kCAAkC,EACtE,wCAAwC,EAAE,wCAAwC,EAClF,+BAA+B,EAAE,+BAA+B,EAChE,0BAA0B,EAAE,iCAAiC,EAC7D,uBAAuB,EAAE,uBAAuB,EAChD,sBAAsB,EAAE,mCAAmC,EAC3D,wBAAwB,EAAE,qCAAqC,EAC/D,eAAe,EAAE,4BAA4B,EAC7C,OAAO,EAAE,OAAO,EAChB,qBAAqB,GAAE,qBAAqB,GAAG,IAAW;IAG7E,GAAG,GAAU,QAAQ;QACnB,0BAA0B,EAAE,MAAM,CAAC;QACnC,8BAA8B,EAAE,MAAM,CAAC;QACvC,+BAA+B,EAAE,MAAM,CAAC;QACxC,cAAc,EAAE,MAAM,CAAC;QACvB,qCAAqC,EAAE,MAAM,CAAC;QAC9C,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;QACnC,GAAG,EAAE,IAAI,CAAC;KACX,KAAG,OAAO,CAAC,IAAI,CAAC,CAiFf;IAEF,OAAO,CAAC,eAAe,CAmCrB;IAEF,OAAO,CAAC,gBAAgB,CA+CtB;IAEF,OAAO,CAAC,cAAc,CAqCpB;CACH"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface SilentSessionCandidateStateRepository {
|
|
2
|
+
loadRecentCandidateSessionNames: (params: {
|
|
3
|
+
now: Date;
|
|
4
|
+
recencyWindowSeconds: number;
|
|
5
|
+
}) => Promise<Set<string>>;
|
|
6
|
+
saveCandidateSessionNames: (params: {
|
|
7
|
+
sessionNames: string[];
|
|
8
|
+
now: Date;
|
|
9
|
+
}) => Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=SilentSessionCandidateStateRepository.d.ts.map
|
package/types/domain/usecases/adapter-interfaces/SilentSessionCandidateStateRepository.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SilentSessionCandidateStateRepository.d.ts","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/SilentSessionCandidateStateRepository.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qCAAqC;IACpD,+BAA+B,EAAE,CAAC,MAAM,EAAE;QACxC,GAAG,EAAE,IAAI,CAAC;QACV,oBAAoB,EAAE,MAAM,CAAC;KAC9B,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3B,yBAAyB,EAAE,CAAC,MAAM,EAAE;QAClC,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,GAAG,EAAE,IAAI,CAAC;KACX,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrB"}
|