feat: implement real-time message editing streaming (like OpenClaw)
This commit is contained in:
@@ -46,44 +46,52 @@ export async function sendStreamingMessage(ctx, text, options = {}) {
|
|||||||
if (!text) return;
|
if (!text) return;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
delay = 100,
|
delay = 80,
|
||||||
minDelay = 50,
|
minDelay = 40,
|
||||||
maxDelay = 250,
|
maxDelay = 150,
|
||||||
charMode = false // Set to true for character-by-character, false for word-by-word
|
charMode = false // Set to true for character-by-character
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Send initial "typing..." indicator
|
// Send initial placeholder message
|
||||||
const sendTyping = () => ctx.api.sendChatAction(ctx.chat.id, 'typing').catch(() => {});
|
const sentMsg = await ctx.reply('⌨️ Typing...', { parse_mode: 'Markdown' });
|
||||||
|
|
||||||
|
let sentText = '';
|
||||||
|
|
||||||
if (charMode) {
|
if (charMode) {
|
||||||
// Character-by-character streaming
|
// Character-by-character streaming
|
||||||
let sentText = '';
|
|
||||||
const chars = text.split('');
|
const chars = text.split('');
|
||||||
|
|
||||||
for (const char of chars) {
|
for (const char of chars) {
|
||||||
sentText += char;
|
sentText += char;
|
||||||
|
|
||||||
// Send message with the accumulated text
|
// Edit the message in place
|
||||||
await ctx.reply(sentText, { parse_mode: 'Markdown' });
|
await ctx.api.editMessageText(sentText, {
|
||||||
|
message_id: sentMsg.message_id,
|
||||||
|
chat_id: sentMsg.chat.id,
|
||||||
|
parse_mode: 'Markdown'
|
||||||
|
});
|
||||||
|
|
||||||
// Random delay between min and max
|
// Random delay between min and max
|
||||||
const delayMs = minDelay + Math.random() * (maxDelay - minDelay);
|
const delayMs = minDelay + Math.random() * (maxDelay - minDelay);
|
||||||
await new Promise(resolve => setTimeout(resolve, delayMs));
|
await new Promise(resolve => setTimeout(resolve, delayMs));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Word-by-word streaming (default)
|
// Word-by-word streaming
|
||||||
const words = text.split(' ');
|
const words = text.split(' ');
|
||||||
let sentText = '';
|
|
||||||
|
|
||||||
for (let i = 0; i < words.length; i++) {
|
for (let i = 0; i < words.length; i++) {
|
||||||
sentText += (i > 0 ? ' ' : '') + words[i];
|
sentText += (i > 0 ? ' ' : '') + words[i];
|
||||||
|
|
||||||
// Send accumulated text
|
// Edit the message in place
|
||||||
await ctx.reply(sentText, { parse_mode: 'Markdown' });
|
await ctx.api.editMessageText(sentText, {
|
||||||
|
message_id: sentMsg.message_id,
|
||||||
|
chat_id: sentMsg.chat.id,
|
||||||
|
parse_mode: 'Markdown'
|
||||||
|
});
|
||||||
|
|
||||||
// Variable delay based on word length
|
// Variable delay based on word length
|
||||||
const wordDelay = Math.max(minDelay, Math.min(maxDelay, delay + words[i].length * 10));
|
const wordDelay = Math.max(minDelay, Math.min(maxDelay, delay + words[i].length * 8));
|
||||||
await new Promise(resolve => setTimeout(resolve, wordDelay));
|
await new Promise(resolve => setTimeout(resolve, wordDelay));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user