@ducci/jarvis 1.0.77 → 1.0.78
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/package.json +1 -1
- package/src/channels/telegram/index.js +230 -53
- package/src/server/tools.js +4 -1
package/package.json
CHANGED
|
@@ -98,15 +98,73 @@ export async function startTelegramChannel(config) {
|
|
|
98
98
|
const bot = new Bot(token);
|
|
99
99
|
const sessions = load();
|
|
100
100
|
|
|
101
|
-
// Tracks chats with an active agent run
|
|
102
|
-
//
|
|
101
|
+
// Tracks chats with an active agent run per slot.
|
|
102
|
+
// Keys are "chatId:slot" strings.
|
|
103
103
|
const isRunning = new Set();
|
|
104
|
-
const pendingMessages = new Map(); // chatId -> [{text, attachments, ts}]
|
|
104
|
+
const pendingMessages = new Map(); // "chatId:slot" -> [{text, attachments, ts}]
|
|
105
|
+
const runStartTimes = new Map(); // "chatId:slot" -> Date
|
|
106
|
+
|
|
107
|
+
// --- Slot helpers ---
|
|
108
|
+
// sessions[chatId] is either:
|
|
109
|
+
// - undefined (no session yet)
|
|
110
|
+
// - string (legacy: single session ID, treated as slot 1)
|
|
111
|
+
// - { active: number, slots: { "1": sessionId, "2": sessionId, ... } }
|
|
112
|
+
|
|
113
|
+
function getActiveSlot(chatId) {
|
|
114
|
+
const d = sessions[chatId];
|
|
115
|
+
if (!d || typeof d === 'string') return 1;
|
|
116
|
+
return d.active ?? 1;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function getSessionId(chatId, slot) {
|
|
120
|
+
const d = sessions[chatId];
|
|
121
|
+
if (!d) return null;
|
|
122
|
+
if (typeof d === 'string') return slot == 1 ? d : null;
|
|
123
|
+
return d.slots?.[String(slot)] ?? null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function setSessionId(chatId, slot, sessionId) {
|
|
127
|
+
const d = sessions[chatId];
|
|
128
|
+
if (!d || typeof d === 'string') {
|
|
129
|
+
const legacy = typeof d === 'string' ? d : null;
|
|
130
|
+
sessions[chatId] = { active: Number(slot), slots: {} };
|
|
131
|
+
if (legacy) sessions[chatId].slots['1'] = legacy;
|
|
132
|
+
}
|
|
133
|
+
if (sessionId === null) {
|
|
134
|
+
delete sessions[chatId].slots[String(slot)];
|
|
135
|
+
if (Object.keys(sessions[chatId].slots).length === 0) {
|
|
136
|
+
delete sessions[chatId];
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
sessions[chatId].slots[String(slot)] = sessionId;
|
|
140
|
+
}
|
|
141
|
+
save(sessions);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function setActiveSlot(chatId, slot) {
|
|
145
|
+
const d = sessions[chatId];
|
|
146
|
+
if (!d || typeof d === 'string') {
|
|
147
|
+
const legacy = typeof d === 'string' ? d : null;
|
|
148
|
+
sessions[chatId] = { active: Number(slot), slots: {} };
|
|
149
|
+
if (legacy) sessions[chatId].slots['1'] = legacy;
|
|
150
|
+
} else {
|
|
151
|
+
sessions[chatId].active = Number(slot);
|
|
152
|
+
}
|
|
153
|
+
save(sessions);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function slotKey(chatId, slot) {
|
|
157
|
+
return `${chatId}:${slot}`;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// --- Commands ---
|
|
105
161
|
|
|
106
162
|
await bot.api.setMyCommands([
|
|
107
|
-
{ command: 'new',
|
|
108
|
-
{ command: 'usage', description: '
|
|
109
|
-
{ command: 'stop',
|
|
163
|
+
{ command: 'new', description: 'Reset the active slot (fresh session)' },
|
|
164
|
+
{ command: 'usage', description: 'Token usage for the active slot' },
|
|
165
|
+
{ command: 'stop', description: 'Stop the running agent on the active slot' },
|
|
166
|
+
{ command: 'slots', description: 'Show all slots and their status' },
|
|
167
|
+
{ command: 'slot', description: 'Switch or delete a slot: /slot 2 or /slot del 2' },
|
|
110
168
|
]);
|
|
111
169
|
|
|
112
170
|
bot.command('usage', async (ctx) => {
|
|
@@ -114,7 +172,8 @@ export async function startTelegramChannel(config) {
|
|
|
114
172
|
if (!allowedUserIds.includes(userId)) return;
|
|
115
173
|
|
|
116
174
|
const chatId = ctx.chat.id;
|
|
117
|
-
const
|
|
175
|
+
const slot = getActiveSlot(chatId);
|
|
176
|
+
const sessionId = getSessionId(chatId, slot);
|
|
118
177
|
if (!sessionId) {
|
|
119
178
|
await ctx.reply('No active session. Send a message to start one.');
|
|
120
179
|
return;
|
|
@@ -134,7 +193,7 @@ export async function startTelegramChannel(config) {
|
|
|
134
193
|
? `\nCache read: ${cacheRead.toLocaleString()}\nCache written: ${cacheCreation.toLocaleString()}`
|
|
135
194
|
: '';
|
|
136
195
|
await ctx.reply(
|
|
137
|
-
`Token usage for
|
|
196
|
+
`Token usage for slot ${slot}:\nIn: ${u.prompt.toLocaleString()}\nOut: ${u.completion.toLocaleString()}\nTotal: ${total.toLocaleString()}${cacheLines}`
|
|
138
197
|
);
|
|
139
198
|
});
|
|
140
199
|
|
|
@@ -143,9 +202,11 @@ export async function startTelegramChannel(config) {
|
|
|
143
202
|
if (!allowedUserIds.includes(userId)) return;
|
|
144
203
|
|
|
145
204
|
const chatId = ctx.chat.id;
|
|
146
|
-
const
|
|
205
|
+
const slot = getActiveSlot(chatId);
|
|
206
|
+
const sessionId = getSessionId(chatId, slot);
|
|
207
|
+
const key = slotKey(chatId, slot);
|
|
147
208
|
|
|
148
|
-
if (!isRunning.has(
|
|
209
|
+
if (!isRunning.has(key) || !sessionId) {
|
|
149
210
|
await ctx.reply('Nothing is currently running.');
|
|
150
211
|
return;
|
|
151
212
|
}
|
|
@@ -160,24 +221,127 @@ export async function startTelegramChannel(config) {
|
|
|
160
221
|
if (!allowedUserIds.includes(userId)) return;
|
|
161
222
|
|
|
162
223
|
const chatId = ctx.chat.id;
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
224
|
+
const slot = getActiveSlot(chatId);
|
|
225
|
+
const key = slotKey(chatId, slot);
|
|
226
|
+
pendingMessages.delete(key);
|
|
227
|
+
const oldSessionId = getSessionId(chatId, slot);
|
|
228
|
+
if (oldSessionId) {
|
|
229
|
+
await appendTelegramChatLog(chatId, oldSessionId, 'SYSTEM', '--- /new: session reset ---');
|
|
230
|
+
setSessionId(chatId, slot, null);
|
|
231
|
+
console.log(`[telegram] session unlinked chat_id=${chatId} slot=${slot}`);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
await ctx.reply(`New session started on slot ${slot}.`);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
bot.command('slots', async (ctx) => {
|
|
238
|
+
const userId = ctx.from?.id;
|
|
239
|
+
if (!allowedUserIds.includes(userId)) return;
|
|
240
|
+
|
|
241
|
+
const chatId = ctx.chat.id;
|
|
242
|
+
const d = sessions[chatId];
|
|
243
|
+
const activeSlot = getActiveSlot(chatId);
|
|
244
|
+
|
|
245
|
+
const slotsMap = {};
|
|
246
|
+
if (typeof d === 'string') {
|
|
247
|
+
slotsMap['1'] = d;
|
|
248
|
+
} else if (d && d.slots) {
|
|
249
|
+
Object.assign(slotsMap, d.slots);
|
|
169
250
|
}
|
|
170
251
|
|
|
171
|
-
|
|
252
|
+
const slotNums = [...new Set(['1', ...Object.keys(slotsMap)])].sort((a, b) => Number(a) - Number(b));
|
|
253
|
+
|
|
254
|
+
const lines = ['<b>Slots:</b>'];
|
|
255
|
+
for (const sn of slotNums) {
|
|
256
|
+
const n = Number(sn);
|
|
257
|
+
const sid = slotsMap[sn] ?? null;
|
|
258
|
+
const key = slotKey(chatId, n);
|
|
259
|
+
const activeMarker = n === activeSlot ? ' ← aktiv' : '';
|
|
260
|
+
let statusIcon;
|
|
261
|
+
if (isRunning.has(key)) {
|
|
262
|
+
const startTime = runStartTimes.get(key);
|
|
263
|
+
let elapsed = '';
|
|
264
|
+
if (startTime) {
|
|
265
|
+
const secs = Math.floor((Date.now() - startTime.getTime()) / 1000);
|
|
266
|
+
const m = Math.floor(secs / 60);
|
|
267
|
+
const s = secs % 60;
|
|
268
|
+
elapsed = m > 0 ? ` (seit ${m}m ${s}s)` : ` (seit ${s}s)`;
|
|
269
|
+
}
|
|
270
|
+
statusIcon = `🟢 läuft${elapsed}`;
|
|
271
|
+
} else if (sid) {
|
|
272
|
+
statusIcon = '💬 bereit';
|
|
273
|
+
} else {
|
|
274
|
+
statusIcon = '➕ leer';
|
|
275
|
+
}
|
|
276
|
+
lines.push(`Slot ${n}: ${statusIcon}${activeMarker}`);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Always show one empty slot beyond the highest existing one
|
|
280
|
+
const maxSlot = Math.max(...slotNums.map(Number));
|
|
281
|
+
const nextSlot = maxSlot + 1;
|
|
282
|
+
if (!isRunning.has(slotKey(chatId, nextSlot)) && !slotsMap[String(nextSlot)]) {
|
|
283
|
+
lines.push(`Slot ${nextSlot}: ➕ leer`);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
await ctx.reply(lines.join('\n'), { parse_mode: 'HTML' });
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
bot.command('slot', async (ctx) => {
|
|
290
|
+
const userId = ctx.from?.id;
|
|
291
|
+
if (!allowedUserIds.includes(userId)) return;
|
|
292
|
+
|
|
293
|
+
const chatId = ctx.chat.id;
|
|
294
|
+
const args = (ctx.match || '').trim().split(/\s+/).filter(Boolean);
|
|
295
|
+
|
|
296
|
+
// /slot del N
|
|
297
|
+
if (args[0] === 'del') {
|
|
298
|
+
const n = parseInt(args[1], 10);
|
|
299
|
+
if (!n || n < 1) { await ctx.reply('Usage: /slot del <number>'); return; }
|
|
300
|
+
const key = slotKey(chatId, n);
|
|
301
|
+
if (isRunning.has(key) || pendingMessages.has(key)) {
|
|
302
|
+
await ctx.reply(`Slot ${n} ist gerade aktiv. Erst /stop, dann löschen.`);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
const oldSid = getSessionId(chatId, n);
|
|
306
|
+
if (oldSid) {
|
|
307
|
+
await appendTelegramChatLog(chatId, oldSid, 'SYSTEM', `--- /slot del ${n} ---`);
|
|
308
|
+
}
|
|
309
|
+
setSessionId(chatId, n, null);
|
|
310
|
+
pendingMessages.delete(key);
|
|
311
|
+
runStartTimes.delete(key);
|
|
312
|
+
if (getActiveSlot(chatId) === n) {
|
|
313
|
+
setActiveSlot(chatId, 1);
|
|
314
|
+
await ctx.reply(`Slot ${n} gelöscht. Zu Slot 1 gewechselt.`);
|
|
315
|
+
} else {
|
|
316
|
+
await ctx.reply(`Slot ${n} gelöscht.`);
|
|
317
|
+
}
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// /slot N — switch active slot
|
|
322
|
+
const n = parseInt(args[0], 10);
|
|
323
|
+
if (!n || n < 1) { await ctx.reply('Usage: /slot <number> oder /slot del <number>'); return; }
|
|
324
|
+
setActiveSlot(chatId, n);
|
|
325
|
+
const sid = getSessionId(chatId, n);
|
|
326
|
+
const key = slotKey(chatId, n);
|
|
327
|
+
let status;
|
|
328
|
+
if (isRunning.has(key)) {
|
|
329
|
+
status = '🟢 läuft';
|
|
330
|
+
} else if (sid) {
|
|
331
|
+
status = '💬 bereit (vorhandene Session)';
|
|
332
|
+
} else {
|
|
333
|
+
status = '➕ leer (neue Session beim nächsten Message)';
|
|
334
|
+
}
|
|
335
|
+
await ctx.reply(`Slot ${n} ist jetzt aktiv. Status: ${status}`);
|
|
172
336
|
});
|
|
173
337
|
|
|
174
338
|
// Runs one or more batches until the pending queue is drained.
|
|
175
339
|
// Each iteration takes all currently pending messages, merges them into a
|
|
176
340
|
// single user turn, calls handleChat once, and sends one response.
|
|
177
|
-
async function processQueue(api, chatId, firstBatch) {
|
|
341
|
+
async function processQueue(api, chatId, slot, firstBatch) {
|
|
178
342
|
let batch = firstBatch;
|
|
179
343
|
while (batch.length > 0) {
|
|
180
|
-
const sessionId =
|
|
344
|
+
const sessionId = getSessionId(chatId, slot) || null;
|
|
181
345
|
const combinedText = batch.length === 1
|
|
182
346
|
? batch[0].text
|
|
183
347
|
: batch.map(m => m.text).join('\n\n');
|
|
@@ -213,28 +377,30 @@ export async function startTelegramChannel(config) {
|
|
|
213
377
|
|
|
214
378
|
let lastCheckpointSent = null;
|
|
215
379
|
let result;
|
|
380
|
+
const key = slotKey(chatId, slot);
|
|
216
381
|
try {
|
|
217
382
|
result = await handleChat(config, sessionId, userText, allAttachments, async (checkpointResponse) => {
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
383
|
+
const rawText = typeof checkpointResponse === 'string' ? checkpointResponse : JSON.stringify(checkpointResponse);
|
|
384
|
+
const currentActive = getActiveSlot(chatId);
|
|
385
|
+
const prefixed = slot !== currentActive ? `[Slot ${slot}] ${rawText}` : rawText;
|
|
386
|
+
lastCheckpointSent = prefixed;
|
|
387
|
+
await appendTelegramChatLog(chatId, getSessionId(chatId, slot) || null, 'JARVIS', prefixed);
|
|
388
|
+
await sendMessage(api, chatId, prefixed, getSessionId(chatId, slot) || null);
|
|
222
389
|
});
|
|
223
390
|
} catch (e) {
|
|
224
|
-
console.error(`[telegram] agent error chat_id=${chatId}: ${e.message}`);
|
|
391
|
+
console.error(`[telegram] agent error chat_id=${chatId} slot=${slot}: ${e.message}`);
|
|
225
392
|
const errText = e.message
|
|
226
393
|
? `Sorry, something went wrong: ${e.message}`
|
|
227
394
|
: 'Sorry, something went wrong. Please try again.';
|
|
228
395
|
await api.sendMessage(chatId, errText).catch(() => {});
|
|
229
|
-
batch = pendingMessages.get(
|
|
230
|
-
pendingMessages.delete(
|
|
396
|
+
batch = pendingMessages.get(key) || [];
|
|
397
|
+
pendingMessages.delete(key);
|
|
231
398
|
continue;
|
|
232
399
|
}
|
|
233
400
|
|
|
234
|
-
if (!
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
console.log(`[telegram] session created sessionId=${result.sessionId.slice(0, 8)}`);
|
|
401
|
+
if (!getSessionId(chatId, slot)) {
|
|
402
|
+
setSessionId(chatId, slot, result.sessionId);
|
|
403
|
+
console.log(`[telegram] session created slot=${slot} sessionId=${result.sessionId.slice(0, 8)}`);
|
|
238
404
|
}
|
|
239
405
|
|
|
240
406
|
// Log each original message individually with its own timestamp
|
|
@@ -248,24 +414,27 @@ export async function startTelegramChannel(config) {
|
|
|
248
414
|
: result.response != null ? JSON.stringify(result.response, null, 2) : '';
|
|
249
415
|
const text = rawResponse.trim()
|
|
250
416
|
|| 'The agent encountered an error and could not produce a response. Please try again.';
|
|
417
|
+
// Prefix response with slot number if the user has switched away from this slot
|
|
418
|
+
const currentActive = getActiveSlot(chatId);
|
|
419
|
+
const displayText = slot !== currentActive ? `[Slot ${slot}] ${text}` : text;
|
|
251
420
|
// Skip sending if this response was already sent as a checkpoint update —
|
|
252
421
|
// intervention_required and zero-progress reuse the last checkpoint response
|
|
253
422
|
// as their finalResponse, which would otherwise cause a duplicate message.
|
|
254
|
-
if (
|
|
255
|
-
await appendTelegramChatLog(chatId, result.sessionId, 'JARVIS',
|
|
256
|
-
await sendMessage(api, chatId,
|
|
257
|
-
console.log(`[telegram] response sent chat_id=${chatId} length=${
|
|
423
|
+
if (displayText !== lastCheckpointSent) {
|
|
424
|
+
await appendTelegramChatLog(chatId, result.sessionId, 'JARVIS', displayText);
|
|
425
|
+
await sendMessage(api, chatId, displayText, result.sessionId);
|
|
426
|
+
console.log(`[telegram] response sent chat_id=${chatId} slot=${slot} length=${displayText.length}`);
|
|
258
427
|
} else {
|
|
259
|
-
console.log(`[telegram] skipped duplicate final response chat_id=${chatId}`);
|
|
428
|
+
console.log(`[telegram] skipped duplicate final response chat_id=${chatId} slot=${slot}`);
|
|
260
429
|
}
|
|
261
430
|
} catch (e) {
|
|
262
|
-
console.error(`[telegram] delivery error chat_id=${chatId}: ${e.message}`);
|
|
431
|
+
console.error(`[telegram] delivery error chat_id=${chatId} slot=${slot}: ${e.message}`);
|
|
263
432
|
await api.sendMessage(chatId, 'Sorry, something went wrong sending the response. Please try again.').catch(() => {});
|
|
264
433
|
}
|
|
265
434
|
|
|
266
435
|
// Drain any messages that arrived while we were running
|
|
267
|
-
batch = pendingMessages.get(
|
|
268
|
-
pendingMessages.delete(
|
|
436
|
+
batch = pendingMessages.get(key) || [];
|
|
437
|
+
pendingMessages.delete(key);
|
|
269
438
|
}
|
|
270
439
|
}
|
|
271
440
|
|
|
@@ -296,25 +465,29 @@ export async function startTelegramChannel(config) {
|
|
|
296
465
|
}
|
|
297
466
|
|
|
298
467
|
const entry = { text: ctx.message.caption || '', attachments: [attachment], ts };
|
|
468
|
+
const slot = getActiveSlot(chatId);
|
|
469
|
+
const key = slotKey(chatId, slot);
|
|
299
470
|
|
|
300
|
-
if (isRunning.has(
|
|
301
|
-
if (!pendingMessages.has(
|
|
302
|
-
pendingMessages.get(
|
|
303
|
-
console.log(`[telegram] buffered photo chat_id=${chatId} pending=${pendingMessages.get(
|
|
471
|
+
if (isRunning.has(key)) {
|
|
472
|
+
if (!pendingMessages.has(key)) pendingMessages.set(key, []);
|
|
473
|
+
pendingMessages.get(key).push(entry);
|
|
474
|
+
console.log(`[telegram] buffered photo chat_id=${chatId} slot=${slot} pending=${pendingMessages.get(key).length}`);
|
|
304
475
|
return;
|
|
305
476
|
}
|
|
306
477
|
|
|
307
|
-
isRunning.add(
|
|
478
|
+
isRunning.add(key);
|
|
479
|
+
runStartTimes.set(key, new Date());
|
|
308
480
|
await ctx.api.sendChatAction(chatId, 'typing');
|
|
309
481
|
const typingInterval = setInterval(() => {
|
|
310
482
|
ctx.api.sendChatAction(chatId, 'typing').catch(() => {});
|
|
311
483
|
}, 4000);
|
|
312
484
|
|
|
313
485
|
try {
|
|
314
|
-
await processQueue(ctx.api, chatId, [entry]);
|
|
486
|
+
await processQueue(ctx.api, chatId, slot, [entry]);
|
|
315
487
|
} finally {
|
|
316
488
|
clearInterval(typingInterval);
|
|
317
|
-
isRunning.delete(
|
|
489
|
+
isRunning.delete(key);
|
|
490
|
+
runStartTimes.delete(key);
|
|
318
491
|
}
|
|
319
492
|
});
|
|
320
493
|
|
|
@@ -327,26 +500,30 @@ export async function startTelegramChannel(config) {
|
|
|
327
500
|
const chatId = ctx.chat.id;
|
|
328
501
|
const ts = new Date().toISOString();
|
|
329
502
|
const entry = { text: ctx.message.text, attachments: [], ts };
|
|
503
|
+
const slot = getActiveSlot(chatId);
|
|
504
|
+
const key = slotKey(chatId, slot);
|
|
330
505
|
|
|
331
|
-
if (isRunning.has(
|
|
332
|
-
if (!pendingMessages.has(
|
|
333
|
-
pendingMessages.get(
|
|
334
|
-
console.log(`[telegram] buffered message chat_id=${chatId} pending=${pendingMessages.get(
|
|
506
|
+
if (isRunning.has(key)) {
|
|
507
|
+
if (!pendingMessages.has(key)) pendingMessages.set(key, []);
|
|
508
|
+
pendingMessages.get(key).push(entry);
|
|
509
|
+
console.log(`[telegram] buffered message chat_id=${chatId} slot=${slot} pending=${pendingMessages.get(key).length}`);
|
|
335
510
|
return;
|
|
336
511
|
}
|
|
337
512
|
|
|
338
|
-
isRunning.add(
|
|
339
|
-
|
|
513
|
+
isRunning.add(key);
|
|
514
|
+
runStartTimes.set(key, new Date());
|
|
515
|
+
console.log(`[telegram] incoming chat_id=${chatId} slot=${slot}`);
|
|
340
516
|
await ctx.api.sendChatAction(chatId, 'typing');
|
|
341
517
|
const typingInterval = setInterval(() => {
|
|
342
518
|
ctx.api.sendChatAction(chatId, 'typing').catch(() => {});
|
|
343
519
|
}, 4000);
|
|
344
520
|
|
|
345
521
|
try {
|
|
346
|
-
await processQueue(ctx.api, chatId, [entry]);
|
|
522
|
+
await processQueue(ctx.api, chatId, slot, [entry]);
|
|
347
523
|
} finally {
|
|
348
524
|
clearInterval(typingInterval);
|
|
349
|
-
isRunning.delete(
|
|
525
|
+
isRunning.delete(key);
|
|
526
|
+
runStartTimes.delete(key);
|
|
350
527
|
}
|
|
351
528
|
});
|
|
352
529
|
|
package/src/server/tools.js
CHANGED
|
@@ -543,7 +543,10 @@ const SEED_TOOLS = {
|
|
|
543
543
|
try {
|
|
544
544
|
const tgSessionsFile = path.join(process.env.HOME, '.jarvis/data/channels/telegram/sessions.json');
|
|
545
545
|
const tgSessions = JSON.parse(await fs.promises.readFile(tgSessionsFile, 'utf8').catch(() => '{}'));
|
|
546
|
-
const
|
|
546
|
+
const chatData = tgSessions[String(chatId)];
|
|
547
|
+
const sessionId = typeof chatData === 'string'
|
|
548
|
+
? chatData
|
|
549
|
+
: chatData?.slots?.[String(chatData?.active ?? 1)] ?? null;
|
|
547
550
|
const prefix = sessionId ? String(sessionId).slice(0, 8) : 'unknown';
|
|
548
551
|
const logDir = path.join(process.env.HOME, '.jarvis/telegram-chats');
|
|
549
552
|
const logFile = path.join(logDir, String(chatId) + '-' + prefix + '.log');
|