Commit Graph

1851 Commits

Author SHA1 Message Date
qingminlong
47751c117c fix(discord): bound ffmpeg stderr by bytes (#104230) 2026-07-11 12:23:32 -07:00
Peter Steinberger
934a974c29 feat(slack): support native data visualizations (#104539) 2026-07-11 09:18:39 -07:00
Peter Steinberger
fa77fe10d5 chore: migrate active GPT-5.5 references to GPT-5.6 (#104452)
* chore(models): migrate active GPT-5.5 references

* test(workboard): expect GPT-5.6 Sol default

* chore: keep release notes in PR body

* test(models): align picker fixtures with Sol default

* test: update PDF default model expectation

* test(qa): migrate thinking smoke to Luna

* test(gateway): align mock catalog with Sol default

* ci: retrigger exact-head PR checks

* test(gateway): document default catalog invariant
2026-07-11 06:30:57 -07:00
Peter Steinberger
234e8f4fae test(discord): exercise multipart proxy fetch path (#104421) 2026-07-11 04:13:00 -07:00
Peter Lee
ef95c5d74e fix(discord): reset progress drafts across queued turns (#102341)
* 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>
2026-07-11 02:59:29 -07:00
Peter Steinberger
d8bf51b462 fix(discord): single-source thread-binding default placement and guard artifact parity (#104342)
* fix(discord): single-source thread-binding default placement and guard artifact parity

* fix(tests): load thread-binding parity artifacts via sanctioned contract test helpers
2026-07-11 02:50:53 -07:00
Peter Steinberger
72cf43fa80 refactor(discord): unify custom-id value codecs into one shared module (#104334) 2026-07-11 02:12:37 -07:00
Peter Steinberger
7bf80dc2c6 chore(tooling): enforce formatting and refresh TypeScript checks (#104239)
* chore(tooling): enforce current formatter and refresh checks

* chore(tooling): keep release changelog formatter-owned

* chore(tooling): retain compatible Node type surface

* ci: enforce formatting for docs-only changes

* ci: isolate docs formatter check

* chore(tooling): apply updated lint and format rules

* chore(tooling): satisfy updated switch lint

* style(ui): apply Linux formatter layout

* test(doctor): match quiet local audio contribution

* test(doctor): assert quiet output only

* test(doctor): follow restored information contract
2026-07-11 01:09:51 -07:00
Yuval Dinodia
df883ab81a fix(discord): stop retrying non-idempotent sends on post-connect-ambiguous errors (#103867)
* 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>
2026-07-11 00:54:23 -07:00
Peter Steinberger
f94a7dc183 feat(codex): supervise native Codex sessions (#104045)
* feat(codex): add native session supervision

* fix(codex): harden supervision integration

* fix(codex): preserve locked harness ownership

* fix(codex): fence native session archive

* fix(codex): revalidate archive binding ownership

* feat(codex): integrate supervision runtime

* feat(sessions): preserve harness-owned execution

* feat(sessions): persist harness ownership invariants

* feat(gateway): enforce harness-owned sessions

* feat(setup): enable detected Codex supervision

* feat(mac): expose supervised Codex sessions

* feat(ui): make Codex sessions actionable

* docs(codex): document session supervision

* test(codex): cover integration ownership

* chore(i18n): refresh supervision inventories

* fix(setup): finalize Codex activation atomically

* test(codex): narrow binding store update

* fix(sessions): preserve legacy model locks

* test(macos): serialize Codex catalog fixtures

* fix(sessions): preserve legacy lock admission

* chore(i18n): reconcile supervision metadata

* test(sessions): mark legacy lock fixture

* fix(macos): drain final Codex catalog frame

* docs: leave supervision note to release

* style(macos): satisfy Codex catalog type length

* chore: record session accessor seam owners

* fix(macos): honor configured Codex supervision

* fix(codex): preserve harness-owned model locks

* fix(codex): satisfy supervision lint gates

* chore(i18n): refresh native supervision inventory

* fix(codex): align supervision validation contracts

* fix(codex): close supervision boundary gaps

* fix(codex): preserve supervision activation contracts

* fix(codex): dispose standalone supervision runtime

* fix(codex): pin supervised source connection

* fix(plugins): bind delegated runs to exact session target

* fix(codex): scope supervised sessions to configured agents

* fix(codex): fingerprint effective supervision home

* fix(codex): normalize supervision plugin policy

* fix(codex): keep supervised bindings stable across upgrades

* fix(codex): guard all supervised binding connections

* fix(codex): preserve catalog filters and pending CAS identity

* fix(codex): preserve supervision identity for diagnostics

* fix(codex): bind uncertain commits to supervision connection

* fix(codex): satisfy supervision type boundaries

* fix(macos): reconcile current main validation

* fix(codex): handle absent runtime config in supervision

* fix(doctor): own local audio acceleration check

* fix(codex): satisfy integration lint gates

* fix(codex): satisfy lifecycle safety guards
2026-07-11 00:12:08 -07:00
Peter Steinberger
81a201df26 feat: add portable table presentation blocks (#103583)
* feat(presentation): add portable table blocks

* chore(presentation): refresh generated contracts

* fix(slack): preserve table fallback payloads

* docs(changelog): note portable message tables

* fix(presentation): preserve cross-channel fallback delivery

* chore(plugin-sdk): refresh rebased contracts

* test(slack): align accessibility expectations

* fix(presentation): harden cross-channel fallback delivery

* chore(plugin-sdk): refresh rebased contracts

* docs(changelog): defer portable table release note

* fix(presentation): satisfy extension lint

* chore(plugin-sdk): refresh surface budgets

* fix(telegram): preserve reactions after progress replies

* fix(slack): preserve rendered preview fallback text

* fix(feishu): preserve oversized presentation fallbacks

* docs(changelog): note portable message tables

* docs(changelog): defer portable table release note

* chore(plugin-sdk): refresh rebased contracts

---------

Co-authored-by: Peter Steinberger <steipete@openai.com>
2026-07-10 22:29:13 -07:00
Peter Steinberger
36e0ac3576 fix(logs): clean up gateway and channel startup/shutdown log output (#104174)
* 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.
2026-07-10 22:13:33 -07:00
xingzhou
6595d1756b fix(discord): stream multipart uploads (#102972)
* fix(discord): bound multipart REST uploads
* Preserve Discord media upload payload limits
* fix(discord): stream multipart uploads

---------

Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-07-11 10:10:41 +05:30
Josh Avant
fbd330b7aa fix(channels): honor configured read target policies (#99905)
* fix(channels): enforce configured read targets

* test(channels): align policy checks with boundaries

* fix: bind channel reads to trusted turn context

* test: satisfy gateway lint

* fix: narrow message action channel imports

* fix(feishu): authorize message reads before provider access

* fix(slack): await reaction clear authorization

* fix(channels): align provider action contracts

* fix(matrix): read direct-room account data before sync

* fix(channels): reject unsupported attachment actions early

* fix: restore trusted operator conversation reads

* fix(matrix): authorize pin actions before provider reads

* fix: preserve trusted channel read workflows

* fix(discord): resolve current channel ids consistently

* fix(agents): preserve message action turn capability

* fix(plugins): enforce host-owned read provenance

* fix(channels): harden Teams and Discord read policy

* fix(channels): preserve exact-current action compatibility

* fix(imessage): authorize trusted current chat aliases

* fix(channels): preserve normalized current aliases

* fix(channels): preserve external current target aliases

* fix: reconcile channel policy with current main

* fix(discord): isolate DM read policy

* fix(channels): enforce provider read gates

* fix(gateway): await serialized message action identity tokens

* fix(ci): refresh channel protocol contracts
2026-07-10 22:29:37 -05:00
Peter Steinberger
dba64d574f chore(release): set version to 2026.7.2 2026-07-11 04:00:49 +01:00
ToToKr
b745862361 fix(discord): keep thread-binding persona UTF-16 safe (#103543)
* fix(discord): keep thread-binding persona UTF-16 safe

resolveThreadBindingPersona truncated the persona label with a raw .slice(0, THREAD_BINDING_PERSONA_MAX_CHARS). When an emoji or other astral code point straddles the 80-unit limit, the raw slice keeps a dangling high surrogate, so the Discord thread-binding persona (webhook display name) can carry a lone surrogate. Route the clamp through the shared truncateUtf16Safe primitive so the boundary code point is dropped whole. Adds a regression test.

* test(discord): assert exact persona boundary

* docs(changelog): credit Discord persona fix

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 16:16:24 +01:00
JC
59e95fe3fd feat: support GPT-5.6 Ultra across OpenClaw and Codex runtimes (#98021)
* feat: support GPT-5.6 Ultra across agent runtimes

Co-authored-by: J Cai <anyech@gmail.com>

* fix: keep harness projections discovery-free

* fix(codex): mirror V2 native subagent tasks

* chore: refresh plugin SDK surface budgets

* test: expose Ultra wire effort proof

* test(cron): avoid hoisted mock initialization race

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 15:23:24 +01:00
Peter Steinberger
abbd5ae3ea fix(discord): recover from failed gateway resumes (#103596)
* fix(discord): recover from failed gateway resumes

* chore: leave release notes to release workflow
2026-07-10 10:34:29 +01:00
Peter Steinberger
26d200c6a3 feat(channels): narrated progress drafts + activity receipt on the final answer (#103463)
* feat(channels): narrated progress drafts + activity receipt on the final answer

Progress mode replaces raw tool lines with short utility-model narration of
what the agent is doing (streaming.progress.narration, default on, requires
an explicit utilityModel). On Discord the final answer now carries the
-# activity receipt and the working draft is deleted once the answer lands,
so busy channels keep no orphaned tool log above the reply.

Formatting verified remotely via Testbox oxfmt --check (hook bypassed:
no node_modules in this worktree).

* fix(channels): keep narration toggle independent of channel-default stream mode

Discord resolves its own progress default, so the resolver must not re-derive
mode with the generic partial fallback (narration was off for unset config).

* fix(auto-reply): honor status-only command text in narration model input

streaming.progress.commandText: "status" hides raw exec/bash text from the
channel draft; narration input now mirrors that policy so the utility model
never receives more command detail than the draft shows (Codex review P2).

Formatting verified remotely via Testbox oxfmt --check.

* fix(auto-reply): share the draft's command-tool set for narration and regen channel metadata

Reuse isCommandToolName (exec|shell|bash) so narration's commandText policy
matches the draft formatter exactly, and regenerate bundled channel config
metadata for the new streaming.progress.narration key (Codex review round 2).

Gates verified on Testbox: config:channels:check, oxfmt --check, 4 test shards.

* fix(channels): clear stale narration when the narrator stops mid-turn

An empty narration update now falls the draft back to raw tool lines, and the
narrator emits that clear when it disables after consecutive failures or the
per-turn cap, so drafts never pin stale status text (Codex review round 3).

Gates verified on Testbox: oxfmt --check + 4 test shards.

* chore(config): regen bundled channel metadata after rebase onto main

* chore: CI fixups — lint nits, test harness types, docs map, SDK surface budget

Two deliberate public SDK additions (resolveChannelStreamingProgressNarration,
isCommandToolName via the streaming wildcard re-export) bump the pinned
public-surface budgets to current counts (exports 10488, callable 5235).

Gates verified on Testbox: oxfmt, targeted oxlint, docs:map:check,
config:channels:check, check:test-types, 5 test shards.
2026-07-10 09:28:47 +01:00
Peter Steinberger
e8fcc93cd3 fix(talk): await realtime tool result delivery (#103268)
* fix(talk): await realtime tool result delivery

* fix(talk): terminally cancel queued results

* chore: keep release changelog out of PR

---------

Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-09 20:11:20 -07:00
Peter Steinberger
add2c586c2 feat(slack): support native chart presentations (#102635) 2026-07-10 04:05:23 +01:00
tzy-17
3dd5c1880f fix(discord): honor forum archive defaults (#103033)
Carry typed forum/media parent metadata through the message-send path so implicit thread creation uses the configured default archive duration.

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-10 00:23:34 +01:00
Alix-007
f8efe14639 fix(discord): add timeouts to voice upload requests (#102863)
* fix(discord): add timeouts to voice upload requests

* fix(discord): refine voice upload timeouts

Use the normalized REST timeout for upload negotiation and the existing attachment transfer budget for the signed audio upload. Reuse the shared loopback test harness and verify both hanging sockets close.

Thanks @Alix-007 for the original timeout fix.

Co-authored-by: llagy009 <0668001470@xydigit.com>

---------

Co-authored-by: llagy009 <0668001470@xydigit.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 22:15:13 +01:00
lsr911
ed9ce1c584 fix(discord): use truncateUtf16Safe for deploy error body truncation (#102525)
* fix(discord): use truncateUtf16Safe for deploy error body truncation

* test(discord): cover utf16 deploy errors

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 09:33:46 +01:00
Dave Fano
b502554f6c Suppress failed tool progress in Discord (#92517)
* fix(discord): suppress failed tool progress

Co-authored-by: davefano-agents@teal-03-mst-m2u-wheeljack <davefano-agents@users.noreply.github.com>

* chore: leave changelog to release

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: davefano-agents@teal-03-mst-m2u-wheeljack <davefano-agents@users.noreply.github.com>
2026-07-09 05:39:59 +01:00
VectorPeak
2cb482dd40 fix(discord): split encoded video URLs from captions (#101815)
* fix(discord): split encoded video URLs from captions

Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>

* refactor(discord): scope media filename decoding

---------

Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 04:41:53 +01:00
mushuiyu886
e90bf31829 fix(discord): keep gateway close reasons UTF-16 safe (#102246)
* fix(discord): keep gateway close reasons UTF-16 safe

* test(discord): assert exact close reason truncation

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 04:28:06 +01:00
xingzhou
1017ea5bc8 fix(discord): prevent stale gateway error listeners after restart (#101617)
* fix(discord): remove gateway error listener on dispose

* fix(discord): preserve late gateway error guard

* fix(discord): retain late gateway diagnostics

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 04:25:37 +01:00
Vincent Koc
686b6b51da test(release): refresh beta plugin expectations 2026-07-08 14:22:22 -07:00
Vincent Koc
22ae651e9a fix(channels): keep native think menus responsive (#101926) 2026-07-07 18:58:39 -07:00
Vincent Koc
99b24e7416 refactor(discord): localize internal declarations (#101945) 2026-07-07 18:28:35 -07:00
Vincent Koc
b88f80940a refactor: localize internal implementation symbols (#101831) 2026-07-07 10:23:36 -07:00
Vincent Koc
3d206140f3 refactor: localize internal implementation constants (#101758) 2026-07-07 08:34:13 -07:00
Vincent Koc
fdc7892a6e refactor: localize internal implementation types (#101731) 2026-07-07 07:41:04 -07:00
Vincent Koc
c8d95da14c refactor: localize file-private exports (#101701) 2026-07-07 06:57:19 -07:00
Peter Steinberger
176fee5d07 fix: prevent garbled emoji at remaining text limits (#101685)
* fix: keep remaining bounded text UTF-16 safe

Co-authored-by: 0668000787 <ma.weibin@xydigit.com>
Co-authored-by: ben.li <li.yang6@xydigit.com>
Co-authored-by: 廖石荣 0668000909 <liao.shirong@xydigit.com>
Co-authored-by: 陈志强0668000989 <chen.zhiqiang1@xydigit.com>

* test: use tracked prompt template fixture

---------

Co-authored-by: 0668000787 <ma.weibin@xydigit.com>
Co-authored-by: ben.li <li.yang6@xydigit.com>
Co-authored-by: 廖石荣 0668000909 <liao.shirong@xydigit.com>
Co-authored-by: 陈志强0668000989 <chen.zhiqiang1@xydigit.com>
2026-07-07 14:49:15 +01:00
Alix-007
936136a707 fix(channels): prevent metadata caches from growing without bound (#101650)
* fix(discord): cap channel info cache size

* fix(channels): consolidate bounded metadata caches

---------

Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
2026-07-07 06:47:37 -07:00
Peter Steinberger
9fb2403221 fix(discord): keep thread title prompts UTF-16 safe (#101551)
Co-authored-by: Alix-007 <li.long15@xydigit.com>
2026-07-07 11:16:59 +01:00
Peter Steinberger
a2a68d154b fix(agent): preserve explicit recipient sessions (#101507)
* fix(agent): honor recipient session routing

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
Co-authored-by: pingfanfan <pingfan.work@gmail.com>

* fix(agent): preserve canonical recipient routes

* fix(agent): require exact recipient routes

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>

Co-authored-by: pingfanfan <pingfan.work@gmail.com>

* fix(agent): harden recipient route resolution

* fix(imessage): require canonical recipient handles

* fix(agent): refine provider recipient exactness

* fix(agent): bound direct alias session routing

* fix(signal): preserve direct alias route type

* fix(agent): honor binding-scoped recipient sessions

* fix(routing): honor configured main session aliases

* fix(clickclack): align account-owned session routes

* fix(twitch): preserve canonical recipient sessions

* fix(routing): isolate stable outbound identities

* chore: defer recipient session changelog

* fix(sms): use dedicated channel SDK facade

---------

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
Co-authored-by: pingfanfan <pingfan.work@gmail.com>
2026-07-07 10:07:13 +01:00
Vincent Koc
f0564943a7 docs(openai): refresh realtime 2.1 examples 2026-07-06 23:22:33 -07:00
Vincent Koc
84e5327720 fix(text): keep bounded outputs UTF-16 safe (#101355)
Co-authored-by: Alix-007 <li.long15@xydigit.com>
2026-07-06 21:33:24 -07:00
Peter Steinberger
95f46743e4 fix(discord): prioritize eligible default account (#101292)
Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
2026-07-07 04:10:32 +01:00
Vincent Koc
775ef966c3 refactor(deadcode): localize internal type aliases (#101243) 2026-07-06 17:57:32 -07:00
tiffanychum
da0103f025 fix(discord): messages sent during gateway reconnect are silently dropped (#100896)
* fix(discord): drain queued outbound deliveries after gateway reconnect (#56610)

Discord sends that failed while the gateway websocket was reconnecting
(close codes 1005/1006) stayed stuck in the outbound delivery queue and
were silently dropped. Classify sends that fail while the registered
gateway is disconnected as retryable, and drain pending discord queue
entries when the gateway reconnects, matching the WhatsApp/Telegram
reconnect drains.

* fix(discord): harden reconnect recovery

Co-authored-by: tiffanychum <71036662+tiffanychum@users.noreply.github.com>

* refactor(discord): remove unsafe reconnect replay

* fix(discord): bound reconnect retry per request

Co-authored-by: tiffanychum <71036662+tiffanychum@users.noreply.github.com>

* chore(changelog): leave reconnect fix to release flow

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 23:56:17 +01:00
Zachary Yuan
01f0b2340f fix(discord): download attachments at receipt time, not after the run queue (#96183)
* fix(discord): download attachments at receipt time, not after the run queue

Discord's CDN attachment URLs carry an expiring `ex` TTL. Media was
downloaded in processDiscordMessageInner, after the inbound run queue,
so messages delayed behind a busy run lost their attachments silently.
Resolve attachments/forwarded media during preflightDiscordMessage
instead, before the message is enqueued, and carry the result forward
on the context for process to reuse.

Fixes #96165

* refactor(discord): carry one prepared media snapshot

Co-authored-by: ZacharyYW <zachary.w.yuan123@gmail.com>

* fix(discord): guard bot media before download

* chore(discord): leave release notes to release flow

* docs(changelog): credit Discord attachment fix

* chore(changelog): leave attachment fix to release flow

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 23:45:32 +01:00
wings1029
fc77c2b04b fix(discord): bound gateway metadata response body reads to prevent OOM (#98682)
* fix(discord): bound gateway metadata response body reads to prevent OOM

The materializeGuardedResponse helper in the Discord gateway metadata path
buffered the full upstream Response body via response.arrayBuffer() without
any size cap. A malicious or malfunctioning /gateway/bot endpoint that returns
an oversized payload could exhaust gateway memory.

Replace arrayBuffer() with readResponseWithLimit(4 MiB), consistent with
DISCORD_API_RESPONSE_BODY_LIMIT_BYTES in api.ts. Overflow throws an Error
with the byte counts.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(discord): wrap readResponseWithLimit result in Uint8Array for type compat

readResponseWithLimit returns Buffer which is not assignable to BodyInit in
the undici Response constructor type. Wrap in new Uint8Array() to satisfy the
boundary dts check. Also remove testExports export and mock fetchWithSsrFGuard
in tests via vi.hoisted + vi.mock to avoid leaking internal test-only exports.

Co-Authored-By: Claude <noreply@anthropic.com>

* test(discord): tighten gateway metadata proof

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 23:34:03 +01:00
Peter Steinberger
e29efa6852 fix(discord): terminate ffmpeg on stream errors (#101124)
* fix(discord): terminate ffmpeg on stream errors

* docs(changelog): note Discord ffmpeg cleanup

* fix(discord): force-stop ffmpeg after output failures

* chore: defer Discord release note to changelog batch
2026-07-06 23:11:45 +01:00
weiqinl
e938461aa2 fix(discord): use configured statusReactions.timing instead of DEFAULT_TIMING (#94736)
* fix(discord): use configured statusReactions.timing instead of DEFAULT_TIMING

Makes the Discord message finalizer respect user-configured
doneHoldMs/errorHoldMs instead of always using hardcoded
DEFAULT_TIMING values. Brings Discord to parity with Telegram
and Slack which already use configured timing.

Fixes #78431

* test(discord): strengthen configured-timing regression with old-default assertion

Add a no-cleanup assertion at DEFAULT_TIMING.doneHoldMs (1500ms) before
advancing to the configured 2000ms hold, so the test fails against the
old hardcoded-default behavior. Add a matching errorHoldMs regression
test using failedCounts to drive the error terminal path.

Address ClawSweeper [P2] review finding on #94736: the previous test
advanced straight to 2000ms and would pass without the runtime fix
because main already removes the done reaction at 1500ms.

* refactor(discord): unify status reaction timing proof

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 12:18:40 -07:00
Masato Hoshino
b6c7a77d3f fix(discord): handle ffmpeg stderr stream errors in voice playback (#101088)
* fix(discord): handle ffmpeg stderr stream errors in voice playback

createDiscordOpusPlaybackStream guards ffmpeg stdout and stdin against raw
stream 'error' events (an unhandled stream error throws and crashes the
gateway via uncaughtException), but the stderr stream on the same child was
left unguarded. Add the symmetric stderr error handler, routing it through
opusStream.destroy like stdout. Add a regression test covering stdout and
stderr stream errors.

* refactor(discord): unify ffmpeg stream errors

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-06 19:43:10 +01:00
Vincent Koc
c3e46e710d test(discord): align proxy websocket override helper type 2026-07-06 20:26:45 +02:00