instar 0.8.8 → 0.8.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.
|
@@ -36,11 +36,13 @@ export declare class WebSocketManager {
|
|
|
36
36
|
private sessionManager;
|
|
37
37
|
private state;
|
|
38
38
|
private authToken?;
|
|
39
|
+
private registryPath?;
|
|
39
40
|
constructor(options: {
|
|
40
41
|
server: HttpServer;
|
|
41
42
|
sessionManager: SessionManager;
|
|
42
43
|
state: StateManager;
|
|
43
44
|
authToken?: string;
|
|
45
|
+
instarDir?: string;
|
|
44
46
|
});
|
|
45
47
|
private authenticate;
|
|
46
48
|
private verifyToken;
|
|
@@ -50,6 +52,12 @@ export declare class WebSocketManager {
|
|
|
50
52
|
* Uses diff-based approach: only sends new content since last capture.
|
|
51
53
|
*/
|
|
52
54
|
private startStreaming;
|
|
55
|
+
/**
|
|
56
|
+
* Resolve display names by cross-referencing the topic-session registry.
|
|
57
|
+
* Maps tmux session names to their Telegram topic names.
|
|
58
|
+
*/
|
|
59
|
+
private getTopicDisplayNames;
|
|
60
|
+
private buildSessionList;
|
|
53
61
|
private sendSessionList;
|
|
54
62
|
private broadcastSessionList;
|
|
55
63
|
private clientId;
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import { WebSocketServer, WebSocket } from 'ws';
|
|
27
27
|
import { createHash, timingSafeEqual } from 'node:crypto';
|
|
28
|
+
import fs from 'node:fs';
|
|
29
|
+
import path from 'node:path';
|
|
28
30
|
export class WebSocketManager {
|
|
29
31
|
wss;
|
|
30
32
|
clients = new Map();
|
|
@@ -35,10 +37,14 @@ export class WebSocketManager {
|
|
|
35
37
|
sessionManager;
|
|
36
38
|
state;
|
|
37
39
|
authToken;
|
|
40
|
+
registryPath;
|
|
38
41
|
constructor(options) {
|
|
39
42
|
this.sessionManager = options.sessionManager;
|
|
40
43
|
this.state = options.state;
|
|
41
44
|
this.authToken = options.authToken;
|
|
45
|
+
if (options.instarDir) {
|
|
46
|
+
this.registryPath = path.join(options.instarDir, 'topic-session-registry.json');
|
|
47
|
+
}
|
|
42
48
|
this.wss = new WebSocketServer({
|
|
43
49
|
noServer: true,
|
|
44
50
|
});
|
|
@@ -226,32 +232,52 @@ export class WebSocketManager {
|
|
|
226
232
|
}, 500);
|
|
227
233
|
this.streamInterval.unref();
|
|
228
234
|
}
|
|
229
|
-
|
|
235
|
+
/**
|
|
236
|
+
* Resolve display names by cross-referencing the topic-session registry.
|
|
237
|
+
* Maps tmux session names to their Telegram topic names.
|
|
238
|
+
*/
|
|
239
|
+
getTopicDisplayNames() {
|
|
240
|
+
const map = new Map();
|
|
241
|
+
if (!this.registryPath)
|
|
242
|
+
return map;
|
|
243
|
+
try {
|
|
244
|
+
const data = JSON.parse(fs.readFileSync(this.registryPath, 'utf-8'));
|
|
245
|
+
const topicToSession = data.topicToSession || {};
|
|
246
|
+
const topicToName = data.topicToName || {};
|
|
247
|
+
// Build reverse map: tmux session name → topic display name
|
|
248
|
+
for (const [topicId, tmuxSession] of Object.entries(topicToSession)) {
|
|
249
|
+
const name = topicToName[topicId];
|
|
250
|
+
if (name) {
|
|
251
|
+
map.set(tmuxSession, name);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
// Registry missing or corrupt — skip
|
|
257
|
+
}
|
|
258
|
+
return map;
|
|
259
|
+
}
|
|
260
|
+
buildSessionList() {
|
|
230
261
|
const running = this.sessionManager.listRunningSessions();
|
|
231
|
-
const
|
|
262
|
+
const displayNames = this.getTopicDisplayNames();
|
|
263
|
+
return running.map(s => ({
|
|
232
264
|
id: s.id,
|
|
233
|
-
name: s.name,
|
|
265
|
+
name: displayNames.get(s.tmuxSession) || s.name,
|
|
234
266
|
tmuxSession: s.tmuxSession,
|
|
235
267
|
status: s.status,
|
|
236
268
|
startedAt: s.startedAt,
|
|
237
269
|
jobSlug: s.jobSlug,
|
|
238
270
|
model: s.model,
|
|
239
271
|
}));
|
|
272
|
+
}
|
|
273
|
+
sendSessionList(ws) {
|
|
274
|
+
const sessions = this.buildSessionList();
|
|
240
275
|
this.send(ws, { type: 'sessions', sessions });
|
|
241
276
|
}
|
|
242
277
|
broadcastSessionList() {
|
|
243
278
|
if (this.clients.size === 0)
|
|
244
279
|
return;
|
|
245
|
-
const
|
|
246
|
-
const sessions = running.map(s => ({
|
|
247
|
-
id: s.id,
|
|
248
|
-
name: s.name,
|
|
249
|
-
tmuxSession: s.tmuxSession,
|
|
250
|
-
status: s.status,
|
|
251
|
-
startedAt: s.startedAt,
|
|
252
|
-
jobSlug: s.jobSlug,
|
|
253
|
-
model: s.model,
|
|
254
|
-
}));
|
|
280
|
+
const sessions = this.buildSessionList();
|
|
255
281
|
const msg = JSON.stringify({ type: 'sessions', sessions });
|
|
256
282
|
for (const client of this.clients.values()) {
|
|
257
283
|
if (client.ws.readyState === WebSocket.OPEN) {
|