From 145f49b28a757c2838e7ce3e8d7e4e9f2941c24b Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 5 May 2026 18:46:32 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20persistent=20typing=20indicator=20?= =?UTF-8?q?=E2=80=94=20refreshes=20every=204s=20until=20first=20stream=20t?= =?UTF-8?q?oken?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- memories.md | 6 ++++++ src/bot/index.js | 22 ++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 memories.md diff --git a/memories.md b/memories.md new file mode 100644 index 00000000..6f9cdc91 --- /dev/null +++ b/memories.md @@ -0,0 +1,6 @@ + + +### Self-Challenge Results (2025-07-09) +- Demonstrated full self-challenge loop: write code → write tests → run tests → all pass ✅ +- 10/10 tests passed on math_utils.py (fibonacci, is_prime, factorial) +- Python 3.12 available at /usr/bin/python3, pytest 9.0.2 pre-installed diff --git a/src/bot/index.js b/src/bot/index.js index 0b477251..bf526f4a 100644 --- a/src/bot/index.js +++ b/src/bot/index.js @@ -1026,8 +1026,15 @@ export async function initBot(config, api, tools, skills, agents) { logger.info(`${prefix} ${user}: ${text.substring(0, 80)}…`); await queueRequest(key, text, async () => { - await ctx.api.sendChatAction(ctx.chat.id, 'typing'); + // ── Typing indicator: keep pinging until first stream token arrives ── + let firstTokenArrived = false; + const typingInterval = setInterval(async () => { + if (firstTokenArrived) return; + try { await ctx.api.sendChatAction(ctx.chat.id, 'typing'); } catch {} + }, 4000); // Telegram typing expires after 5s, refresh every 4s + await ctx.api.sendChatAction(ctx.chat.id, 'typing'); // initial ping + try { // ── Load conversation history for this chat ── const chatKey = conversation._key(ctx.chat.id, ctx.message?.message_thread_id); svc.currentChatId = ctx.chat.id; // Track for TTS auto-send @@ -1046,7 +1053,10 @@ export async function initBot(config, api, tools, skills, agents) { // Wrap chatWithAI with self-correction + streaming const chatWithCorrection = withSelfCorrection(async (msgs) => { - return await chatWithAI(msgs, { onDelta: (token) => consumer.onDelta(token) }); + return await chatWithAI(msgs, { onDelta: (token) => { + if (!firstTokenArrived) firstTokenArrived = true; + consumer.onDelta(token); + }}); }); const result = await chatWithCorrection(messages); @@ -1055,6 +1065,10 @@ export async function initBot(config, api, tools, skills, agents) { await conversation.add(chatKey, 'user', text); if (result) await conversation.add(chatKey, 'assistant', result); + // Stop typing indicator + firstTokenArrived = true; + clearInterval(typingInterval); + // Signal completion and wait for final edit consumer.finish(); await runPromise; @@ -1069,6 +1083,10 @@ export async function initBot(config, api, tools, skills, agents) { // ── Self-learning: extract patterns from this interaction ── await selfLearn(text, result, memory); + } finally { + // Always stop typing indicator, even on error + clearInterval(typingInterval); + } }); }