github-issue-tower-defence-management 1.151.0 → 1.151.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 +15 -0
- package/bin/adapter/entry-points/console/consoleDoneStore.js +19 -1
- package/bin/adapter/entry-points/console/consoleDoneStore.js.map +1 -1
- package/bin/adapter/entry-points/console/consoleOperationApi.js +17 -5
- package/bin/adapter/entry-points/console/consoleOperationApi.js.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-CY96HROQ.js +83 -0
- package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +14 -15
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js +2 -10
- package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js.map +1 -1
- package/bin/adapter/repositories/TranscriptOwnerCallStatusProvider.js +16 -5
- package/bin/adapter/repositories/TranscriptOwnerCallStatusProvider.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/console/consoleDoneStore.test.ts +21 -0
- package/src/adapter/entry-points/console/consoleDoneStore.ts +25 -0
- package/src/adapter/entry-points/console/consoleOperationApi.test.ts +58 -7
- package/src/adapter/entry-points/console/consoleOperationApi.ts +43 -6
- package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.test.ts +79 -1
- package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.ts +20 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.test.tsx +42 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +6 -2
- package/src/adapter/entry-points/console/ui-dist/assets/index-CY96HROQ.js +83 -0
- package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +26 -28
- package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.test.ts +36 -3
- package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts +3 -22
- package/src/adapter/repositories/TranscriptOwnerCallStatusProvider.singleScan.test.ts +88 -0
- package/src/adapter/repositories/TranscriptOwnerCallStatusProvider.ts +22 -11
- package/types/adapter/entry-points/console/consoleDoneStore.d.ts +3 -0
- package/types/adapter/entry-points/console/consoleDoneStore.d.ts.map +1 -1
- package/types/adapter/entry-points/console/consoleOperationApi.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts +2 -2
- package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts.map +1 -1
- package/types/adapter/repositories/TranscriptOwnerCallStatusProvider.d.ts +2 -0
- package/types/adapter/repositories/TranscriptOwnerCallStatusProvider.d.ts.map +1 -1
- package/bin/adapter/entry-points/console/ui-dist/assets/index-UQt5L756.js +0 -83
- package/src/adapter/entry-points/console/ui-dist/assets/index-UQt5L756.js +0 -83
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>TDPM Console</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-CY96HROQ.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-Dihcph6j.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
@@ -24,6 +24,8 @@ import { LocalProcessLiveSessionProcessSnapshotProvider } from '../../repositori
|
|
|
24
24
|
import { ProcFsProcessEnvironReader } from '../../repositories/ProcFsProcessEnvironReader';
|
|
25
25
|
import { FileSystemInteractiveLiveSessionTranscriptResolver } from '../../repositories/FileSystemInteractiveLiveSessionTranscriptResolver';
|
|
26
26
|
import { TranscriptOwnerCallStatusProvider } from '../../repositories/TranscriptOwnerCallStatusProvider';
|
|
27
|
+
import { NoUnansweredOwnerCallStatusProvider } from '../../repositories/NoUnansweredOwnerCallStatusProvider';
|
|
28
|
+
import { OwnerCallStatusProvider } from '../../../domain/usecases/adapter-interfaces/OwnerCallStatusProvider';
|
|
27
29
|
import { UnansweredOwnerCall } from '../../../domain/entities/UnansweredOwnerCall';
|
|
28
30
|
import {
|
|
29
31
|
resetDegeneratedTmuxSessions,
|
|
@@ -638,17 +640,33 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
638
640
|
|
|
639
641
|
const inTmuxNow = new Date();
|
|
640
642
|
|
|
643
|
+
const inTmuxGetuid = process.getuid?.bind(process);
|
|
644
|
+
const ownerCallMarker =
|
|
645
|
+
mergedInput.ownerCallMarker ??
|
|
646
|
+
process.env.TDPM_SILENT_OWNER_CALL_MARKER ??
|
|
647
|
+
null;
|
|
648
|
+
const ownerReplyMarkerDirectory = ownerReplyMarkerDirectoryResolve(
|
|
649
|
+
mergedInput.ownerReplyMarkerDirectory ?? null,
|
|
650
|
+
process.env,
|
|
651
|
+
inTmuxGetuid === undefined ? null : inTmuxGetuid(),
|
|
652
|
+
);
|
|
653
|
+
const transcriptOwnerCallStatusProvider =
|
|
654
|
+
ownerCallMarker !== null && ownerCallMarker.length > 0
|
|
655
|
+
? new TranscriptOwnerCallStatusProvider(
|
|
656
|
+
ownerCallMarker,
|
|
657
|
+
ownerReplyMarkerDirectory,
|
|
658
|
+
)
|
|
659
|
+
: null;
|
|
660
|
+
const ownerCallStatusProvider: OwnerCallStatusProvider =
|
|
661
|
+
transcriptOwnerCallStatusProvider ??
|
|
662
|
+
new NoUnansweredOwnerCallStatusProvider();
|
|
663
|
+
|
|
641
664
|
let unansweredCallsByTmuxSessionName = new Map<
|
|
642
665
|
string,
|
|
643
666
|
UnansweredOwnerCall[]
|
|
644
667
|
>();
|
|
645
668
|
try {
|
|
646
|
-
|
|
647
|
-
mergedInput.ownerCallMarker ??
|
|
648
|
-
process.env.TDPM_SILENT_OWNER_CALL_MARKER ??
|
|
649
|
-
null;
|
|
650
|
-
if (inTmuxOwnerCallMarker !== null) {
|
|
651
|
-
const inTmuxGetuid = process.getuid?.bind(process);
|
|
669
|
+
if (transcriptOwnerCallStatusProvider !== null) {
|
|
652
670
|
unansweredCallsByTmuxSessionName =
|
|
653
671
|
await resolveUnansweredOwnerCallsByTmuxSessionName({
|
|
654
672
|
liveSessionProcessSnapshotProvider:
|
|
@@ -659,14 +677,7 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
659
677
|
interactiveLiveSessionTranscriptResolver:
|
|
660
678
|
new FileSystemInteractiveLiveSessionTranscriptResolver(),
|
|
661
679
|
unansweredOwnerCallListProvider:
|
|
662
|
-
|
|
663
|
-
inTmuxOwnerCallMarker,
|
|
664
|
-
ownerReplyMarkerDirectoryResolve(
|
|
665
|
-
mergedInput.ownerReplyMarkerDirectory ?? null,
|
|
666
|
-
process.env,
|
|
667
|
-
inTmuxGetuid === undefined ? null : inTmuxGetuid(),
|
|
668
|
-
),
|
|
669
|
-
),
|
|
680
|
+
transcriptOwnerCallStatusProvider,
|
|
670
681
|
});
|
|
671
682
|
}
|
|
672
683
|
} catch (error) {
|
|
@@ -773,23 +784,11 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
773
784
|
mergedInput.subAgentProcessMatchPattern ??
|
|
774
785
|
process.env.TDPM_SUBAGENT_PROCESS_MATCH_PATTERN ??
|
|
775
786
|
null;
|
|
776
|
-
const ownerCallMarker =
|
|
777
|
-
mergedInput.ownerCallMarker ??
|
|
778
|
-
process.env.TDPM_SILENT_OWNER_CALL_MARKER ??
|
|
779
|
-
null;
|
|
780
787
|
const subAgentTranscriptRootDirectory =
|
|
781
788
|
mergedInput.subAgentTranscriptRootDirectory ??
|
|
782
789
|
process.env.TDPM_SUBAGENT_TRANSCRIPT_ROOT_DIRECTORY ??
|
|
783
790
|
null;
|
|
784
791
|
const getuid = process.getuid?.bind(process);
|
|
785
|
-
// The status line writes the reply time it renders here, and the owner sees only that
|
|
786
|
-
// status line, so reading the same file keeps the reminder decision and the owner's view
|
|
787
|
-
// of it from disagreeing.
|
|
788
|
-
const ownerReplyMarkerDirectory = ownerReplyMarkerDirectoryResolve(
|
|
789
|
-
mergedInput.ownerReplyMarkerDirectory ?? null,
|
|
790
|
-
process.env,
|
|
791
|
-
getuid === undefined ? null : getuid(),
|
|
792
|
-
);
|
|
793
792
|
const subAgentRuntimeRootDirectory =
|
|
794
793
|
mergedInput.subAgentRuntimeRootDirectory ??
|
|
795
794
|
process.env.TDPM_SUBAGENT_RUNTIME_ROOT_DIRECTORY ??
|
|
@@ -799,8 +798,7 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
799
798
|
await notifySilentTmuxSessions({
|
|
800
799
|
enabled: silentNotificationEnabled,
|
|
801
800
|
localCommandRunner: nodeLocalCommandRunner,
|
|
802
|
-
|
|
803
|
-
ownerReplyMarkerDirectory,
|
|
801
|
+
ownerCallStatusProvider,
|
|
804
802
|
subAgentOutputRootDirectory,
|
|
805
803
|
subAgentProcessMatchPattern,
|
|
806
804
|
subAgentTranscriptRootDirectory,
|
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
notifySilentTmuxSessions,
|
|
11
11
|
DEFAULT_NOTIFY_SILENT_TMUX_SESSIONS_PARAMS,
|
|
12
12
|
} from './notifySilentTmuxSessions';
|
|
13
|
+
import { OwnerCallStatusProvider } from '../../../domain/usecases/adapter-interfaces/OwnerCallStatusProvider';
|
|
14
|
+
import { NoUnansweredOwnerCallStatusProvider } from '../../repositories/NoUnansweredOwnerCallStatusProvider';
|
|
15
|
+
import { TranscriptOwnerCallStatusProvider } from '../../repositories/TranscriptOwnerCallStatusProvider';
|
|
13
16
|
|
|
14
17
|
const NOW = new Date('2026-06-26T00:00:00.000Z');
|
|
15
18
|
const NOW_EPOCH_SECONDS = Math.floor(NOW.getTime() / 1000);
|
|
@@ -135,7 +138,7 @@ describe('notifySilentTmuxSessions', () => {
|
|
|
135
138
|
enabled: true,
|
|
136
139
|
localCommandRunner: runner,
|
|
137
140
|
processEnvironReader: makeEnvironReader(),
|
|
138
|
-
|
|
141
|
+
ownerCallStatusProvider: new NoUnansweredOwnerCallStatusProvider(),
|
|
139
142
|
subAgentOutputRootDirectory: null,
|
|
140
143
|
subAgentProcessMatchPattern: null,
|
|
141
144
|
subAgentTranscriptRootDirectory: null,
|
|
@@ -189,6 +192,32 @@ describe('notifySilentTmuxSessions', () => {
|
|
|
189
192
|
expect(secondSendCall?.[1][4]).toContain('No output has been observed for');
|
|
190
193
|
});
|
|
191
194
|
|
|
195
|
+
it('decides from the owner call status provider it was given', async () => {
|
|
196
|
+
silentAssistantTranscript();
|
|
197
|
+
seedPreviousCandidates([SESSION_NAME]);
|
|
198
|
+
const runner = liveSessionRunner();
|
|
199
|
+
const consultedSessionNames: string[] = [];
|
|
200
|
+
const injectedProvider: OwnerCallStatusProvider = {
|
|
201
|
+
listUnansweredOwnerCallEpochSecondsBySessionName: (
|
|
202
|
+
transcriptPathBySessionName: Map<string, string>,
|
|
203
|
+
): Promise<Map<string, number>> => {
|
|
204
|
+
consultedSessionNames.push(...transcriptPathBySessionName.keys());
|
|
205
|
+
return Promise.resolve(new Map([[SESSION_NAME, NOW_EPOCH_SECONDS]]));
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
await notifySilentTmuxSessions({
|
|
210
|
+
...baseParams(runner),
|
|
211
|
+
ownerCallStatusProvider: injectedProvider,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
expect(consultedSessionNames).toContain(SESSION_NAME);
|
|
215
|
+
const sendCall = runner.runCommand.mock.calls.find(
|
|
216
|
+
(call) => call[0] === 'tmux' && call[1][0] === 'send-keys',
|
|
217
|
+
);
|
|
218
|
+
expect(sendCall).toBeUndefined();
|
|
219
|
+
});
|
|
220
|
+
|
|
192
221
|
it('does not notify a silent github-named live session on its first candidate cycle', async () => {
|
|
193
222
|
silentAssistantTranscript();
|
|
194
223
|
const runner = liveSessionRunner();
|
|
@@ -323,7 +352,9 @@ describe('notifySilentTmuxSessions', () => {
|
|
|
323
352
|
|
|
324
353
|
await notifySilentTmuxSessions({
|
|
325
354
|
...baseParams(runner),
|
|
326
|
-
|
|
355
|
+
ownerCallStatusProvider: new TranscriptOwnerCallStatusProvider(
|
|
356
|
+
'<<OWNER_CALL>>',
|
|
357
|
+
),
|
|
327
358
|
});
|
|
328
359
|
|
|
329
360
|
const sendCall = runner.runCommand.mock.calls.find(
|
|
@@ -359,7 +390,9 @@ describe('notifySilentTmuxSessions', () => {
|
|
|
359
390
|
|
|
360
391
|
await notifySilentTmuxSessions({
|
|
361
392
|
...baseParams(runner),
|
|
362
|
-
|
|
393
|
+
ownerCallStatusProvider: new TranscriptOwnerCallStatusProvider(
|
|
394
|
+
'<<OWNER_CALL>>',
|
|
395
|
+
),
|
|
363
396
|
});
|
|
364
397
|
|
|
365
398
|
const sendCall = runner.runCommand.mock.calls.find(
|
|
@@ -23,8 +23,6 @@ import {
|
|
|
23
23
|
DEFAULT_SUBMIT_PUSH_OUT_WAIT_MILLISECONDS,
|
|
24
24
|
TmuxSilentSessionNotificationRepository,
|
|
25
25
|
} from '../../repositories/TmuxSilentSessionNotificationRepository';
|
|
26
|
-
import { NoUnansweredOwnerCallStatusProvider } from '../../repositories/NoUnansweredOwnerCallStatusProvider';
|
|
27
|
-
import { TranscriptOwnerCallStatusProvider } from '../../repositories/TranscriptOwnerCallStatusProvider';
|
|
28
26
|
import { TranscriptRefusalTailStatusProvider } from '../../repositories/TranscriptRefusalTailStatusProvider';
|
|
29
27
|
import { ProcessListSessionSubAgentActivityRepository } from '../../repositories/ProcessListSessionSubAgentActivityRepository';
|
|
30
28
|
import { TranscriptSessionSubAgentActivityRepository } from '../../repositories/TranscriptSessionSubAgentActivityRepository';
|
|
@@ -44,8 +42,7 @@ export type NotifySilentTmuxSessionsParams = {
|
|
|
44
42
|
enabled: boolean;
|
|
45
43
|
localCommandRunner: LocalCommandRunner;
|
|
46
44
|
processEnvironReader?: ProcessEnvironReader;
|
|
47
|
-
|
|
48
|
-
ownerReplyMarkerDirectory?: string | null;
|
|
45
|
+
ownerCallStatusProvider: OwnerCallStatusProvider;
|
|
49
46
|
subAgentOutputRootDirectory: string | null;
|
|
50
47
|
subAgentProcessMatchPattern: string | null;
|
|
51
48
|
subAgentTranscriptRootDirectory: string | null;
|
|
@@ -66,19 +63,6 @@ export type NotifySilentTmuxSessionsParams = {
|
|
|
66
63
|
now: Date;
|
|
67
64
|
};
|
|
68
65
|
|
|
69
|
-
const createOwnerCallStatusProvider = (
|
|
70
|
-
ownerCallMarker: string | null,
|
|
71
|
-
ownerReplyMarkerDirectory: string | null,
|
|
72
|
-
): OwnerCallStatusProvider => {
|
|
73
|
-
if (ownerCallMarker !== null && ownerCallMarker.length > 0) {
|
|
74
|
-
return new TranscriptOwnerCallStatusProvider(
|
|
75
|
-
ownerCallMarker,
|
|
76
|
-
ownerReplyMarkerDirectory,
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
return new NoUnansweredOwnerCallStatusProvider();
|
|
80
|
-
};
|
|
81
|
-
|
|
82
66
|
const createSubAgentActivityRepository = (
|
|
83
67
|
subAgentTranscriptRootDirectory: string | null,
|
|
84
68
|
subAgentRuntimeRootDirectory: string | null,
|
|
@@ -114,7 +98,7 @@ export const notifySilentTmuxSessions = async (
|
|
|
114
98
|
enabled,
|
|
115
99
|
localCommandRunner,
|
|
116
100
|
processEnvironReader,
|
|
117
|
-
|
|
101
|
+
ownerCallStatusProvider,
|
|
118
102
|
subAgentOutputRootDirectory,
|
|
119
103
|
subAgentProcessMatchPattern,
|
|
120
104
|
subAgentTranscriptRootDirectory,
|
|
@@ -159,10 +143,7 @@ export const notifySilentTmuxSessions = async (
|
|
|
159
143
|
localCommandRunner,
|
|
160
144
|
now,
|
|
161
145
|
),
|
|
162
|
-
|
|
163
|
-
ownerCallMarker,
|
|
164
|
-
params.ownerReplyMarkerDirectory ?? null,
|
|
165
|
-
),
|
|
146
|
+
ownerCallStatusProvider,
|
|
166
147
|
new TmuxSilentSessionNotificationRepository(
|
|
167
148
|
localCommandRunner,
|
|
168
149
|
new RealSleeper(),
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as os from 'os';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { TranscriptOwnerCallStatusProvider } from './TranscriptOwnerCallStatusProvider';
|
|
5
|
+
|
|
6
|
+
describe('TranscriptOwnerCallStatusProvider single transcript scan', () => {
|
|
7
|
+
let rootDirectory: string;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
rootDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'single-scan-'));
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
fs.rmSync(rootDirectory, { force: true, recursive: true });
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const writeTranscript = (fileName: string, lines: object[]): string => {
|
|
18
|
+
const filePath = path.join(rootDirectory, fileName);
|
|
19
|
+
fs.writeFileSync(
|
|
20
|
+
filePath,
|
|
21
|
+
lines.map((line) => JSON.stringify(line)).join('\n'),
|
|
22
|
+
'utf8',
|
|
23
|
+
);
|
|
24
|
+
return filePath;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const assistantWithMarker = (timestamp: string): object => ({
|
|
28
|
+
type: 'assistant',
|
|
29
|
+
timestamp,
|
|
30
|
+
message: {
|
|
31
|
+
role: 'assistant',
|
|
32
|
+
stop_reason: 'end_turn',
|
|
33
|
+
content: [
|
|
34
|
+
{ type: 'text', text: 'Waiting <<OWNER_CALL>> please decide.' },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const epochSecondsOf = (timestamp: string): number =>
|
|
40
|
+
Math.floor(Date.parse(timestamp) / 1000);
|
|
41
|
+
|
|
42
|
+
it('serves the reminder path and the listing path from one read of the transcript', async () => {
|
|
43
|
+
const transcriptPath = writeTranscript('session.jsonl', [
|
|
44
|
+
assistantWithMarker('2026-08-13T10:00:00.000Z'),
|
|
45
|
+
]);
|
|
46
|
+
const transcriptPathBySessionName = new Map([['session', transcriptPath]]);
|
|
47
|
+
const provider = new TranscriptOwnerCallStatusProvider('<<OWNER_CALL>>');
|
|
48
|
+
|
|
49
|
+
const calls = await provider.listUnansweredOwnerCallsBySessionName(
|
|
50
|
+
transcriptPathBySessionName,
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
writeTranscript('session.jsonl', [
|
|
54
|
+
assistantWithMarker('2026-08-13T11:00:00.000Z'),
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
const epochSeconds =
|
|
58
|
+
await provider.listUnansweredOwnerCallEpochSecondsBySessionName(
|
|
59
|
+
transcriptPathBySessionName,
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
expect(calls.get('session')).toEqual([
|
|
63
|
+
{
|
|
64
|
+
calledAt: '2026-08-13T10:00:00.000Z',
|
|
65
|
+
body: 'Waiting <<OWNER_CALL>> please decide.',
|
|
66
|
+
},
|
|
67
|
+
]);
|
|
68
|
+
expect(epochSeconds.get('session')).toBe(
|
|
69
|
+
epochSecondsOf('2026-08-13T10:00:00.000Z'),
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('scans a transcript that only the reminder path asked for', async () => {
|
|
74
|
+
const transcriptPath = writeTranscript('reminder-only.jsonl', [
|
|
75
|
+
assistantWithMarker('2026-08-13T12:00:00.000Z'),
|
|
76
|
+
]);
|
|
77
|
+
const provider = new TranscriptOwnerCallStatusProvider('<<OWNER_CALL>>');
|
|
78
|
+
|
|
79
|
+
const epochSeconds =
|
|
80
|
+
await provider.listUnansweredOwnerCallEpochSecondsBySessionName(
|
|
81
|
+
new Map([['session', transcriptPath]]),
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
expect(epochSeconds.get('session')).toBe(
|
|
85
|
+
epochSecondsOf('2026-08-13T12:00:00.000Z'),
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
@@ -158,6 +158,11 @@ const isCandidateOwnerCallMarker = (marker: string): boolean =>
|
|
|
158
158
|
export class TranscriptOwnerCallStatusProvider implements OwnerCallStatusProvider {
|
|
159
159
|
private readonly ownerCallMarkerFamily: string[];
|
|
160
160
|
|
|
161
|
+
private readonly transcriptScanByPath = new Map<
|
|
162
|
+
string,
|
|
163
|
+
TranscriptOwnerCallScan | null
|
|
164
|
+
>();
|
|
165
|
+
|
|
161
166
|
constructor(
|
|
162
167
|
ownerCallMarker: string | null,
|
|
163
168
|
private readonly ownerReplyMarkerDirectory: string | null = null,
|
|
@@ -179,10 +184,8 @@ export class TranscriptOwnerCallStatusProvider implements OwnerCallStatusProvide
|
|
|
179
184
|
return unansweredOwnerCallEpochSecondsBySessionName;
|
|
180
185
|
}
|
|
181
186
|
for (const [sessionName, transcriptPath] of transcriptPathBySessionName) {
|
|
182
|
-
const unansweredOwnerCallEpochMs =
|
|
183
|
-
transcriptPath
|
|
184
|
-
this.ownerCallMarkerFamily,
|
|
185
|
-
);
|
|
187
|
+
const unansweredOwnerCallEpochMs =
|
|
188
|
+
this.findUnansweredOwnerCallEpochMs(transcriptPath);
|
|
186
189
|
if (unansweredOwnerCallEpochMs !== null) {
|
|
187
190
|
unansweredOwnerCallEpochSecondsBySessionName.set(
|
|
188
191
|
sessionName,
|
|
@@ -204,10 +207,7 @@ export class TranscriptOwnerCallStatusProvider implements OwnerCallStatusProvide
|
|
|
204
207
|
return unansweredOwnerCallsBySessionName;
|
|
205
208
|
}
|
|
206
209
|
for (const [sessionName, transcriptPath] of transcriptPathBySessionName) {
|
|
207
|
-
const transcript = this.scanTranscript(
|
|
208
|
-
transcriptPath,
|
|
209
|
-
this.ownerCallMarkerFamily,
|
|
210
|
-
);
|
|
210
|
+
const transcript = this.scanTranscript(transcriptPath);
|
|
211
211
|
if (transcript === null) {
|
|
212
212
|
continue;
|
|
213
213
|
}
|
|
@@ -236,8 +236,20 @@ export class TranscriptOwnerCallStatusProvider implements OwnerCallStatusProvide
|
|
|
236
236
|
|
|
237
237
|
private scanTranscript = (
|
|
238
238
|
transcriptPath: string,
|
|
239
|
-
markerFamily: string[],
|
|
240
239
|
): TranscriptOwnerCallScan | null => {
|
|
240
|
+
const alreadyScanned = this.transcriptScanByPath.get(transcriptPath);
|
|
241
|
+
if (alreadyScanned !== undefined) {
|
|
242
|
+
return alreadyScanned;
|
|
243
|
+
}
|
|
244
|
+
const scan = this.readTranscriptScan(transcriptPath);
|
|
245
|
+
this.transcriptScanByPath.set(transcriptPath, scan);
|
|
246
|
+
return scan;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
private readTranscriptScan = (
|
|
250
|
+
transcriptPath: string,
|
|
251
|
+
): TranscriptOwnerCallScan | null => {
|
|
252
|
+
const markerFamily = this.ownerCallMarkerFamily;
|
|
241
253
|
let content: string;
|
|
242
254
|
try {
|
|
243
255
|
content = fs.readFileSync(transcriptPath, 'utf8');
|
|
@@ -311,9 +323,8 @@ export class TranscriptOwnerCallStatusProvider implements OwnerCallStatusProvide
|
|
|
311
323
|
|
|
312
324
|
private findUnansweredOwnerCallEpochMs = (
|
|
313
325
|
transcriptPath: string,
|
|
314
|
-
markerFamily: string[],
|
|
315
326
|
): number | null => {
|
|
316
|
-
const transcript = this.scanTranscript(transcriptPath
|
|
327
|
+
const transcript = this.scanTranscript(transcriptPath);
|
|
317
328
|
if (transcript === null) {
|
|
318
329
|
return null;
|
|
319
330
|
}
|
|
@@ -6,6 +6,9 @@ export declare const doneFilePathForTab: (consoleDataOutputDir: string, pjcode:
|
|
|
6
6
|
export declare const readDoneProjectItemIds: (consoleDataOutputDir: string, pjcode: string, tab: string) => string[];
|
|
7
7
|
export declare const recordDoneProjectItemId: (consoleDataOutputDir: string, pjcode: string, tab: string, projectItemId: string) => void;
|
|
8
8
|
export declare const CONSOLE_DONE_TAB_NAMES: string[];
|
|
9
|
+
export declare const CONSOLE_DONE_STATUS_SELECTED_TAB_NAMES: string[];
|
|
10
|
+
export declare const CONSOLE_DONE_STORY_SELECTED_TAB_NAMES: string[];
|
|
11
|
+
export declare const recordDoneProjectItemIdForTabs: (consoleDataOutputDir: string, pjcode: string, projectItemId: string, tabNames: string[]) => void;
|
|
9
12
|
export declare const recordDoneProjectItemIdAcrossTabs: (consoleDataOutputDir: string, pjcode: string, projectItemId: string) => void;
|
|
10
13
|
export declare const resetDoneProjectItemIds: (consoleDataOutputDir: string, pjcode: string, tab: string) => void;
|
|
11
14
|
export declare const resetDoneProjectItemIdsAcrossTabs: (consoleDataOutputDir: string, pjcode: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consoleDoneStore.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/consoleDoneStore.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,eAAe,CAAC;AAEnD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AAqBF,eAAO,MAAM,kBAAkB,GAC7B,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,EACd,KAAK,MAAM,KACV,MACmE,CAAC;AAYvE,eAAO,MAAM,sBAAsB,GACjC,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,EACd,KAAK,MAAM,KACV,MAAM,EASR,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,EACd,KAAK,MAAM,EACX,eAAe,MAAM,KACpB,IAaF,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,MAAM,EAS1C,CAAC;AAEF,eAAO,MAAM,iCAAiC,GAC5C,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,EACd,eAAe,MAAM,KACpB,IAIF,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,EACd,KAAK,MAAM,KACV,IAGF,CAAC;AAEF,eAAO,MAAM,iCAAiC,GAC5C,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,KACb,IAIF,CAAC"}
|
|
1
|
+
{"version":3,"file":"consoleDoneStore.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/consoleDoneStore.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,eAAe,CAAC;AAEnD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AAqBF,eAAO,MAAM,kBAAkB,GAC7B,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,EACd,KAAK,MAAM,KACV,MACmE,CAAC;AAYvE,eAAO,MAAM,sBAAsB,GACjC,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,EACd,KAAK,MAAM,KACV,MAAM,EASR,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,EACd,KAAK,MAAM,EACX,eAAe,MAAM,KACpB,IAaF,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,MAAM,EAS1C,CAAC;AAEF,eAAO,MAAM,sCAAsC,EAAE,MAAM,EAO1D,CAAC;AAEF,eAAO,MAAM,qCAAqC,EAAE,MAAM,EAGzD,CAAC;AAEF,eAAO,MAAM,8BAA8B,GACzC,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,EACd,eAAe,MAAM,EACrB,UAAU,MAAM,EAAE,KACjB,IAIF,CAAC;AAEF,eAAO,MAAM,iCAAiC,GAC5C,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,EACd,eAAe,MAAM,KACpB,IAIF,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,EACd,KAAK,MAAM,KACV,IAGF,CAAC;AAEF,eAAO,MAAM,iCAAiC,GAC5C,sBAAsB,MAAM,EAC5B,QAAQ,MAAM,KACb,IAIF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consoleOperationApi.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/consoleOperationApi.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EAEhB,MAAM,6DAA6D,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,uEAAuE,CAAC;AAClH,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"consoleOperationApi.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/consoleOperationApi.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EAEhB,MAAM,6DAA6D,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,uEAAuE,CAAC;AAClH,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAU3D,eAAO,MAAM,8BAA8B,uBAAuB,CAAC;AACnE,eAAO,MAAM,4BAA4B,qBAAqB,CAAC;AAC/D,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,CACnC,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;AAE3C,MAAM,MAAM,sBAAsB,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;AAEjE,MAAM,MAAM,8BAA8B,GAAG,CAC3C,qBAAqB,EAAE,MAAM,KAC1B,eAAe,CAAC;AAErB,MAAM,MAAM,uBAAuB,GAAG;IACpC,sBAAsB,EAAE,8BAA8B,CAAC;IACvD,cAAc,EAAE,sBAAsB,CAAC;IACvC,kBAAkB,EAAE,sBAAsB,CAAC;IAC3C,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,yBAAyB,EAAE,yBAAyB,GAAG,IAAI,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AA6MF,eAAO,MAAM,YAAY,GACvB,SAAS,uBAAuB,EAChC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,wBAAwB,CA6HlC,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,SAAS,uBAAuB,EAChC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,wBAAwB,CA6FlC,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,SAAS,uBAAuB,EAChC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,wBAAwB,CA8BlC,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,SAAS,uBAAuB,EAChC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,wBAAwB,CA2ClC,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,SAAS,uBAAuB,EAChC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,wBAAwB,CA6BlC,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,SAAS,uBAAuB,EAChC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,wBAAwB,CAiClC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AAoDA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAqD3D,qBAAa,kCAAkC;IAC7C,MAAM,GACJ,gBAAgB,MAAM,EACtB,UAAU,OAAO,EACjB,6BAA4B,MAAM,EAAE,GAAG,IAAW,KACjD,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,CAyyBP;CACH"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LocalCommandRunner } from '../../../domain/usecases/adapter-interfaces/LocalCommandRunner';
|
|
2
|
+
import { OwnerCallStatusProvider } from '../../../domain/usecases/adapter-interfaces/OwnerCallStatusProvider';
|
|
2
3
|
import { ProcessEnvironReader } from '../../../domain/usecases/adapter-interfaces/ProcessEnvironReader';
|
|
3
4
|
import { HubTaskStatusResolver } from '../../../domain/usecases/NotifySilentLiveSessionsUseCase';
|
|
4
5
|
import { SilentSessionMessageTemplates } from '../../repositories/ConfigurableSilentSessionMessageComposer';
|
|
@@ -6,8 +7,7 @@ export type NotifySilentTmuxSessionsParams = {
|
|
|
6
7
|
enabled: boolean;
|
|
7
8
|
localCommandRunner: LocalCommandRunner;
|
|
8
9
|
processEnvironReader?: ProcessEnvironReader;
|
|
9
|
-
|
|
10
|
-
ownerReplyMarkerDirectory?: string | null;
|
|
10
|
+
ownerCallStatusProvider: OwnerCallStatusProvider;
|
|
11
11
|
subAgentOutputRootDirectory: string | null;
|
|
12
12
|
subAgentProcessMatchPattern: string | null;
|
|
13
13
|
subAgentTranscriptRootDirectory: string | null;
|
|
@@ -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;
|
|
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;AAEpG,OAAO,EAAE,uBAAuB,EAAE,MAAM,qEAAqE,CAAC;AAC9G,OAAO,EAAE,oBAAoB,EAAE,MAAM,kEAAkE,CAAC;AACxG,OAAO,EAEL,qBAAqB,EAQtB,MAAM,0DAA0D,CAAC;AAkBlE,OAAO,EAEL,6BAA6B,EAC9B,MAAM,6DAA6D,CAAC;AAKrE,MAAM,MAAM,8BAA8B,GAAG;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,uBAAuB,EAAE,uBAAuB,CAAC;IACjD,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,+BAA+B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,4BAA4B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,0BAA0B,EAAE,MAAM,CAAC;IACnC,+BAA+B,EAAE,MAAM,CAAC;IACxC,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,+BAA+B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,4BAA4B,EAAE,MAAM,CAAC;IACrC,gBAAgB,EAAE,6BAA6B,CAAC;IAChD,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,GAAG,EAAE,IAAI,CAAC;CACX,CAAC;AA8BF,eAAO,MAAM,wBAAwB,GACnC,QAAQ,8BAA8B,KACrC,OAAO,CAAC,IAAI,CAoFd,CAAC;AAEF,eAAO,MAAM,0CAA0C;;;;;;;;CAS7C,CAAC"}
|
|
@@ -4,10 +4,12 @@ export declare const ownerCallMarkerFamilyResolve: (marker: string) => string[];
|
|
|
4
4
|
export declare class TranscriptOwnerCallStatusProvider implements OwnerCallStatusProvider {
|
|
5
5
|
private readonly ownerReplyMarkerDirectory;
|
|
6
6
|
private readonly ownerCallMarkerFamily;
|
|
7
|
+
private readonly transcriptScanByPath;
|
|
7
8
|
constructor(ownerCallMarker: string | null, ownerReplyMarkerDirectory?: string | null);
|
|
8
9
|
listUnansweredOwnerCallEpochSecondsBySessionName: (transcriptPathBySessionName: Map<string, string>) => Promise<Map<string, number>>;
|
|
9
10
|
listUnansweredOwnerCallsBySessionName: (transcriptPathBySessionName: Map<string, string>) => Promise<Map<string, UnansweredOwnerCall[]>>;
|
|
10
11
|
private scanTranscript;
|
|
12
|
+
private readTranscriptScan;
|
|
11
13
|
private resolveReplyEpochMs;
|
|
12
14
|
private findUnansweredOwnerCallEpochMs;
|
|
13
15
|
private readOwnerReplyMarkerEpochMs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TranscriptOwnerCallStatusProvider.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/TranscriptOwnerCallStatusProvider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,kEAAkE,CAAC;AAC3G,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAwGhF,eAAO,MAAM,4BAA4B,GAAI,QAAQ,MAAM,KAAG,MAAM,EAMtD,CAAC;AA4Cf,qBAAa,iCAAkC,YAAW,uBAAuB;
|
|
1
|
+
{"version":3,"file":"TranscriptOwnerCallStatusProvider.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/TranscriptOwnerCallStatusProvider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,kEAAkE,CAAC;AAC3G,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAwGhF,eAAO,MAAM,4BAA4B,GAAI,QAAQ,MAAM,KAAG,MAAM,EAMtD,CAAC;AA4Cf,qBAAa,iCAAkC,YAAW,uBAAuB;IAU7E,OAAO,CAAC,QAAQ,CAAC,yBAAyB;IAT5C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAW;IAEjD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAGjC;gBAGF,eAAe,EAAE,MAAM,GAAG,IAAI,EACb,yBAAyB,GAAE,MAAM,GAAG,IAAW;IAQlE,gDAAgD,GAC9C,6BAA6B,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAC/C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAmB7B;IAEF,qCAAqC,GACnC,6BAA6B,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAC/C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAkC5C;IAEF,OAAO,CAAC,cAAc,CAUpB;IAEF,OAAO,CAAC,kBAAkB,CA6DxB;IAEF,OAAO,CAAC,mBAAmB,CAUzB;IAEF,OAAO,CAAC,8BAA8B,CAgCpC;IAOF,OAAO,CAAC,2BAA2B,CAGyC;IAS5E,OAAO,CAAC,sBAAsB,CAW5B;IAEF,OAAO,CAAC,2BAA2B,CAgBjC;IAEF,OAAO,CAAC,wBAAwB,CAoB9B;IAEF,OAAO,CAAC,iBAAiB,CA4BvB;CACH"}
|