Releases: gaato/discord.mbt
Release list
discord.mbt v0.5.0
Runs the Gateway Shard and Bot on JavaScript and moonrun Wasm in addition to native. Gateway sessions are values: Shard::start(resume~), Shard::session(), Bot(resume~), and Bot::sessions() carry a session across restarts, and a BotSession also keeps the READY metadata needed to process replayed events before RESUMED. The workers_gateway example runs a full bot in a Cloudflare Durable Object; its README records a deployed run that resumed after an eviction and after a redeploy and re-identified once when Discord rejected a RESUME.
Bot now reads session_start_limit from GET /gateway/bot before every IDENTIFY and ends run with SessionStartLimitExceeded when the limit is exhausted, because exceeding Discord's daily IDENTIFY limit resets the bot token.
HTTP interactions gain one host-independent entry point, InteractionEndpoint::handle_signed_http, with the public InteractionHttpRequest, InteractionHttpBody, and InteractionHttpResponse types. On JavaScript, App::start_signed_http returns { response, background } for host adapters; examples cover Cloudflare Workers, Deno, Bun, Vercel, Fastly, and Lambda Function URLs, plus a Spin WASIp2 experiment.
Breaking: InflateError gains Unsupported; exhaustive matches need a new arm. The native endpoint_http server answers NoResponse with 202 and TimedOut with 504. Voice remains native-only, and zlib-stream Gateway compression is unavailable on JavaScript and Wasm.
Validation: native 1186, JavaScript 979, and Wasm 984 tests; CI covers workerd, Node.js, Bun, and Deno adapter suites and a Wasm component build. See CHANGELOG.md for the full list.
discord.mbt v0.4.3
Adds experimental moonrun Wasm support for REST, typed interactions, signature verification, HTTP interactions serving, the TCP coordinator, and common data/test packages. The root API exposes the common APIs and HTTP server on Wasm.
Gateway/Bot and Voice remain native-only. DAVE follows the existing JS behavior on Wasm: unavailable, with safe constructors reporting LibraryUnavailable.
Requires gaato/http-async@0.1.1 and gaato/dave@0.1.1. Browser/WASI/wasm-gc support is not included.
Validation: 910 discord Wasm tests passed with the published dependency versions; native and JS regression suites passed locally. CI includes Wasm HTTP/TCP loopback tests and the HTTP interactions example build.
discord.mbt v0.4.2
A patch release: documentation only, no code changes. Details are in CHANGELOG.md.
Fixed:
- The documentation appears once on mooncakes. 0.4.1 removed the
readmefield, but the published package still containedREADME.md, which mooncakes uses as the module README when the field is absent, and the root package'ssrc/README.mbt.mdwas rendered again below it. The root package guide is nowsrc/overview.mbt.md, still compiled with the test suite, and it is the module README.
The voice shim runtime is unchanged (voice-shim-v0.1.0).
discord.mbt v0.4.1
A patch release: documentation only, no code changes. Details are in CHANGELOG.md.
Fixed:
- The documentation no longer appears twice on mooncakes.
moon.modnamed a link to the root package'ssrc/README.mbt.mdas the module README, so mooncakes rendered the same document as the module page and again as the root package's documentation. The module now has no separate README: the root package guide is the one document, on mooncakes and on GitHub.
The voice shim runtime is unchanged (voice-shim-v0.1.0).
discord.mbt v0.4.0
A minor release: it contains breaking changes. Details are in CHANGELOG.md.
Added:
Client(transport=...)accepts agaato/httpTransport. The wire exchange below validation, middleware, rate limiting, 429 retries, status mapping, and decoding is now pluggable; by default the client creates agaato/http-asyncAsyncTransportwith a keep-alive pool.Client::offlineruns handlers without a network, answering every logical REST call from a function of the same shape as thenextcontinuation ofHttpMiddleware.- Fixtures for handler tests (
gaato/discord/testkit), on JS and native. - Outgoing embeds, components, and modals are checked against Discord's documented limits before any request is made (
DiscordHttpError::Validation,AppConfigError::ModalOutsideLimits,ModalPrefillError::ValueTooLong). - CDN URL builders cover Discord's CDN endpoint table, plus
display_avatar_url.
Changed (breaking):
- Connection pooling moved to
gaato/http-async;max_connectionsnow bounds parked idle connections per origin instead of connections in flight.gaato/httpandgaato/http-asyncare new dependencies. - CDN URL corrections:
sticker_urlloses itssizeargument, static-only endpoints reject GIF with the newCdnUrlError::UnsupportedFormat. - Typed route ids may contain
:;App::validatenow rejects only ids nested at a:boundary. - Dot-callable trait methods are declared explicitly for moonc 0.10.14; other promoted methods stop resolving once the compiler removes the promotion.
Fixed:
- The Node.js build prerequisite is documented in the README, the getting-started guide, and the template.
The voice shim runtime is unchanged (voice-shim-v0.1.0).
discord.mbt v0.3.1
A patch release: one addition and one fix, no breaking changes. Details are in CHANGELOG.md.
Added:
arg_int32: an integer option that decodes toInt.arg_intyieldsInt64, and narrowing it withto_int()wraps silently when a command registers no bounds.arg_int32registers theIntrange for a missingminormaxand fails decoding withArgsDecodeError::Validationfor a received value outside the range.
Fixed:
- Gateway jitter was identical in every shard and process.
Shard::start,VoiceGateway, andVoiceConnectiondefaultedrandto@random.Rand::chacha8(), whose default seed is a fixed constant, so the first-heartbeat jitter, reconnect backoff, and invalid-session wait replayed the same sequence everywhere. The default is now@random.Rand::new(), seeded from platform entropy. Passrand=to keep a deterministic sequence.
The changelog and README now state the compatibility policy directly: minor releases may contain breaking changes, patch releases do not. The voice shim runtime is unchanged (voice-shim-v0.1.0).
discord.mbt v0.3.0
Boundary hardening: escape hatches, routing, and lifecycle side effects now have explicit, checked contracts. Every breaking change has a migration note in CHANGELOG.md.
Breaking changes:
- Command sync is no longer configured on
App.CommandSyncis nowCommandScope(noDisabled); passBot(app, token~, sync=Global)to opt in, or callapp.sync_commands(client, application_id, scope=...)from a one-shot.App::serve/serve_interactionslost theirsyncflag. - Components are routed by a typed
ComponentRoute[A]: one value produces the custom id (route.custom_id(state)), registers the handler (app.on_component(route, handler)), and reads ids back (route.decode(id)). The string-prefixon_component(prefix~)andsuffix()are gone;on_component_raw(prefix~)is the literal-prefix tier. - Typed component and modal routes match the exact id or
id:state;App::validaterejects empty, duplicate, and malformed routes. - Error policies follow the response gate's real state:
failure.response_state()replacesfailure.phase();ResponsePhaseandAppDispatchErrorare removed. - Component waits default to the invoking user (
from? : WaitFrom = Invoker); passfrom=Anyonefor shared waits. CommandCheckisasync (CheckCtx) -> Bool;CheckCtx::app()reaches the REST client.request_timeout_msbounds one network attempt; rate-limit waits and 429 back-off no longer count against it.- The
gaato/discordfacade is cut to golden-path families (169 → 113 names); import the focused package for anything removed.
Added:
@framework.ResponseState,ResponseGate::state()/expire(), andresponse_state()on contexts. A handler that responds throughRaw/raw()and then fails, a rejected or failed initial response, and middleware raising afternext()now reach the user instead of degrading to a warning.CustomIdCodec(unit,string,int,id,custom,zip,imap) with Discord's 100-unit custom id limit enforced at encode time.gaato/discord/cooldown: injectableCooldownStore, plus@coordinator.RemoteCooldownStorefor cooldowns shared across processes.UnownedCommands::Keep,SyncReport, and the pure planner@framework.plan_command_sync.src/examples/gate_probefor live-verifying error-policy recovery and user-restricted waits.
Fixed:
- Command sync always preserves Discord's Entry Point command. Before, syncing an app with Activities enabled failed with error 50240.
- Command sync no longer re-sends every global command on each run for apps that support user installs.
- A third command sync within a minute waits for the bulk-overwrite bucket instead of failing with
Timeout.
The voice and coordinator packages are marked experimental. The voice shim runtime is unchanged (voice-shim-v0.1.0).
discord.mbt v0.2.0
Breaking release tracking upstream MoonBit, moonbitlang/async, and Discord API changes.
Breaking changes:
- Requires
moonbitlang/async0.22.1 and MoonBit 0.10.13. Cancellation is now a signal rather than an error;Coordinator::closeandInteractionsServer::closeare async. - Fields Discord documents as nullable are now
Nullable[T]?:Channel.application_id,ThreadMetadata.create_timestamp, scheduled-event recurrenceby_*arrays, and Components V2 mediadescription/width/height. Routevalues hold raw emoji, invite/template codes, and external ids;Route::pathpercent-encodes them.
Added:
- Channel obfuscation support ahead of Discord's 2026-11-16 cut-over:
GatewayCapabilities(Bot(capabilities=...)),Channel::is_obfuscated(), and thechannel_obfuscated/is_spoiler_channelchannel flags. file_typesupload filters on ATTACHMENT options and File Upload components, plus a typedfile_fieldfor modals that decodes to resolved attachments.shardonget_current_user_guilds/paginate_current_user_guilds, required for large bot sharding.- Application Identity Profile endpoints (Game Stats Widgets).
Channel.app_permissionsfor resolved interaction channels.
Fixed:
- Command sync no longer re-registers commands when Discord echoes set-valued fields (
file_types,channel_types,contexts,integration_types) in a different order.
The voice shim runtime is unchanged (voice-shim-v0.1.0).
discord.mbt v0.1.0
Initial experimental release of gaato/discord for MoonBit.
Highlights:
- Typed Discord REST APIs, Gateway/Bot runtime, command synchronization, events, cache, collectors, and coordinator.
- Native Discord voice gateway v8 with Opus send/receive and DAVE E2EE through
gaato/dave. - Verified automatic bootstrap for the versioned transport AEAD shim on Linux, macOS, and Windows, with cache, offline, and preseed overrides.
- Signed HTTP interactions and JS/serverless support, including a tested Cloudflare Workers adapter.
Native voice applications can provision both pinned runtimes with:
env DISCORD_VOICE_REQUIRE_SHIM=1 MBT_DAVE_REQUIRE_NATIVE=1 moon build --target native --release
Voice and serverless APIs remain experimental.
Discord voice shim v0.1.0
First binary release of the Discord voice transport AEAD shim. Supports AES-256-GCM and XChaCha20-Poly1305 through C ABI version 3. DAVE MLS and media encryption are provided separately by gaato/dave. The release workflow attaches prebuilt archives for Linux, macOS, and Windows together with archive and runtime checksums and asset sizes.