* fix(discord): guard progress draft collapse to prevent re-collapse on cleaned stream
Commit 86ea382 added a progressDraftStartedBeforeFinal latch that snapshots
hasStarted at markFinalReplyStarted time. This correctly preserves collapse
eligibility when an abort cancels the compositor gate before
shouldCollapseProgressDraft runs.
However the latch was never cleared. After markPreviewFinalized turned the
draft into a summary, hasProgressDraftStarted remained true permanently. In
multi-tool turns with multiple final-payload deliveries, this caused
shouldCollapseProgressDraft to re-trigger collapse on an already-cleaned or
sealed draft stream, corrupting downstream delivery state and causing tool
results to render as image content blocks instead of text.
Fix: add a progressDraftCollapsed guard set by markPreviewFinalized that
prevents hasProgressDraftStarted from returning true after the draft has been
collapsed into a summary. Reset the guard on handleAssistantMessageBoundary
so followup/queued turns start fresh.
Per Discord channel session, all tool results rendered as image content
blocks. Model received (see attached image) placeholders instead of text.
Fixes#100782
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(discord): use valid table/chunk mode literals in collapse-guard tests
* test(discord): add abort-race gate-cancellation latch survival test
* fix(discord): consume progress draft collapse once
Co-authored-by: xialonglee <li.xialong@xydigit.com>
* fix(discord): retain progress receipt on retry
Co-authored-by: xialonglee <li.xialong@xydigit.com>
* fix(discord): rearm queued progress drafts
Co-authored-by: xialonglee <li.xialong@xydigit.com>
* test(discord): assert progress lifecycle outcomes
Co-authored-by: xialonglee <li.xialong@xydigit.com>
* fix(discord): reset queued progress turn state
Co-authored-by: xialonglee <li.xialong@xydigit.com>
* test(discord): model recreated progress drafts
Co-authored-by: xialonglee <li.xialong@xydigit.com>
* fix(discord): serialize progress draft rotation
Co-authored-by: xialonglee <li.xialong@xydigit.com>
* fix(discord): isolate queued draft generations
Co-authored-by: Peter Lee <xialonglee@users.noreply.github.com>
* test(discord): align synchronous draft rotation
Co-authored-by: Peter Lee <xialonglee@users.noreply.github.com>
* fix(discord): distinguish draft rotation ownership
Co-authored-by: Peter Lee <xialonglee@users.noreply.github.com>
* chore: keep release notes in pull request
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(discord): stop retrying non-idempotent sends on post-connect-ambiguous errors
Discord's outbound retry runner treated every transient transport error as
retryable, including ECONNRESET, ETIMEDOUT, AbortError, and the undici
headers/body/socket timeouts. Those errors can fire after Discord has already
received and created the message but before the client reads the response, so
replaying the non-idempotent createChannelMessage POST delivers the same
message twice while reporting success.
Add a pre-connect-only classifier (isRetryableDiscordPreConnectError) covering
errors that provably never reached Discord (DNS/connect refused/connect
timeout) plus rate-limit rejections, mirroring the Telegram send-path
carve-out. The retry runner now accepts a per-call nonIdempotent option; the
message-create and thread-create call sites opt in so ambiguous post-connect
errors surface to the caller instead of double-sending. Idempotent REST calls
(reactions, edits, DM-channel lookup, uploads) keep the broader transient set.
* fix(discord): retry nonce-enforced message creates
* fix(discord): scope create retries by endpoint
* fix(discord): stabilize sticker and poll create nonce across retries
* fix(discord): tighten create retry safety
* fix(discord): preserve nonce-safe retries
* fix(discord): scope nonce fields to message creates
* test(discord): cover nonce-safe direct sends
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(google-meet): force English UI when reusing existing Chrome tab
* fix(google-meet): narrow reused tab before forcing English UI
* test(google-meet): assert /navigate target id is adopted in reused tabs
* fix(google-meet): preserve active call tabs and normalize English before recovery
* fix(google-meet): preserve localized active tabs
* test(google-meet): avoid shadowing path import
* test(google-meet): align mocks with English-pinned tab reuse
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(logs): clean up gateway and channel startup/shutdown log output
Scope Discord slash-command deploy REST diagnostics to command routes so
concurrent startup traffic (voice-state probes, channel lookups) keeps its
owner's error handling; make per-request deploy error lines verbose-only and
drop JSON bodies that only repeat message+code. Log allowlist summaries one
line per call so unresolved lines keep their timestamp/subsystem prefix, and
skip identity lookups that resolved to themselves. Remove embedded subsystem
prefixes, demote routine signal/shutdown/force/postbuild/diag chatter to
debug or verbose, merge the duplicate Control UI build notices, drop doctor's
duplicate backup line, and name the config surface or platform limit in the
transcripts autoStart and command-limit warnings.
Fixes#104163
* fix(slack): keep bare-name allowlist resolutions in startup log summary
Only omit identity lookups where the input already is the resolved id;
name-based lookups that translated to an id stay logged even when the
display name matches the input.
* fix(telegram): keep isolated-ingress readiness marker on the runtime log
test/e2e/qa-lab telegram-bot-token-runtime waits for this line via the
injected RuntimeEnv.log; verbose-only logging would deterministically time
out that live proof. Comment the contract at the call site.
restrict-plus-operands (Buffer + string) and no-promise-executor-return
tripped the lint shards on every PR since #101783 landed; scoped fixes
only, no behavior change.
Long-running Telegram senders leaked HTTP transports: the client-options cache in extensions/telegram/src/send.ts created an owned undici dispatcher per account/network entry but evicted entries without closing it. Cache entries now own their transport; eviction retires the entry and closes the transport once the operation-level lease releases, so cache pressure never aborts an in-flight, retrying, or still-preparing send. Includes a real-socket e2e regression against a local Bot API server.
Co-authored-by: zhangguiping-xydt <zhangguiping-xydt@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>