feat(discord): add optional Captain communication surface#33
Closed
robinbraemer wants to merge 5 commits into
Closed
feat(discord): add optional Captain communication surface#33robinbraemer wants to merge 5 commits into
robinbraemer wants to merge 5 commits into
Conversation
…, and dispatch durability
…oken configuration gaps
Member
Author
|
Superseded by the private akua-dev/agentos-discord integration repository at exact commit |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Add an optional Discord Captain and team communication surface while preserving AgentOS's native-tool and durable-authority philosophy. Discord must remain a human provider surface, never Fleet authority: a narrow fixed-origin REST CLI performs synchronous effects, a persistent Gateway ingress only filters and appends approved non-credential events through the released PostgreSQL ingestion function, and the existing pg-listen path remains the sole Pi wake owner. Do not add a Discord outbox, conversation abstraction, controller, model invocation, Task writes, Inbox writes, or shadow queue/cursor. Keep provider authority least-privileged, mount the bot identity only into First Mate, make the Kubernetes patch explicitly optional, and teach bootstrap, Mate roles, architecture, recovery, embeds, interactions, and Captain communication contracts through the correct Skills and docs. Install the CLI and ingress in the common image and test their observable behavior and manifest preservation. The Discord CLI default must remain unchanged provider JSON; an explicit --axi mode follows AXI principles with compact TOON message projections, bounded collection output, definitive empty states, structured stdout errors and authoritative exit codes, while --axi --full preserves complete provider data. Unknown resource shapes must remain lossless. Use the standalone current TOON encoder rather than adopting the AXI SDK's unrelated full command lifecycle.
What Changed
Risk Assessment
Testing
The focused suite completed with 51 passing tests and no failures; CLI, ingress, manifest, credential-redaction, and full-image entrypoint evidence was captured. The linked-worktree Docker limitation was bypassed with a temporary clean committed context, then removed; the worktree remains clean.
Evidence: Discord CLI transcript
Evidence: Ingress persistence trace
Evidence: First-Mate optional patch render
Evidence: Full image build log
Evidence: Built image entrypoints
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 4 issues found → auto-fixed (3) ✅
clis/discord/discord.ts:133- The required contract says the default must remain unchanged provider JSON, but non-AXI HTTP failures prependDiscord HTTP <status>to the provider body at this line, making the result no longer raw JSON. Preserve the raw body or confirm this intentional exception.clis/discord/discord.ts:240- The required contract says unknown resource shapes must remain lossless, but this condition treats any array from a/messagespath as messages, filters unrecognized entries, and emits only the recognized subset. Only project arrays when every item is a recognized message; otherwise emit the original value.services/discord-ingress/src/gateway.ts:228- This reconnects with the previous session for every close code except 1000. Discord requires a fresh Identify for codes 1001, 4007, and 4009; otherwise the ingress can repeatedly attempt invalid Resume operations and stop receiving events. Apply an explicit close-code resume policy. Discord close codesservices/discord-ingress/src/gateway.ts:153- The sequence is advanced beforeonDispatchpersistence completes, while close handling settles the connection without draining the processing chain. If the socket closes during a slow or failed PostgreSQL ingest, the next Resume starts after that event and the late failure is swallowed becausefailis already settled, allowing an accepted dispatch to be lost.🔧 Fix: Fixed Discord output, losslessness, close policy, and dispatch durability
4 errors still open:
Dockerfile:146- The required criterion is “Install the CLI and ingress in the common image.” The final image copies the root and ingress dependencies but omitsclis/discord/node_modules; the CLI imports@toon-format/toon, so/usr/local/bin/discordand the ingress startup import can fail at runtime. Copy the Discord CLI dependency tree into the final image.services/discord-ingress/src/events.ts:95-INTERACTION_CREATEreturns before the bot/webhook author checks below, so bot-authored component or modal interactions with a validagentos:custom ID are persisted and acknowledged. Apply the same bot/webhook rejection before handling interactions.services/discord-ingress/src/gateway.ts:243- Anerrorevent immediately schedules a resumable reconnect and cleanup. If the WebSocket then emits a fatal close code, the close handler has been removed and the fatal policy is bypassed, potentially causing repeated invalid resumes instead of a visible failure. Make the close event authoritative before reconnecting (Discord Gateway close-code policy).clis/discord/discord.ts:43- The required criterion includes “structured stdout errors and authoritative exit codes.” A missing or unreadableDISCORD_BOT_TOKEN_FILEthrows the raw filesystem error here; the CLI then fails to recognize it as configuration failure at line 143 and returns exit 1 withdiscord_request_failedinstead of exit 2 withdiscord_configuration. Classify token-file read failures as configuration errors.🔧 Fix: Fixed Discord image, interaction, gateway, and token configuration gaps
2 issues (1 error, 1 warning) still open:
services/discord-ingress/src/gateway.ts:132-onAbortsettles the gateway before awaiting the processing chain. If shutdown arrives during PostgreSQL persistence,runDiscordGatewayreturns and the ingress closes its sink while the accepted dispatch is still in flight; any late persistence failure is swallowed because the connection is already settled, allowing a clean exit with lost evidence. Drain processing before settling or surface the failure.services/discord-ingress/src/events.ts:114- DiscordMESSAGE_DELETEpayloads contain no author fields (Gateway Events), so the bot/webhook filter cannot reject them. This condition accepts every deletion in a managed category, including deletions of bot/webhook messages, despite the ingress contract to ignore those authors. Gate deletes on previously accepted message IDs or confirm the intended recovery trade-off.🔧 Fix: Drained shutdown persistence and gated unknown Discord deletions
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
bun test clis/discord/tests/discord.test.ts services/discord-ingress/tests/events.test.ts services/discord-ingress/tests/gateway.test.ts services/discord-ingress/tests/main.test.ts services/discord-ingress/tests/postgres.test.ts agents/firstmate/kubernetes/tests/manifests.test.tskubectl kustomize agents/firstmate/kubernetes/basekubectl patch --local --type strategic --patch-file agents/firstmate/kubernetes/patches/discord.yamlPublicrunDiscordCliharness covering raw JSON,--axi,--axi --full, bounded collections, and HTTP 429 errorsPublicrunDiscordIngressharness covering released PostgreSQL ingestion and persistence-before-ack orderingdocker build --target agentos-runtime-dependencies --progress=plain .docker build --progress=plain .tmp-image-context-discord-validationdocker run --rm <built-image> discord --helpdocker run --rm <built-image> discord-ingress --helpenv -u DISCORD_BOT_TOKEN -u DISCORD_BOT_TOKEN_FILE bun clis/discord/discord.ts request GET /users/@me --axi✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.