github-issue-tower-defence-management 1.117.10 → 1.118.1
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 +11 -7
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +38 -12
- 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/ConfigurableSilentSessionMessageComposer.js +44 -11
- package/bin/adapter/repositories/ConfigurableSilentSessionMessageComposer.js.map +1 -1
- package/bin/adapter/repositories/FileSystemSilentSessionHubTaskStatusCacheRepository.js +128 -0
- package/bin/adapter/repositories/FileSystemSilentSessionHubTaskStatusCacheRepository.js.map +1 -0
- package/bin/domain/usecases/DefaultSilentSessionMessageComposer.js +27 -7
- package/bin/domain/usecases/DefaultSilentSessionMessageComposer.js.map +1 -1
- package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js +65 -17
- package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js.map +1 -1
- package/bin/domain/usecases/adapter-interfaces/SilentSessionHubTaskStatusCacheRepository.js +3 -0
- package/bin/domain/usecases/adapter-interfaces/SilentSessionHubTaskStatusCacheRepository.js.map +1 -0
- package/package.json +1 -1
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +29 -8
- package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.test.ts +14 -4
- package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts +13 -0
- package/src/adapter/repositories/ConfigurableSilentSessionMessageComposer.test.ts +81 -28
- package/src/adapter/repositories/ConfigurableSilentSessionMessageComposer.ts +91 -19
- package/src/adapter/repositories/FileSystemSilentSessionHubTaskStatusCacheRepository.test.ts +251 -0
- package/src/adapter/repositories/FileSystemSilentSessionHubTaskStatusCacheRepository.ts +121 -0
- package/src/domain/usecases/DefaultSilentSessionMessageComposer.test.ts +91 -15
- package/src/domain/usecases/DefaultSilentSessionMessageComposer.ts +54 -11
- package/src/domain/usecases/NotifySilentLiveSessionsUseCase.test.ts +252 -9
- package/src/domain/usecases/NotifySilentLiveSessionsUseCase.ts +111 -20
- package/src/domain/usecases/adapter-interfaces/SilentSessionHubTaskStatusCacheRepository.ts +20 -0
- package/src/domain/usecases/adapter-interfaces/SilentSessionMessageComposer.ts +9 -1
- 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/ConfigurableSilentSessionMessageComposer.d.ts +8 -4
- package/types/adapter/repositories/ConfigurableSilentSessionMessageComposer.d.ts.map +1 -1
- package/types/adapter/repositories/FileSystemSilentSessionHubTaskStatusCacheRepository.d.ts +20 -0
- package/types/adapter/repositories/FileSystemSilentSessionHubTaskStatusCacheRepository.d.ts.map +1 -0
- package/types/domain/usecases/DefaultSilentSessionMessageComposer.d.ts +2 -2
- package/types/domain/usecases/DefaultSilentSessionMessageComposer.d.ts.map +1 -1
- package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts +7 -1
- package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts.map +1 -1
- package/types/domain/usecases/adapter-interfaces/SilentSessionHubTaskStatusCacheRepository.d.ts +19 -0
- package/types/domain/usecases/adapter-interfaces/SilentSessionHubTaskStatusCacheRepository.d.ts.map +1 -0
- package/types/domain/usecases/adapter-interfaces/SilentSessionMessageComposer.d.ts +5 -1
- package/types/domain/usecases/adapter-interfaces/SilentSessionMessageComposer.d.ts.map +1 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.FileSystemSilentSessionHubTaskStatusCacheRepository = exports.DEFAULT_HUB_TASK_STATUS_RETENTION_WINDOW_SECONDS = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const os = __importStar(require("os"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
41
|
+
const isIssueState = (value) => value === 'OPEN' || value === 'CLOSED' || value === 'MERGED';
|
|
42
|
+
exports.DEFAULT_HUB_TASK_STATUS_RETENTION_WINDOW_SECONDS = 60 * 60;
|
|
43
|
+
const defaultStateFilePath = () => {
|
|
44
|
+
const base = process.env.XDG_CACHE_HOME ?? path.join(os.homedir(), '.cache');
|
|
45
|
+
return path.join(base, 'tdpm', 'silent-session-hub-task-status.json');
|
|
46
|
+
};
|
|
47
|
+
class FileSystemSilentSessionHubTaskStatusCacheRepository {
|
|
48
|
+
constructor(stateFilePath = defaultStateFilePath(), retentionWindowSeconds = exports.DEFAULT_HUB_TASK_STATUS_RETENTION_WINDOW_SECONDS) {
|
|
49
|
+
this.stateFilePath = stateFilePath;
|
|
50
|
+
this.retentionWindowSeconds = retentionWindowSeconds;
|
|
51
|
+
this.loadHubTaskStatus = async (params) => {
|
|
52
|
+
for (const entry of this.readEntries()) {
|
|
53
|
+
if (entry.url === params.url) {
|
|
54
|
+
return entry;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
};
|
|
59
|
+
this.saveHubTaskStatus = async (params) => {
|
|
60
|
+
const recordedEpochSeconds = Math.floor(params.now.getTime() / 1000);
|
|
61
|
+
const oldestRetainedEpochSeconds = recordedEpochSeconds - this.retentionWindowSeconds;
|
|
62
|
+
const mergedByUrl = new Map();
|
|
63
|
+
for (const entry of this.readEntries()) {
|
|
64
|
+
if (entry.recordedEpochSeconds >= oldestRetainedEpochSeconds &&
|
|
65
|
+
entry.url !== params.url) {
|
|
66
|
+
mergedByUrl.set(entry.url, entry);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
mergedByUrl.set(params.url, {
|
|
70
|
+
url: params.url,
|
|
71
|
+
state: params.state,
|
|
72
|
+
status: params.status,
|
|
73
|
+
recordedEpochSeconds,
|
|
74
|
+
});
|
|
75
|
+
this.writeEntries(Array.from(mergedByUrl.values()));
|
|
76
|
+
};
|
|
77
|
+
this.readEntries = () => {
|
|
78
|
+
let raw;
|
|
79
|
+
try {
|
|
80
|
+
raw = fs.readFileSync(this.stateFilePath, 'utf8');
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
let parsed;
|
|
86
|
+
try {
|
|
87
|
+
parsed = JSON.parse(raw);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
if (!isRecord(parsed)) {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
const storedEntries = parsed.hubTaskStatuses;
|
|
96
|
+
if (!Array.isArray(storedEntries)) {
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
const entries = [];
|
|
100
|
+
for (const storedEntry of storedEntries) {
|
|
101
|
+
if (!isRecord(storedEntry)) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const url = storedEntry.url;
|
|
105
|
+
const state = storedEntry.state;
|
|
106
|
+
const status = storedEntry.status;
|
|
107
|
+
const recordedEpochSeconds = storedEntry.recordedEpochSeconds;
|
|
108
|
+
if (typeof url === 'string' &&
|
|
109
|
+
isIssueState(state) &&
|
|
110
|
+
(typeof status === 'string' || status === null) &&
|
|
111
|
+
typeof recordedEpochSeconds === 'number' &&
|
|
112
|
+
Number.isFinite(recordedEpochSeconds)) {
|
|
113
|
+
entries.push({ url, state, status, recordedEpochSeconds });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return entries;
|
|
117
|
+
};
|
|
118
|
+
this.writeEntries = (entries) => {
|
|
119
|
+
const directory = path.dirname(this.stateFilePath);
|
|
120
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
121
|
+
const temporaryPath = `${this.stateFilePath}.${process.pid}.tmp`;
|
|
122
|
+
fs.writeFileSync(temporaryPath, JSON.stringify({ hubTaskStatuses: entries }));
|
|
123
|
+
fs.renameSync(temporaryPath, this.stateFilePath);
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
exports.FileSystemSilentSessionHubTaskStatusCacheRepository = FileSystemSilentSessionHubTaskStatusCacheRepository;
|
|
128
|
+
//# sourceMappingURL=FileSystemSilentSessionHubTaskStatusCacheRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSystemSilentSessionHubTaskStatusCacheRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemSilentSessionHubTaskStatusCacheRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,22 @@ const formatMinutes = (seconds) => {
|
|
|
6
6
|
const minutes = Math.floor(seconds / 60);
|
|
7
7
|
return `${minutes}m`;
|
|
8
8
|
};
|
|
9
|
+
const composeIdleSubAgentSection = (idleSubAgents) => {
|
|
10
|
+
const lines = idleSubAgents.map((subAgent) => `- ${subAgent.label}: no output for ${formatMinutes(subAgent.silentSeconds)}`);
|
|
11
|
+
return [
|
|
12
|
+
`${silentSessionReminderSentinel_1.SILENT_SESSION_REMINDER_SENTINEL} The following sub-process(es) have produced no output for several minutes and may be stalled:`,
|
|
13
|
+
...lines,
|
|
14
|
+
'Check each one. If it is stuck, take action (restart, hand off, or replace it). If it is legitimately waiting on an external dependency (continuous integration, an external API, or another process), let it continue.',
|
|
15
|
+
].join('\n');
|
|
16
|
+
};
|
|
17
|
+
const composeLongRunningSubAgentSection = (longRunningSubAgents) => {
|
|
18
|
+
const lines = longRunningSubAgents.map((subAgent) => `- ${subAgent.label}: running for ${formatMinutes(subAgent.runningSeconds)}`);
|
|
19
|
+
return [
|
|
20
|
+
`${silentSessionReminderSentinel_1.SILENT_SESSION_REMINDER_SENTINEL} The following sub-process(es) have been running longer than a task should normally take, which may mean an infinite loop, a task that is too large, or being stuck in an incorrect approach that is not making forward progress:`,
|
|
21
|
+
...lines,
|
|
22
|
+
'Verify each one is genuinely advancing toward completion; do not dismiss it merely because it produced output recently. If it is not progressing, intervene: break the task down, restart, hand off, or replace it.',
|
|
23
|
+
].join('\n');
|
|
24
|
+
};
|
|
9
25
|
const composeOwnerCallFormatGuidance = (ownerCallMarker) => {
|
|
10
26
|
const markerInstruction = ownerCallMarker !== null && ownerCallMarker.length > 0
|
|
11
27
|
? `Emit the owner-call as the configured owner-call marker tag "${ownerCallMarker}" as a complete matching pair — opening marker, content, then closing marker — on a single line with no newline inside the tag.`
|
|
@@ -29,13 +45,17 @@ class DefaultSilentSessionMessageComposer {
|
|
|
29
45
|
this.composeMainStalledSection = (mainSilentSeconds) => {
|
|
30
46
|
return composeMainStalledMessage(mainSilentSeconds, this.ownerCallMarker);
|
|
31
47
|
};
|
|
32
|
-
this.composeSubAgentSection = (subAgents) => {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
48
|
+
this.composeSubAgentSection = (subAgents, thresholds) => {
|
|
49
|
+
const idleSubAgents = subAgents.filter((subAgent) => subAgent.silentSeconds >= thresholds.subAgentSilentThresholdSeconds);
|
|
50
|
+
const longRunningSubAgents = subAgents.filter((subAgent) => subAgent.runningSeconds >= thresholds.subAgentRunningThresholdSeconds);
|
|
51
|
+
const sections = [];
|
|
52
|
+
if (idleSubAgents.length > 0) {
|
|
53
|
+
sections.push(composeIdleSubAgentSection(idleSubAgents));
|
|
54
|
+
}
|
|
55
|
+
if (longRunningSubAgents.length > 0) {
|
|
56
|
+
sections.push(composeLongRunningSubAgentSection(longRunningSubAgents));
|
|
57
|
+
}
|
|
58
|
+
return sections.join('\n\n');
|
|
39
59
|
};
|
|
40
60
|
}
|
|
41
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultSilentSessionMessageComposer.js","sourceRoot":"","sources":["../../../src/domain/usecases/DefaultSilentSessionMessageComposer.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"DefaultSilentSessionMessageComposer.js","sourceRoot":"","sources":["../../../src/domain/usecases/DefaultSilentSessionMessageComposer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NotifySilentLiveSessionsUseCase = exports.isGitHubIssueOrPullRequestSessionName = exports.parseHubTaskIssueUrlFromSessionName = exports.DEFAULT_CANDIDATE_DEBOUNCE_RECENCY_WINDOW_SECONDS = exports.DEFAULT_NOTIFICATION_STAGGER_SECONDS = exports.DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS = exports.DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS = exports.DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS = void 0;
|
|
3
|
+
exports.NotifySilentLiveSessionsUseCase = exports.isGitHubIssueOrPullRequestSessionName = exports.parseHubTaskIssueUrlFromSessionName = exports.DEFAULT_HUB_TASK_STATUS_CACHE_TTL_SECONDS = exports.DEFAULT_CANDIDATE_DEBOUNCE_RECENCY_WINDOW_SECONDS = exports.DEFAULT_NOTIFICATION_STAGGER_SECONDS = exports.DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS = exports.DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS = exports.DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS = void 0;
|
|
4
4
|
const ResolveInteractiveLiveSessionsUseCase_1 = require("./ResolveInteractiveLiveSessionsUseCase");
|
|
5
5
|
exports.DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS = 10 * 60;
|
|
6
6
|
exports.DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS = 5 * 60;
|
|
7
7
|
exports.DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS = 15 * 60;
|
|
8
8
|
exports.DEFAULT_NOTIFICATION_STAGGER_SECONDS = 25;
|
|
9
9
|
exports.DEFAULT_CANDIDATE_DEBOUNCE_RECENCY_WINDOW_SECONDS = 15 * 60;
|
|
10
|
+
exports.DEFAULT_HUB_TASK_STATUS_CACHE_TTL_SECONDS = 5 * 60;
|
|
10
11
|
const GITHUB_ISSUE_OR_PULL_URL_PATTERN = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/(?:issues|pull)\/(\d+)$/;
|
|
11
12
|
const GITHUB_TMUX_SESSION_NAME_PATTERN = /^https_\/\/github_com\/([^/]+)\/([^/]+)\/(?:issues|pull)\/(\d+)$/;
|
|
12
13
|
const parseHubTaskIssueUrlFromSessionName = (sessionName) => {
|
|
@@ -26,7 +27,7 @@ const GITHUB_ISSUE_OR_PULL_REQUEST_SESSION_NAME_PATTERN = /^https(:\/\/|_\/\/)gi
|
|
|
26
27
|
const isGitHubIssueOrPullRequestSessionName = (sessionName) => GITHUB_ISSUE_OR_PULL_REQUEST_SESSION_NAME_PATTERN.test(sessionName);
|
|
27
28
|
exports.isGitHubIssueOrPullRequestSessionName = isGitHubIssueOrPullRequestSessionName;
|
|
28
29
|
class NotifySilentLiveSessionsUseCase {
|
|
29
|
-
constructor(liveSessionProcessSnapshotProvider, interactiveLiveSessionTranscriptResolver, sessionOutputActivityRepository, subAgentActivityRepository, ownerCallStatusProvider, notificationRepository, candidateStateRepository, messageComposer, sleeper, hubTaskStatusResolver = null) {
|
|
30
|
+
constructor(liveSessionProcessSnapshotProvider, interactiveLiveSessionTranscriptResolver, sessionOutputActivityRepository, subAgentActivityRepository, ownerCallStatusProvider, notificationRepository, candidateStateRepository, messageComposer, sleeper, hubTaskStatusResolver = null, hubTaskStatusCacheRepository = null) {
|
|
30
31
|
this.liveSessionProcessSnapshotProvider = liveSessionProcessSnapshotProvider;
|
|
31
32
|
this.interactiveLiveSessionTranscriptResolver = interactiveLiveSessionTranscriptResolver;
|
|
32
33
|
this.sessionOutputActivityRepository = sessionOutputActivityRepository;
|
|
@@ -37,6 +38,7 @@ class NotifySilentLiveSessionsUseCase {
|
|
|
37
38
|
this.messageComposer = messageComposer;
|
|
38
39
|
this.sleeper = sleeper;
|
|
39
40
|
this.hubTaskStatusResolver = hubTaskStatusResolver;
|
|
41
|
+
this.hubTaskStatusCacheRepository = hubTaskStatusCacheRepository;
|
|
40
42
|
this.resolveInteractiveLiveSessions = new ResolveInteractiveLiveSessionsUseCase_1.ResolveInteractiveLiveSessionsUseCase();
|
|
41
43
|
this.run = async (params) => {
|
|
42
44
|
const snapshot = await this.liveSessionProcessSnapshotProvider.getSnapshot();
|
|
@@ -73,7 +75,7 @@ class NotifySilentLiveSessionsUseCase {
|
|
|
73
75
|
console.log(`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.`);
|
|
74
76
|
let sentCount = 0;
|
|
75
77
|
for (const candidate of debouncedCandidates) {
|
|
76
|
-
if (!(await this.isHubTaskActive(candidate.sessionName, params.activeHubTaskStatus))) {
|
|
78
|
+
if (!(await this.isHubTaskActive(candidate.sessionName, params.activeHubTaskStatus, params.hubTaskStatusCacheTtlSeconds, params.now))) {
|
|
77
79
|
continue;
|
|
78
80
|
}
|
|
79
81
|
if (sentCount > 0) {
|
|
@@ -84,7 +86,7 @@ class NotifySilentLiveSessionsUseCase {
|
|
|
84
86
|
console.log(`Notified ${candidate.sessionName}.`);
|
|
85
87
|
}
|
|
86
88
|
};
|
|
87
|
-
this.isHubTaskActive = async (sessionName, activeHubTaskStatus) => {
|
|
89
|
+
this.isHubTaskActive = async (sessionName, activeHubTaskStatus, hubTaskStatusCacheTtlSeconds, now) => {
|
|
88
90
|
if (activeHubTaskStatus === null || this.hubTaskStatusResolver === null) {
|
|
89
91
|
return true;
|
|
90
92
|
}
|
|
@@ -92,23 +94,66 @@ class NotifySilentLiveSessionsUseCase {
|
|
|
92
94
|
if (hubTaskIssueUrl === null) {
|
|
93
95
|
return true;
|
|
94
96
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
97
|
+
const cachedEntry = this.hubTaskStatusCacheRepository === null
|
|
98
|
+
? null
|
|
99
|
+
: await this.hubTaskStatusCacheRepository.loadHubTaskStatus({
|
|
100
|
+
url: hubTaskIssueUrl,
|
|
101
|
+
});
|
|
102
|
+
const nowEpochSeconds = Math.floor(now.getTime() / 1000);
|
|
103
|
+
if (cachedEntry !== null) {
|
|
104
|
+
const cacheAgeSeconds = nowEpochSeconds - cachedEntry.recordedEpochSeconds;
|
|
105
|
+
if (cacheAgeSeconds <= hubTaskStatusCacheTtlSeconds) {
|
|
106
|
+
const active = this.isResolvedStatusActive(cachedEntry.state, cachedEntry.status, activeHubTaskStatus);
|
|
107
|
+
if (!active) {
|
|
108
|
+
console.log(`Skipping ${sessionName}: hub task ${hubTaskIssueUrl} is no longer active per cached status (state "${cachedEntry.state}", status "${cachedEntry.status ?? 'null'}", active status "${activeHubTaskStatus}").`);
|
|
109
|
+
}
|
|
110
|
+
return active;
|
|
104
111
|
}
|
|
105
|
-
|
|
112
|
+
}
|
|
113
|
+
const resolution = await this.tryResolveAndCacheHubTask(hubTaskIssueUrl, activeHubTaskStatus, sessionName, now);
|
|
114
|
+
if (resolution.resolved) {
|
|
115
|
+
return resolution.active;
|
|
116
|
+
}
|
|
117
|
+
if (cachedEntry !== null) {
|
|
118
|
+
const active = this.isResolvedStatusActive(cachedEntry.state, cachedEntry.status, activeHubTaskStatus);
|
|
119
|
+
console.warn(`Hub task ${hubTaskIssueUrl} for session ${sessionName} could not be resolved (${resolution.reason}); falling back to expired cached status (state "${cachedEntry.state}", status "${cachedEntry.status ?? 'null'}"), so the notification is ${active ? 'sent' : 'suppressed'}.`);
|
|
120
|
+
return active;
|
|
121
|
+
}
|
|
122
|
+
console.warn(`Hub task ${hubTaskIssueUrl} for session ${sessionName} is not resolvable and has no cached status (${resolution.reason}); sending notification (fail-open).`);
|
|
123
|
+
return true;
|
|
124
|
+
};
|
|
125
|
+
this.tryResolveAndCacheHubTask = async (hubTaskIssueUrl, activeHubTaskStatus, sessionName, now) => {
|
|
126
|
+
if (this.hubTaskStatusResolver === null) {
|
|
127
|
+
return { resolved: false, reason: 'resolver is not configured' };
|
|
128
|
+
}
|
|
129
|
+
let issue;
|
|
130
|
+
try {
|
|
131
|
+
issue = await this.hubTaskStatusResolver.getIssueByUrl(hubTaskIssueUrl);
|
|
106
132
|
}
|
|
107
133
|
catch (error) {
|
|
108
|
-
|
|
109
|
-
|
|
134
|
+
return {
|
|
135
|
+
resolved: false,
|
|
136
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (issue === null) {
|
|
140
|
+
return { resolved: false, reason: 'resolver returned no tracked task' };
|
|
141
|
+
}
|
|
142
|
+
if (this.hubTaskStatusCacheRepository !== null) {
|
|
143
|
+
await this.hubTaskStatusCacheRepository.saveHubTaskStatus({
|
|
144
|
+
url: hubTaskIssueUrl,
|
|
145
|
+
state: issue.state,
|
|
146
|
+
status: issue.status,
|
|
147
|
+
now,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
const active = this.isResolvedStatusActive(issue.state, issue.status, activeHubTaskStatus);
|
|
151
|
+
if (!active) {
|
|
152
|
+
console.log(`Skipping ${sessionName}: hub task ${hubTaskIssueUrl} is no longer active (state "${issue.state}", status "${issue.status ?? 'null'}", active status "${activeHubTaskStatus}").`);
|
|
110
153
|
}
|
|
154
|
+
return { resolved: true, active };
|
|
111
155
|
};
|
|
156
|
+
this.isResolvedStatusActive = (state, status, activeHubTaskStatus) => state === 'OPEN' && status === activeHubTaskStatus;
|
|
112
157
|
this.collectSnapshots = async (interactiveSessions, transcriptPathBySessionName, now) => {
|
|
113
158
|
const sessionNames = interactiveSessions.map((session) => session.sessionName);
|
|
114
159
|
const activities = await this.sessionOutputActivityRepository.listSessionOutputActivities(transcriptPathBySessionName);
|
|
@@ -142,7 +187,10 @@ class NotifySilentLiveSessionsUseCase {
|
|
|
142
187
|
const stalledSubAgents = snapshot.subAgents.filter((subAgent) => subAgent.silentSeconds >= thresholds.subAgentSilentThresholdSeconds ||
|
|
143
188
|
subAgent.runningSeconds >= thresholds.subAgentRunningThresholdSeconds);
|
|
144
189
|
if (stalledSubAgents.length > 0) {
|
|
145
|
-
sections.push(this.messageComposer.composeSubAgentSection(stalledSubAgents
|
|
190
|
+
sections.push(this.messageComposer.composeSubAgentSection(stalledSubAgents, {
|
|
191
|
+
subAgentSilentThresholdSeconds: thresholds.subAgentSilentThresholdSeconds,
|
|
192
|
+
subAgentRunningThresholdSeconds: thresholds.subAgentRunningThresholdSeconds,
|
|
193
|
+
}));
|
|
146
194
|
}
|
|
147
195
|
if (sections.length === 0) {
|
|
148
196
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotifySilentLiveSessionsUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/NotifySilentLiveSessionsUseCase.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"NotifySilentLiveSessionsUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/NotifySilentLiveSessionsUseCase.ts"],"names":[],"mappings":"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"}
|
package/bin/domain/usecases/adapter-interfaces/SilentSessionHubTaskStatusCacheRepository.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SilentSessionHubTaskStatusCacheRepository.js","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/SilentSessionHubTaskStatusCacheRepository.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -120,9 +120,13 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
120
120
|
candidateDebounceRecencyWindowSeconds?: number;
|
|
121
121
|
candidateDebounceStateFilePath?: string;
|
|
122
122
|
activeHubTaskStatus?: string;
|
|
123
|
+
hubTaskStatusCacheStateFilePath?: string;
|
|
124
|
+
hubTaskStatusCacheTtlSeconds?: number;
|
|
123
125
|
silentMainStalledMessage?: string;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
+
silentSubAgentIdleMessageHeader?: string;
|
|
127
|
+
silentSubAgentIdleMessageFooter?: string;
|
|
128
|
+
silentSubAgentLongRunningMessageHeader?: string;
|
|
129
|
+
silentSubAgentLongRunningMessageFooter?: string;
|
|
126
130
|
credentials: {
|
|
127
131
|
manager: {
|
|
128
132
|
github: {
|
|
@@ -624,18 +628,35 @@ export class HandleScheduledEventUseCaseHandler {
|
|
|
624
628
|
process.env.TDPM_ACTIVE_HUB_TASK_STATUS ??
|
|
625
629
|
null,
|
|
626
630
|
hubTaskStatusResolver: issueRepository,
|
|
631
|
+
hubTaskStatusCacheStateFilePath:
|
|
632
|
+
mergedInput.hubTaskStatusCacheStateFilePath ??
|
|
633
|
+
process.env.TDPM_SILENT_HUB_TASK_STATUS_CACHE_STATE_FILE_PATH ??
|
|
634
|
+
null,
|
|
635
|
+
hubTaskStatusCacheTtlSeconds: readSilentSeconds(
|
|
636
|
+
mergedInput.hubTaskStatusCacheTtlSeconds,
|
|
637
|
+
process.env.TDPM_SILENT_HUB_TASK_STATUS_CACHE_TTL_SECONDS,
|
|
638
|
+
DEFAULT_NOTIFY_SILENT_TMUX_SESSIONS_PARAMS.hubTaskStatusCacheTtlSeconds,
|
|
639
|
+
),
|
|
627
640
|
messageTemplates: {
|
|
628
641
|
mainStalledMessage:
|
|
629
642
|
mergedInput.silentMainStalledMessage ??
|
|
630
643
|
process.env.TDPM_SILENT_MAIN_STALLED_MESSAGE ??
|
|
631
644
|
null,
|
|
632
|
-
|
|
633
|
-
mergedInput.
|
|
634
|
-
process.env.
|
|
645
|
+
subAgentIdleMessageHeader:
|
|
646
|
+
mergedInput.silentSubAgentIdleMessageHeader ??
|
|
647
|
+
process.env.TDPM_SILENT_SUBAGENT_IDLE_MESSAGE_HEADER ??
|
|
648
|
+
null,
|
|
649
|
+
subAgentIdleMessageFooter:
|
|
650
|
+
mergedInput.silentSubAgentIdleMessageFooter ??
|
|
651
|
+
process.env.TDPM_SILENT_SUBAGENT_IDLE_MESSAGE_FOOTER ??
|
|
652
|
+
null,
|
|
653
|
+
subAgentLongRunningMessageHeader:
|
|
654
|
+
mergedInput.silentSubAgentLongRunningMessageHeader ??
|
|
655
|
+
process.env.TDPM_SILENT_SUBAGENT_LONG_RUNNING_MESSAGE_HEADER ??
|
|
635
656
|
null,
|
|
636
|
-
|
|
637
|
-
mergedInput.
|
|
638
|
-
process.env.
|
|
657
|
+
subAgentLongRunningMessageFooter:
|
|
658
|
+
mergedInput.silentSubAgentLongRunningMessageFooter ??
|
|
659
|
+
process.env.TDPM_SILENT_SUBAGENT_LONG_RUNNING_MESSAGE_FOOTER ??
|
|
639
660
|
null,
|
|
640
661
|
},
|
|
641
662
|
now: inTmuxNow,
|
|
@@ -20,8 +20,10 @@ const CLAUDE_PID = 201;
|
|
|
20
20
|
|
|
21
21
|
const EMPTY_TEMPLATES: SilentSessionMessageTemplates = {
|
|
22
22
|
mainStalledMessage: null,
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
subAgentIdleMessageHeader: null,
|
|
24
|
+
subAgentIdleMessageFooter: null,
|
|
25
|
+
subAgentLongRunningMessageHeader: null,
|
|
26
|
+
subAgentLongRunningMessageFooter: null,
|
|
25
27
|
};
|
|
26
28
|
|
|
27
29
|
type Mocked<T> = jest.Mocked<T> & jest.MockedObject<T>;
|
|
@@ -37,6 +39,7 @@ const createMockRunner = (): Mocked<LocalCommandRunner> => ({
|
|
|
37
39
|
describe('notifySilentTmuxSessions', () => {
|
|
38
40
|
let configDir: string;
|
|
39
41
|
let candidateStateFilePath: string;
|
|
42
|
+
let hubTaskStatusCacheStateFilePath: string;
|
|
40
43
|
|
|
41
44
|
beforeEach(() => {
|
|
42
45
|
jest.spyOn(console, 'log').mockImplementation(() => undefined);
|
|
@@ -45,6 +48,10 @@ describe('notifySilentTmuxSessions', () => {
|
|
|
45
48
|
configDir,
|
|
46
49
|
'silent-session-candidates.json',
|
|
47
50
|
);
|
|
51
|
+
hubTaskStatusCacheStateFilePath = path.join(
|
|
52
|
+
configDir,
|
|
53
|
+
'silent-session-hub-task-status.json',
|
|
54
|
+
);
|
|
48
55
|
});
|
|
49
56
|
|
|
50
57
|
afterEach(() => {
|
|
@@ -134,6 +141,7 @@ describe('notifySilentTmuxSessions', () => {
|
|
|
134
141
|
candidateDebounceStateFilePath: candidateStateFilePath,
|
|
135
142
|
activeHubTaskStatus: null,
|
|
136
143
|
hubTaskStatusResolver: null,
|
|
144
|
+
hubTaskStatusCacheStateFilePath: hubTaskStatusCacheStateFilePath,
|
|
137
145
|
messageTemplates: EMPTY_TEMPLATES,
|
|
138
146
|
now: NOW,
|
|
139
147
|
...DEFAULT_NOTIFY_SILENT_TMUX_SESSIONS_PARAMS,
|
|
@@ -214,8 +222,10 @@ describe('notifySilentTmuxSessions', () => {
|
|
|
214
222
|
...baseParams(runner),
|
|
215
223
|
messageTemplates: {
|
|
216
224
|
mainStalledMessage: 'CUSTOM_MAIN_TEMPLATE',
|
|
217
|
-
|
|
218
|
-
|
|
225
|
+
subAgentIdleMessageHeader: null,
|
|
226
|
+
subAgentIdleMessageFooter: null,
|
|
227
|
+
subAgentLongRunningMessageHeader: null,
|
|
228
|
+
subAgentLongRunningMessageFooter: null,
|
|
219
229
|
},
|
|
220
230
|
});
|
|
221
231
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
|
|
11
11
|
DEFAULT_NOTIFICATION_STAGGER_SECONDS,
|
|
12
12
|
DEFAULT_CANDIDATE_DEBOUNCE_RECENCY_WINDOW_SECONDS,
|
|
13
|
+
DEFAULT_HUB_TASK_STATUS_CACHE_TTL_SECONDS,
|
|
13
14
|
} from '../../../domain/usecases/NotifySilentLiveSessionsUseCase';
|
|
14
15
|
import { DefaultSilentSessionMessageComposer } from '../../../domain/usecases/DefaultSilentSessionMessageComposer';
|
|
15
16
|
import { LocalProcessLiveSessionProcessSnapshotProvider } from '../../repositories/LocalProcessLiveSessionProcessSnapshotProvider';
|
|
@@ -30,6 +31,7 @@ import {
|
|
|
30
31
|
} from '../../repositories/ConfigurableSilentSessionMessageComposer';
|
|
31
32
|
import { RealSleeper } from '../../repositories/RealSleeper';
|
|
32
33
|
import { FileSystemSilentSessionCandidateStateRepository } from '../../repositories/FileSystemSilentSessionCandidateStateRepository';
|
|
34
|
+
import { FileSystemSilentSessionHubTaskStatusCacheRepository } from '../../repositories/FileSystemSilentSessionHubTaskStatusCacheRepository';
|
|
33
35
|
|
|
34
36
|
export type NotifySilentTmuxSessionsParams = {
|
|
35
37
|
enabled: boolean;
|
|
@@ -47,6 +49,8 @@ export type NotifySilentTmuxSessionsParams = {
|
|
|
47
49
|
candidateDebounceStateFilePath: string | null;
|
|
48
50
|
activeHubTaskStatus: string | null;
|
|
49
51
|
hubTaskStatusResolver: HubTaskStatusResolver | null;
|
|
52
|
+
hubTaskStatusCacheStateFilePath: string | null;
|
|
53
|
+
hubTaskStatusCacheTtlSeconds: number;
|
|
50
54
|
messageTemplates: SilentSessionMessageTemplates;
|
|
51
55
|
now: Date;
|
|
52
56
|
};
|
|
@@ -104,6 +108,8 @@ export const notifySilentTmuxSessions = async (
|
|
|
104
108
|
candidateDebounceStateFilePath,
|
|
105
109
|
activeHubTaskStatus,
|
|
106
110
|
hubTaskStatusResolver,
|
|
111
|
+
hubTaskStatusCacheStateFilePath,
|
|
112
|
+
hubTaskStatusCacheTtlSeconds,
|
|
107
113
|
messageTemplates,
|
|
108
114
|
now,
|
|
109
115
|
} = params;
|
|
@@ -141,6 +147,11 @@ export const notifySilentTmuxSessions = async (
|
|
|
141
147
|
messageComposer,
|
|
142
148
|
new RealSleeper(),
|
|
143
149
|
hubTaskStatusResolver,
|
|
150
|
+
hubTaskStatusCacheStateFilePath !== null
|
|
151
|
+
? new FileSystemSilentSessionHubTaskStatusCacheRepository(
|
|
152
|
+
hubTaskStatusCacheStateFilePath,
|
|
153
|
+
)
|
|
154
|
+
: new FileSystemSilentSessionHubTaskStatusCacheRepository(),
|
|
144
155
|
);
|
|
145
156
|
await useCase.run({
|
|
146
157
|
mainSilentThresholdSeconds,
|
|
@@ -149,6 +160,7 @@ export const notifySilentTmuxSessions = async (
|
|
|
149
160
|
staggerSeconds,
|
|
150
161
|
candidateDebounceRecencyWindowSeconds,
|
|
151
162
|
activeHubTaskStatus,
|
|
163
|
+
hubTaskStatusCacheTtlSeconds,
|
|
152
164
|
now,
|
|
153
165
|
});
|
|
154
166
|
};
|
|
@@ -160,4 +172,5 @@ export const DEFAULT_NOTIFY_SILENT_TMUX_SESSIONS_PARAMS = {
|
|
|
160
172
|
staggerSeconds: DEFAULT_NOTIFICATION_STAGGER_SECONDS,
|
|
161
173
|
candidateDebounceRecencyWindowSeconds:
|
|
162
174
|
DEFAULT_CANDIDATE_DEBOUNCE_RECENCY_WINDOW_SECONDS,
|
|
175
|
+
hubTaskStatusCacheTtlSeconds: DEFAULT_HUB_TASK_STATUS_CACHE_TTL_SECONDS,
|
|
163
176
|
} as const;
|