switchroom 0.13.22 → 0.13.24

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "switchroom",
3
- "version": "0.13.22",
3
+ "version": "0.13.24",
4
4
  "description": "Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -233,6 +233,34 @@ export function createAnswerStream(config: AnswerStreamConfig): AnswerStreamHand
233
233
  }
234
234
  }
235
235
 
236
+ /**
237
+ * Clear the in-progress sendMessageDraft (#1704). When the answer
238
+ * stream was using draft transport (DMs), Telegram leaves the draft
239
+ * sitting in the user's compose area until something replaces or
240
+ * clears it. On Telegram Desktop this blocks the user from typing —
241
+ * the compose field is occupied by the bot's draft preview.
242
+ *
243
+ * Every terminal path on the stream (materialize / stop / retract)
244
+ * must clear the draft. Best-effort: a failed clear is logged but
245
+ * not re-thrown — the worst case is a transient stale draft that
246
+ * Telegram's own 30 s draft expiry eventually mops up.
247
+ */
248
+ async function clearDraftBestEffort(): Promise<void> {
249
+ if (!usesDraftTransport || draftApi == null || draftId == null) return
250
+ try {
251
+ const params: { message_thread_id?: number } = {}
252
+ if (threadId != null) params.message_thread_id = threadId
253
+ await draftApi(
254
+ chatId,
255
+ draftId,
256
+ '',
257
+ Object.keys(params).length > 0 ? params : undefined,
258
+ )
259
+ } catch {
260
+ // Best-effort cleanup
261
+ }
262
+ }
263
+
236
264
  async function sendDraft(text: string): Promise<boolean> {
237
265
  if (!draftApi || draftId == null) return false
238
266
  try {
@@ -406,20 +434,7 @@ export function createAnswerStream(config: AnswerStreamConfig): AnswerStreamHand
406
434
  }
407
435
 
408
436
  // Clear draft so Telegram input area doesn't show stale text
409
- if (usesDraftTransport && draftApi != null && draftId != null) {
410
- try {
411
- const clearParams: { message_thread_id?: number } = {}
412
- if (threadId != null) clearParams.message_thread_id = threadId
413
- await draftApi(
414
- chatId,
415
- draftId,
416
- '',
417
- Object.keys(clearParams).length > 0 ? clearParams : undefined,
418
- )
419
- } catch {
420
- // Best-effort cleanup
421
- }
422
- }
437
+ await clearDraftBestEffort()
423
438
 
424
439
  // The text we want to materialize. Prefer pendingText (most recent
425
440
  // snapshot from the model) over lastSentText (what last reached the
@@ -528,6 +543,10 @@ export function createAnswerStream(config: AnswerStreamConfig): AnswerStreamHand
528
543
  stop(): void {
529
544
  stopped = true
530
545
  cancelScheduled()
546
+ // #1704: clear the compose-box draft. stop() is sync — fire and
547
+ // forget. A dropped clear falls back on Telegram's own 30 s
548
+ // draft expiry; the worst case is a transient stale preview.
549
+ void clearDraftBestEffort()
531
550
  },
532
551
 
533
552
  async retract(): Promise<void> {
@@ -539,6 +558,12 @@ export function createAnswerStream(config: AnswerStreamConfig): AnswerStreamHand
539
558
  if (inFlight) {
540
559
  try { await inFlight } catch { /* ignore */ }
541
560
  }
561
+ // #1704: clear the compose-box draft when this stream was using
562
+ // draft transport. Without this, Telegram Desktop leaves the
563
+ // draft sitting in the user's input area and blocks them from
564
+ // typing until the 30 s draft expiry. Awaited so a follow-up
565
+ // sendMessage on the same chat doesn't race a stale draft edit.
566
+ await clearDraftBestEffort()
542
567
  // Delete the preliminary message if one was sent and deleteMessage
543
568
  // is wired. Best-effort: failures are logged but not re-thrown.
544
569
  const msgId = streamMsgId