- Fix sendThreadMessage room mismatch: use channelId from options instead of hardcoded controlRoomId - Add .catch() to fire-and-forget handleRoomMessage to prevent silent error swallowing - Wrap dispatchJob in try-catch for user-visible error reporting in handleFixCommand - Add MATRIX_BOT_USER_ID validation in connect() to prevent infinite message loops - Fix streamResponse error masking: wrap finally/catch side-effects in try-catch - Replace unsafe type assertion with public getClient() in MatrixRoomService - Add orphaned room warning in provisionRoom on DB failure - Add provider identity to Herald error logs - Add channelId to ThreadMessageOptions interface and all callers - Add missing env var warnings in BridgeModule factory - Fix JSON injection in setup-bot.sh: use jq for safe JSON construction Fixes #377 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
82 lines
2.8 KiB
TypeScript
82 lines
2.8 KiB
TypeScript
import { Logger, Module } from "@nestjs/common";
|
|
import { DiscordService } from "./discord/discord.service";
|
|
import { MatrixService } from "./matrix/matrix.service";
|
|
import { MatrixRoomService } from "./matrix/matrix-room.service";
|
|
import { MatrixStreamingService } from "./matrix/matrix-streaming.service";
|
|
import { CommandParserService } from "./parser/command-parser.service";
|
|
import { StitcherModule } from "../stitcher/stitcher.module";
|
|
import { CHAT_PROVIDERS } from "./bridge.constants";
|
|
import type { IChatProvider } from "./interfaces";
|
|
|
|
const logger = new Logger("BridgeModule");
|
|
|
|
/**
|
|
* Bridge Module - Chat platform integrations
|
|
*
|
|
* Provides integration with chat platforms (Discord, Matrix, etc.)
|
|
* for controlling Mosaic Stack via chat commands.
|
|
*
|
|
* Both services are always registered as providers, but the CHAT_PROVIDERS
|
|
* injection token only includes bridges whose environment variables are set:
|
|
* - Discord: included when DISCORD_BOT_TOKEN is set
|
|
* - Matrix: included when MATRIX_ACCESS_TOKEN is set
|
|
*
|
|
* Both bridges can run simultaneously, and no error occurs if neither is configured.
|
|
* Consumers should inject CHAT_PROVIDERS for bridge-agnostic access to all active providers.
|
|
*
|
|
* CommandParserService provides shared, platform-agnostic command parsing.
|
|
* MatrixRoomService handles workspace-to-Matrix-room mapping.
|
|
*/
|
|
@Module({
|
|
imports: [StitcherModule],
|
|
providers: [
|
|
CommandParserService,
|
|
MatrixRoomService,
|
|
MatrixStreamingService,
|
|
DiscordService,
|
|
MatrixService,
|
|
{
|
|
provide: CHAT_PROVIDERS,
|
|
useFactory: (discord: DiscordService, matrix: MatrixService): IChatProvider[] => {
|
|
const providers: IChatProvider[] = [];
|
|
|
|
if (process.env.DISCORD_BOT_TOKEN) {
|
|
providers.push(discord);
|
|
logger.log("Discord bridge enabled (DISCORD_BOT_TOKEN detected)");
|
|
}
|
|
|
|
if (process.env.MATRIX_ACCESS_TOKEN) {
|
|
const missingVars = [
|
|
"MATRIX_HOMESERVER_URL",
|
|
"MATRIX_BOT_USER_ID",
|
|
"MATRIX_WORKSPACE_ID",
|
|
].filter((v) => !process.env[v]);
|
|
if (missingVars.length > 0) {
|
|
logger.warn(
|
|
`Matrix bridge enabled but missing: ${missingVars.join(", ")}. connect() will fail.`
|
|
);
|
|
}
|
|
providers.push(matrix);
|
|
logger.log("Matrix bridge enabled (MATRIX_ACCESS_TOKEN detected)");
|
|
}
|
|
|
|
if (providers.length === 0) {
|
|
logger.warn("No chat bridges configured. Set DISCORD_BOT_TOKEN or MATRIX_ACCESS_TOKEN.");
|
|
}
|
|
|
|
return providers;
|
|
},
|
|
inject: [DiscordService, MatrixService],
|
|
},
|
|
],
|
|
exports: [
|
|
DiscordService,
|
|
MatrixService,
|
|
MatrixRoomService,
|
|
MatrixStreamingService,
|
|
CommandParserService,
|
|
CHAT_PROVIDERS,
|
|
],
|
|
})
|
|
export class BridgeModule {}
|