@dmsdc-ai/aigentry-telepty 0.1.41 → 0.1.42
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/daemon.js +52 -10
- package/package.json +1 -1
package/daemon.js
CHANGED
|
@@ -143,6 +143,7 @@ app.post('/api/sessions/spawn', (req, res) => {
|
|
|
143
143
|
command,
|
|
144
144
|
cwd,
|
|
145
145
|
createdAt: new Date().toISOString(),
|
|
146
|
+
lastActivityAt: new Date().toISOString(),
|
|
146
147
|
clients: new Set(),
|
|
147
148
|
isClosing: false
|
|
148
149
|
};
|
|
@@ -210,6 +211,7 @@ app.post('/api/sessions/register', (req, res) => {
|
|
|
210
211
|
command: command || 'wrapped',
|
|
211
212
|
cwd,
|
|
212
213
|
createdAt: new Date().toISOString(),
|
|
214
|
+
lastActivityAt: new Date().toISOString(),
|
|
213
215
|
clients: new Set(),
|
|
214
216
|
isClosing: false
|
|
215
217
|
};
|
|
@@ -252,14 +254,24 @@ app.post('/api/sessions/register', (req, res) => {
|
|
|
252
254
|
});
|
|
253
255
|
|
|
254
256
|
app.get('/api/sessions', (req, res) => {
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
257
|
+
const idleGt = req.query.idle_gt ? Number(req.query.idle_gt) : null;
|
|
258
|
+
const now = Date.now();
|
|
259
|
+
let list = Object.entries(sessions).map(([id, session]) => {
|
|
260
|
+
const idleSeconds = session.lastActivityAt ? Math.floor((now - new Date(session.lastActivityAt).getTime()) / 1000) : null;
|
|
261
|
+
return {
|
|
262
|
+
id,
|
|
263
|
+
type: session.type || 'spawned',
|
|
264
|
+
command: session.command,
|
|
265
|
+
cwd: session.cwd,
|
|
266
|
+
createdAt: session.createdAt,
|
|
267
|
+
lastActivityAt: session.lastActivityAt || null,
|
|
268
|
+
idleSeconds,
|
|
269
|
+
active_clients: session.clients.size
|
|
270
|
+
};
|
|
271
|
+
});
|
|
272
|
+
if (idleGt !== null) {
|
|
273
|
+
list = list.filter(s => s.idleSeconds !== null && s.idleSeconds > idleGt);
|
|
274
|
+
}
|
|
263
275
|
res.json(list);
|
|
264
276
|
});
|
|
265
277
|
|
|
@@ -268,6 +280,7 @@ app.get('/api/sessions/:id', (req, res) => {
|
|
|
268
280
|
const resolvedId = resolveSessionAlias(requestedId);
|
|
269
281
|
if (!resolvedId) return res.status(404).json({ error: 'Session not found' });
|
|
270
282
|
const session = sessions[resolvedId];
|
|
283
|
+
const idleSeconds = session.lastActivityAt ? Math.floor((Date.now() - new Date(session.lastActivityAt).getTime()) / 1000) : null;
|
|
271
284
|
res.json({
|
|
272
285
|
id: resolvedId,
|
|
273
286
|
alias: requestedId !== resolvedId ? requestedId : null,
|
|
@@ -275,6 +288,8 @@ app.get('/api/sessions/:id', (req, res) => {
|
|
|
275
288
|
command: session.command,
|
|
276
289
|
cwd: session.cwd,
|
|
277
290
|
createdAt: session.createdAt,
|
|
291
|
+
lastActivityAt: session.lastActivityAt || null,
|
|
292
|
+
idleSeconds,
|
|
278
293
|
active_clients: session.clients ? session.clients.size : 0,
|
|
279
294
|
lastInjectFrom: session.lastInjectFrom || null,
|
|
280
295
|
lastInjectReplyTo: session.lastInjectReplyTo || null
|
|
@@ -611,6 +626,7 @@ app.post('/api/sessions/:id/inject', (req, res) => {
|
|
|
611
626
|
if (from) session.lastInjectFrom = from;
|
|
612
627
|
if (reply_to) session.lastInjectReplyTo = reply_to;
|
|
613
628
|
if (thread_id) session.lastThreadId = thread_id;
|
|
629
|
+
session.lastActivityAt = new Date().toISOString();
|
|
614
630
|
|
|
615
631
|
// Auto-prepend [from:] [reply-to:] header if from is set and not already in prompt
|
|
616
632
|
let finalPrompt = prompt;
|
|
@@ -1037,8 +1053,11 @@ const server = app.listen(PORT, HOST, () => {
|
|
|
1037
1053
|
console.log(`🚀 aigentry-telepty daemon listening on http://${HOST}:${PORT}`);
|
|
1038
1054
|
});
|
|
1039
1055
|
|
|
1056
|
+
const IDLE_THRESHOLD_SECONDS = 60;
|
|
1040
1057
|
setInterval(() => {
|
|
1058
|
+
const now = Date.now();
|
|
1041
1059
|
for (const [id, session] of Object.entries(sessions)) {
|
|
1060
|
+
const idleSeconds = session.lastActivityAt ? Math.floor((now - new Date(session.lastActivityAt).getTime()) / 1000) : null;
|
|
1042
1061
|
const healthMsg = JSON.stringify({
|
|
1043
1062
|
type: 'session_health',
|
|
1044
1063
|
session_id: id,
|
|
@@ -1046,13 +1065,34 @@ setInterval(() => {
|
|
|
1046
1065
|
alive: session.type === 'wrapped' ? (session.ownerWs && session.ownerWs.readyState === 1) : (session.ptyProcess && !session.ptyProcess.killed),
|
|
1047
1066
|
pid: session.ptyProcess?.pid || null,
|
|
1048
1067
|
type: session.type,
|
|
1049
|
-
clients: session.clients ? session.clients.size : 0
|
|
1068
|
+
clients: session.clients ? session.clients.size : 0,
|
|
1069
|
+
idleSeconds
|
|
1050
1070
|
},
|
|
1051
1071
|
timestamp: new Date().toISOString()
|
|
1052
1072
|
});
|
|
1053
1073
|
busClients.forEach(client => {
|
|
1054
1074
|
if (client.readyState === 1) client.send(healthMsg);
|
|
1055
1075
|
});
|
|
1076
|
+
|
|
1077
|
+
// Emit session.idle when idle exceeds threshold
|
|
1078
|
+
if (idleSeconds !== null && idleSeconds >= IDLE_THRESHOLD_SECONDS && !session._idleEmitted) {
|
|
1079
|
+
session._idleEmitted = true;
|
|
1080
|
+
const idleMsg = JSON.stringify({
|
|
1081
|
+
type: 'session.idle',
|
|
1082
|
+
session_id: id,
|
|
1083
|
+
idleSeconds,
|
|
1084
|
+
lastActivityAt: session.lastActivityAt,
|
|
1085
|
+
timestamp: new Date().toISOString()
|
|
1086
|
+
});
|
|
1087
|
+
busClients.forEach(client => {
|
|
1088
|
+
if (client.readyState === 1) client.send(idleMsg);
|
|
1089
|
+
});
|
|
1090
|
+
console.log(`[IDLE] Session ${id} idle for ${idleSeconds}s`);
|
|
1091
|
+
}
|
|
1092
|
+
// Reset idle flag when activity resumes
|
|
1093
|
+
if (idleSeconds !== null && idleSeconds < IDLE_THRESHOLD_SECONDS) {
|
|
1094
|
+
session._idleEmitted = false;
|
|
1095
|
+
}
|
|
1056
1096
|
}
|
|
1057
1097
|
}, 10000);
|
|
1058
1098
|
|
|
@@ -1085,6 +1125,7 @@ wss.on('connection', (ws, req) => {
|
|
|
1085
1125
|
command: 'wrapped',
|
|
1086
1126
|
cwd: process.cwd(),
|
|
1087
1127
|
createdAt: new Date().toISOString(),
|
|
1128
|
+
lastActivityAt: new Date().toISOString(),
|
|
1088
1129
|
clients: new Set([ws]),
|
|
1089
1130
|
isClosing: false
|
|
1090
1131
|
};
|
|
@@ -1123,8 +1164,9 @@ wss.on('connection', (ws, req) => {
|
|
|
1123
1164
|
|
|
1124
1165
|
if (activeSession.type === 'wrapped') {
|
|
1125
1166
|
if (ws === activeSession.ownerWs) {
|
|
1126
|
-
// Owner sending output -> broadcast to other clients
|
|
1167
|
+
// Owner sending output -> broadcast to other clients + update activity
|
|
1127
1168
|
if (type === 'output') {
|
|
1169
|
+
activeSession.lastActivityAt = new Date().toISOString();
|
|
1128
1170
|
activeSession.clients.forEach(client => {
|
|
1129
1171
|
if (client !== ws && client.readyState === 1) {
|
|
1130
1172
|
client.send(JSON.stringify({ type: 'output', data }));
|