@delt/claude-alarm 1.3.0 → 1.4.0
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/dist/cli.js +178 -49
- package/dist/cli.js.map +1 -1
- package/dist/codex/main.js +161 -32
- package/dist/codex/main.js.map +1 -1
- package/dist/dashboard/index.html +77 -46
- package/dist/hub/server.js +56 -31
- package/dist/hub/server.js.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.js +56 -31
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/dashboard/index.html +77 -46
package/dist/index.d.ts
CHANGED
|
@@ -49,6 +49,7 @@ type ChannelMessage = {
|
|
|
49
49
|
title: string;
|
|
50
50
|
message: string;
|
|
51
51
|
level?: NotifyLevel;
|
|
52
|
+
to?: MessageSource;
|
|
52
53
|
} | {
|
|
53
54
|
type: 'reply';
|
|
54
55
|
sessionId: string;
|
|
@@ -78,6 +79,10 @@ type ChannelMessage = {
|
|
|
78
79
|
sessionId: string;
|
|
79
80
|
reason: string;
|
|
80
81
|
withText: boolean;
|
|
82
|
+
} | {
|
|
83
|
+
type: 'message_rejected';
|
|
84
|
+
sessionId: string;
|
|
85
|
+
reason: string;
|
|
81
86
|
} | {
|
|
82
87
|
type: 'sessions_list';
|
|
83
88
|
sessions: SessionInfo[];
|
|
@@ -321,8 +326,8 @@ declare class TelegramBot {
|
|
|
321
326
|
private polling;
|
|
322
327
|
private pollTimer;
|
|
323
328
|
private messageSessionMap;
|
|
324
|
-
onMessageToSession?: (sessionId: string, content: string) =>
|
|
325
|
-
onImageToSession?: (sessionId: string, imagePath: string, mimeType: string, caption?: string) =>
|
|
329
|
+
onMessageToSession?: (sessionId: string, content: string) => boolean;
|
|
330
|
+
onImageToSession?: (sessionId: string, imagePath: string, mimeType: string, caption?: string) => boolean;
|
|
326
331
|
onPermissionVerdict?: (sessionId: string, requestId: string, behavior: 'allow' | 'deny') => void;
|
|
327
332
|
onChoiceVerdict?: (sessionId: string, requestId: string, choiceId: string) => void;
|
|
328
333
|
private choiceTokens;
|
|
@@ -345,6 +350,7 @@ declare class TelegramBot {
|
|
|
345
350
|
private scheduleNextPoll;
|
|
346
351
|
private handleIncomingMessage;
|
|
347
352
|
private deliverToSession;
|
|
353
|
+
private deliverPending;
|
|
348
354
|
private deliverPhotoToSession;
|
|
349
355
|
private deliverPhotoToSessionByFileId;
|
|
350
356
|
private photoNotDelivered;
|
package/dist/index.js
CHANGED
|
@@ -249,6 +249,7 @@ var MAX_SELECTIONS = 20;
|
|
|
249
249
|
var MAX_VISIBLE_CHARS = 4e3;
|
|
250
250
|
var TRUNCATED = "\u2026(truncated)";
|
|
251
251
|
var MAX_PHOTO_BYTES = 10 * 1024 * 1024;
|
|
252
|
+
var NO_LONGER_CONNECTED = "the session is no longer connected";
|
|
252
253
|
function visibleLength(html) {
|
|
253
254
|
return html.replace(/<[^>]*>/g, "").replace(/&(?:amp|lt|gt);/g, "&").length;
|
|
254
255
|
}
|
|
@@ -422,13 +423,7 @@ ${TRUNCATED}`);
|
|
|
422
423
|
this.selections.delete(latest);
|
|
423
424
|
const session = this.pendingSession(pending, parseInt(selectMatch[1], 10) - 1);
|
|
424
425
|
if (session) {
|
|
425
|
-
|
|
426
|
-
if (pending.photoFileId) {
|
|
427
|
-
delivered = await this.deliverPhotoToSessionByFileId(session.id, pending.photoFileId, pending.caption);
|
|
428
|
-
} else if (pending.text) {
|
|
429
|
-
this.deliverToSession(session.id, pending.text);
|
|
430
|
-
}
|
|
431
|
-
if (delivered) this.sendMessage(`Sent to [${this.getLabel(session)}]`);
|
|
426
|
+
if (await this.deliverPending(session.id, pending)) this.sendMessage(`Sent to [${this.getLabel(session)}]`);
|
|
432
427
|
} else {
|
|
433
428
|
this.sendMessage("Invalid session number.");
|
|
434
429
|
}
|
|
@@ -470,9 +465,13 @@ ${TRUNCATED}`);
|
|
|
470
465
|
this.sendMessage("Multiple sessions active. Select one:", void 0, { inline_keyboard: rows });
|
|
471
466
|
}
|
|
472
467
|
deliverToSession(sessionId, content) {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
468
|
+
const delivered = this.onMessageToSession?.(sessionId, content) === true;
|
|
469
|
+
if (!delivered) void this.sendMessage(`Not delivered: ${NO_LONGER_CONNECTED}`);
|
|
470
|
+
return delivered;
|
|
471
|
+
}
|
|
472
|
+
async deliverPending(sessionId, pending) {
|
|
473
|
+
if (pending.photoFileId) return this.deliverPhotoToSessionByFileId(sessionId, pending.photoFileId, pending.caption);
|
|
474
|
+
return pending.text ? this.deliverToSession(sessionId, pending.text) : false;
|
|
476
475
|
}
|
|
477
476
|
async deliverPhotoToSession(sessionId, photos, caption) {
|
|
478
477
|
const largest = photos[photos.length - 1];
|
|
@@ -504,8 +503,19 @@ ${TRUNCATED}`);
|
|
|
504
503
|
const filePath = path2.join(UPLOADS_DIR, filename);
|
|
505
504
|
fs.writeFileSync(filePath, buffer);
|
|
506
505
|
logger.info(`Telegram photo saved: ${filename} (${buffer.length} bytes)`);
|
|
507
|
-
|
|
508
|
-
|
|
506
|
+
let accepted = false;
|
|
507
|
+
try {
|
|
508
|
+
accepted = this.onImageToSession?.(sessionId, filePath, mimeType, caption) === true;
|
|
509
|
+
} catch (err) {
|
|
510
|
+
logger.warn(`Telegram photo hand-off failed: ${err.message}`);
|
|
511
|
+
}
|
|
512
|
+
if (!accepted) {
|
|
513
|
+
try {
|
|
514
|
+
fs.unlinkSync(filePath);
|
|
515
|
+
} catch {
|
|
516
|
+
}
|
|
517
|
+
this.photoNotDelivered(NO_LONGER_CONNECTED);
|
|
518
|
+
return false;
|
|
509
519
|
}
|
|
510
520
|
setTimeout(() => {
|
|
511
521
|
try {
|
|
@@ -513,7 +523,7 @@ ${TRUNCATED}`);
|
|
|
513
523
|
} catch {
|
|
514
524
|
}
|
|
515
525
|
}, 5 * 60 * 1e3).unref();
|
|
516
|
-
return
|
|
526
|
+
return true;
|
|
517
527
|
} catch (err) {
|
|
518
528
|
logger.warn(`Telegram photo download failed: ${err.message}`);
|
|
519
529
|
this.photoNotDelivered("the download failed");
|
|
@@ -708,15 +718,10 @@ ${label}`);
|
|
|
708
718
|
return;
|
|
709
719
|
}
|
|
710
720
|
this.selections.delete(selectionId);
|
|
711
|
-
if (pending
|
|
712
|
-
|
|
713
|
-
if (
|
|
714
|
-
|
|
715
|
-
if (query.message) await this.removeButtons(query.message.chat.id, query.message.message_id);
|
|
716
|
-
return;
|
|
717
|
-
}
|
|
718
|
-
} else if (pending.text) {
|
|
719
|
-
this.deliverToSession(session.id, pending.text);
|
|
721
|
+
if (!await this.deliverPending(session.id, pending)) {
|
|
722
|
+
await this.answerCallbackQuery(query.id, pending.photoFileId ? "Photo not delivered" : "Not delivered");
|
|
723
|
+
if (query.message) await this.removeButtons(query.message.chat.id, query.message.message_id);
|
|
724
|
+
return;
|
|
720
725
|
}
|
|
721
726
|
await this.answerCallbackQuery(query.id, `Sent to ${this.getLabel(session)}`);
|
|
722
727
|
if (query.message) {
|
|
@@ -1495,7 +1500,16 @@ var HubServer = class {
|
|
|
1495
1500
|
this.sessions.updateActivity(msg.sessionId);
|
|
1496
1501
|
const notifySession = this.sessions.get(msg.sessionId);
|
|
1497
1502
|
const notifyLabel = this.getSessionLabel(notifySession);
|
|
1498
|
-
|
|
1503
|
+
const notifyTitle = `[${notifyLabel}] ${msg.title}`;
|
|
1504
|
+
if (msg.to === "api") {
|
|
1505
|
+
logger.info(`${notifyTitle}: ${msg.message}`);
|
|
1506
|
+
break;
|
|
1507
|
+
}
|
|
1508
|
+
if (msg.to === "telegram") {
|
|
1509
|
+
void this.telegramBot?.sendNotification(msg.sessionId, notifyLabel, notifyTitle, msg.message);
|
|
1510
|
+
break;
|
|
1511
|
+
}
|
|
1512
|
+
if (msg.to !== "dashboard") this.notifier.notifyWithSession(msg.sessionId, notifyLabel, notifyTitle, msg.message, msg.level ?? "info");
|
|
1499
1513
|
this.broadcastToDashboards({
|
|
1500
1514
|
type: "notification",
|
|
1501
1515
|
sessionId: msg.sessionId,
|
|
@@ -1697,6 +1711,11 @@ var HubServer = class {
|
|
|
1697
1711
|
const channelWs = this.channelSockets.get(msg.sessionId);
|
|
1698
1712
|
if (channelWs?.readyState === WebSocket.OPEN) {
|
|
1699
1713
|
channelWs.send(JSON.stringify({ ...msg, source: "dashboard" }));
|
|
1714
|
+
} else {
|
|
1715
|
+
const reason = "the session is not connected";
|
|
1716
|
+
logger.warn(`Message rejected for ${msg.sessionId}: ${reason}`);
|
|
1717
|
+
const rejected = { type: "message_rejected", sessionId: msg.sessionId, reason };
|
|
1718
|
+
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify(rejected));
|
|
1700
1719
|
}
|
|
1701
1720
|
} else if (msg.type === "image_upload") {
|
|
1702
1721
|
this.handleImageUpload(ws, msg);
|
|
@@ -1822,19 +1841,25 @@ var HubServer = class {
|
|
|
1822
1841
|
this.telegramBot.getSessions = () => this.sessions.getAll();
|
|
1823
1842
|
this.telegramBot.onMessageToSession = (sessionId, content) => {
|
|
1824
1843
|
const channelWs = this.channelSockets.get(sessionId);
|
|
1825
|
-
if (channelWs?.readyState
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
logger.info(`Telegram message forwarded to session: ${sessionId}`);
|
|
1844
|
+
if (channelWs?.readyState !== WebSocket.OPEN) {
|
|
1845
|
+
logger.warn(`Telegram message not delivered to ${sessionId}: the session is not connected`);
|
|
1846
|
+
return false;
|
|
1829
1847
|
}
|
|
1848
|
+
const msg = { type: "message_to_session", sessionId, content, source: "telegram" };
|
|
1849
|
+
channelWs.send(JSON.stringify(msg));
|
|
1850
|
+
logger.info(`Telegram message forwarded to session: ${sessionId}`);
|
|
1851
|
+
return true;
|
|
1830
1852
|
};
|
|
1831
1853
|
this.telegramBot.onImageToSession = (sessionId, imagePath, mimeType, caption) => {
|
|
1832
1854
|
const channelWs = this.channelSockets.get(sessionId);
|
|
1833
|
-
if (channelWs?.readyState
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
logger.info(`Telegram photo forwarded to session: ${sessionId}`);
|
|
1855
|
+
if (channelWs?.readyState !== WebSocket.OPEN) {
|
|
1856
|
+
logger.warn(`Telegram photo not delivered to ${sessionId}: the session is not connected`);
|
|
1857
|
+
return false;
|
|
1837
1858
|
}
|
|
1859
|
+
const msg = { type: "image_to_session", sessionId, imagePath, mimeType, content: caption, source: "telegram" };
|
|
1860
|
+
channelWs.send(JSON.stringify(msg));
|
|
1861
|
+
logger.info(`Telegram photo forwarded to session: ${sessionId}`);
|
|
1862
|
+
return true;
|
|
1838
1863
|
};
|
|
1839
1864
|
this.telegramBot.onPermissionVerdict = (sessionId, requestId, behavior) => {
|
|
1840
1865
|
if (this.forwardPermissionResponse({ sessionId, requestId, behavior })) {
|