Class DiscordChannel

java.lang.Object
com.tnsai.channels.discord.DiscordChannel
All Implemented Interfaces:
ChannelAdapter

@Channel(id="discord", displayName="Discord") public class DiscordChannel extends Object implements ChannelAdapter
Discord channel adapter using the Gateway WebSocket + REST API (TNS-351).

Inbound: opens a Discord Gateway v10 WebSocket. The lifecycle is:

  1. GET /gateway/bot → obtain the WSS URL.
  2. Connect WSS with ?v=10&encoding=json.
  3. Receive op=10 HELLO carrying heartbeat_interval.
  4. Schedule op=1 HEARTBEAT at that interval (with the last observed s sequence number).
  5. Send op=2 IDENTIFY once with the bot token and the intents bitfield from DiscordChannelConfig.
  6. Receive op=0 t=READY → capture the bot's user_id so we can filter own echoes.
  7. Receive op=0 t=MESSAGE_CREATE → convert payload into UnifiedMessage and deliver via ChannelContext.onMessage(com.tnsai.channels.api.UnifiedMessage).

Outbound: each UnifiedResponse becomes a POST /channels/{channel_id}/messages call carrying content (and message_reference when the response targets a specific reply).

v1 deliberately scopes out three Discord features the issue lists: slash commands (requires POST /applications/{id}/commands registration + handling INTERACTION_CREATE — defer until there is a structured slash-command contract), embeds for rich tool output (UnifiedResponse only carries text + attachments today — add when the SPI grows an embed-shape), and streaming via message edits (PATCH /channels/{id}/messages/{id}, gated by Discord's edit ratelimit — defer to a streaming-aware follow-up).

Thread safety: send(com.tnsai.channels.api.UnifiedResponse) can be called from any agent thread concurrently with the WebSocket callback and the heartbeater. The adapter holds only volatile/atomic state and an immutable HTTP client, so there is no mutable adapter state to guard.