()
| 315 | pendingInterrupt = undefined; |
| 316 | }, |
| 317 | async markInterrupted() { |
| 318 | // Idempotent. Mark BEFORE any await so subsequent subscriber callbacks |
| 319 | // (including the RUN_ERROR that AG-UI fires when we abort) bail. |
| 320 | if (aborted) return; |
| 321 | aborted = true; |
| 322 | // Settle EVERY in-flight text stream. `ChunkedEditStream.append` |
| 323 | // schedules its placeholder post asynchronously (on setupPromise), so a |
| 324 | // stream that just received content may still report chunkCount === 0 |
| 325 | // until that post resolves. If we deleted such a stream without |
| 326 | // finishing it, its in-flight postPlaceholder would still resolve and |
| 327 | // leave a stray "…" message orphaned forever. `finish()` awaits |
| 328 | // setupPromise, so it deterministically creates-and-flushes any pending |
| 329 | // placeholder rather than abandoning it. |
| 330 | const tasks: Promise<void>[] = []; |
| 331 | for (const [id, stream] of Array.from(streams.entries())) { |
| 332 | const buf = buffers.get(id) ?? ""; |
| 333 | if (buf.trim().length > 0) { |
| 334 | // Real content: surface the interrupted marker on the partial reply |
| 335 | // before finishing. |
| 336 | stream.append(buf + INTERRUPTED_SUFFIX); |
| 337 | } |
| 338 | // Empty/whitespace buffer: just finish(). If nothing was ever posted |
| 339 | // it's a no-op; if a placeholder post is in flight it gets flushed/ |
| 340 | // edited rather than left as a stray "…". |
| 341 | tasks.push( |
| 342 | stream |
| 343 | .finish() |
| 344 | .catch((e) => |
| 345 | console.error("[bot-telegram] stream finalize failed:", e), |
| 346 | ), |
| 347 | ); |
| 348 | streams.delete(id); |
| 349 | finalised.add(id); |
| 350 | } |
| 351 | buffers.clear(); |
| 352 | await Promise.all(tasks); |
| 353 | // Clean up any tool-status placeholders whose END never arrived before |
| 354 | // the interrupt — mark them cancelled rather than leaving the stale |
| 355 | // "🔧 using <tool>…" line orphaned in the chat. |
| 356 | await drainToolStatuses((tool) => `⚠️ ${tool} (cancelled)`); |
| 357 | }, |
| 358 | }; |
| 359 | } |
nothing calls this directly
no test coverage detected
searching dependent graphs…