From ed1d985c90e24ca3046bd570a556802927d80ed8 Mon Sep 17 00:00:00 2001 From: Jarvis Date: Mon, 13 Jul 2026 05:10:48 -0500 Subject: [PATCH] fix(tess): route bare Discord approvals --- .../tess-cross-surface.integration.test.ts | 51 +++++++++++++++---- plugins/discord/src/index.ts | 2 +- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts b/apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts index ae43c9a..7bb1118 100644 --- a/apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts +++ b/apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts @@ -2,6 +2,7 @@ import { afterEach, describe, expect, it, vi } from 'vitest'; import { InMemoryDurableSessionStore } from '@mosaicstack/agent'; import { createDiscordIngressEnvelope, + DiscordPlugin, type DiscordIngressPayload, } from '@mosaicstack/discord-plugin'; import { InteractionController } from '../../agent/interaction.controller.js'; @@ -30,7 +31,7 @@ function payload(content: string, messageId: string, correlationId: string): Dis guildId: 'guild-1', channelId: 'channel-1', userId: 'discord-admin-1', - conversationId: 'conversation-1', + conversationId: 'Nova:discord:channel-1', }; } @@ -89,7 +90,7 @@ describe('Tess Discord/CLI durable-session integration', () => { const controller = new InteractionController(enrollmentRuntime as never, durable); await controller.enroll( 'Nova', - 'conversation-1', + 'Nova:discord:channel-1', { providerId: 'fleet', runtimeSessionId: 'runtime-1' }, { id: 'mosaic-admin-1', tenantId: 'tenant-1' }, 'cli-enrollment-correlation', @@ -122,14 +123,46 @@ describe('Tess Discord/CLI durable-session integration', () => { durable, ); const client = { data: { discordService: true }, emit: vi.fn() }; + const plugin = new DiscordPlugin({ + token: 'unused', + gatewayUrl: 'http://unused', + serviceToken: SERVICE_TOKEN, + allowedGuildIds: ['guild-1'], + allowedChannelIds: ['channel-1'], + allowedUserIds: ['discord-admin-1'], + interactionBindings: [ + { + instanceId: 'Nova', + guildId: 'guild-1', + channelId: 'channel-1', + pairedUsers: { + 'discord-admin-1': { role: 'admin', mosaicUserId: 'mosaic-admin-1' }, + }, + }, + ], + }); + const pluginInternals = plugin as unknown as { + client: { user: { id: string } }; + socket: { connected: boolean; emit: ReturnType }; + handleDiscordMessage(message: unknown): void; + }; + const pluginSocket = { connected: true, emit: vi.fn() }; + pluginInternals.client = { user: { id: 'bot-1' } }; + pluginInternals.socket = pluginSocket; + pluginInternals.handleDiscordMessage({ + id: 'approve-1', + guildId: 'guild-1', + channelId: 'channel-1', + author: { id: 'discord-admin-1', bot: false }, + mentions: { has: () => true }, + content: '<@bot-1> /approve', + channel: { parentId: null }, + attachments: new Map(), + }); - await gateway.handleDiscordApproval( - client as never, - createDiscordIngressEnvelope( - payload('/approve', 'approve-1', 'discord-approve-correlation'), - SERVICE_TOKEN, - ), - ); + expect(pluginSocket.emit).toHaveBeenCalledWith('discord:approve', expect.any(Object)); + const approvalEnvelope = pluginSocket.emit.mock.calls[0]?.[1]; + await gateway.handleDiscordApproval(client as never, approvalEnvelope); const approval = client.emit.mock.calls.find( ([event]) => event === 'discord:approval', )?.[1] as { diff --git a/plugins/discord/src/index.ts b/plugins/discord/src/index.ts index d111e87..15d4997 100644 --- a/plugins/discord/src/index.ts +++ b/plugins/discord/src/index.ts @@ -382,7 +382,7 @@ export class DiscordPlugin { this.config.serviceToken, ); this.socket.emit( - content.startsWith('/approve ') + /^\/approve$/i.test(content) ? 'discord:approve' : content.startsWith('/stop ') ? 'discord:stop'