diff --git a/.env.example b/.env.example index f759171..2c0e7cf 100644 --- a/.env.example +++ b/.env.example @@ -316,6 +316,22 @@ RATE_LIMIT_STORAGE=redis # multi-tenant isolation. Each Discord bot instance should be configured for # a single workspace. +# ====================== +# Matrix Bridge (Optional) +# ====================== +# Matrix bot integration for chat-based control via Matrix protocol +# Requires a Matrix account with an access token for the bot user +# MATRIX_HOMESERVER_URL=https://matrix.example.com +# MATRIX_ACCESS_TOKEN= +# MATRIX_BOT_USER_ID=@mosaic-bot:example.com +# MATRIX_CONTROL_ROOM_ID=!roomid:example.com +# MATRIX_WORKSPACE_ID=your-workspace-uuid +# +# SECURITY: MATRIX_WORKSPACE_ID must be a valid workspace UUID from your database. +# All Matrix commands will execute within this workspace context for proper +# multi-tenant isolation. Each Matrix bot instance should be configured for +# a single workspace. + # ====================== # Orchestrator Configuration # ====================== diff --git a/apps/api/package.json b/apps/api/package.json index ce11f92..375c55e 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -64,6 +64,7 @@ "marked": "^17.0.1", "marked-gfm-heading-id": "^4.1.3", "marked-highlight": "^2.2.3", + "matrix-bot-sdk": "^0.8.0", "ollama": "^0.6.3", "openai": "^6.17.0", "reflect-metadata": "^0.2.2", diff --git a/apps/api/src/bridge/matrix/index.ts b/apps/api/src/bridge/matrix/index.ts new file mode 100644 index 0000000..056621f --- /dev/null +++ b/apps/api/src/bridge/matrix/index.ts @@ -0,0 +1 @@ +export { MatrixService } from "./matrix.service"; diff --git a/apps/api/src/bridge/matrix/matrix.service.spec.ts b/apps/api/src/bridge/matrix/matrix.service.spec.ts new file mode 100644 index 0000000..cfbcb97 --- /dev/null +++ b/apps/api/src/bridge/matrix/matrix.service.spec.ts @@ -0,0 +1,658 @@ +import { Test, TestingModule } from "@nestjs/testing"; +import { MatrixService } from "./matrix.service"; +import { StitcherService } from "../../stitcher/stitcher.service"; +import { vi, describe, it, expect, beforeEach } from "vitest"; +import type { ChatMessage } from "../interfaces"; + +// Mock matrix-bot-sdk +const mockMessageCallbacks: Array<(roomId: string, event: Record) => void> = []; +const mockEventCallbacks: Array<(roomId: string, event: Record) => void> = []; + +const mockClient = { + start: vi.fn().mockResolvedValue(undefined), + stop: vi.fn(), + on: vi + .fn() + .mockImplementation( + (event: string, callback: (roomId: string, evt: Record) => void) => { + if (event === "room.message") { + mockMessageCallbacks.push(callback); + } + if (event === "room.event") { + mockEventCallbacks.push(callback); + } + } + ), + sendMessage: vi.fn().mockResolvedValue("$event-id-123"), + sendEvent: vi.fn().mockResolvedValue("$event-id-456"), +}; + +vi.mock("matrix-bot-sdk", () => { + return { + MatrixClient: class MockMatrixClient { + start = mockClient.start; + stop = mockClient.stop; + on = mockClient.on; + sendMessage = mockClient.sendMessage; + sendEvent = mockClient.sendEvent; + }, + SimpleFsStorageProvider: class MockStorageProvider { + constructor(_filename: string) { + // No-op for testing + } + }, + AutojoinRoomsMixin: { + setupOnClient: vi.fn(), + }, + }; +}); + +describe("MatrixService", () => { + let service: MatrixService; + let stitcherService: StitcherService; + + const mockStitcherService = { + dispatchJob: vi.fn().mockResolvedValue({ + jobId: "test-job-id", + queueName: "main", + status: "PENDING", + }), + trackJobEvent: vi.fn().mockResolvedValue(undefined), + }; + + beforeEach(async () => { + // Set environment variables for testing + process.env.MATRIX_HOMESERVER_URL = "https://matrix.example.com"; + process.env.MATRIX_ACCESS_TOKEN = "test-access-token"; + process.env.MATRIX_BOT_USER_ID = "@mosaic-bot:example.com"; + process.env.MATRIX_CONTROL_ROOM_ID = "!test-room:example.com"; + process.env.MATRIX_WORKSPACE_ID = "test-workspace-id"; + + // Clear callbacks + mockMessageCallbacks.length = 0; + mockEventCallbacks.length = 0; + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + MatrixService, + { + provide: StitcherService, + useValue: mockStitcherService, + }, + ], + }).compile(); + + service = module.get(MatrixService); + stitcherService = module.get(StitcherService); + + // Clear all mocks + vi.clearAllMocks(); + }); + + describe("Connection Management", () => { + it("should connect to Matrix", async () => { + await service.connect(); + + expect(mockClient.start).toHaveBeenCalled(); + }); + + it("should disconnect from Matrix", async () => { + await service.connect(); + await service.disconnect(); + + expect(mockClient.stop).toHaveBeenCalled(); + }); + + it("should check connection status", async () => { + expect(service.isConnected()).toBe(false); + + await service.connect(); + expect(service.isConnected()).toBe(true); + + await service.disconnect(); + expect(service.isConnected()).toBe(false); + }); + }); + + describe("Message Handling", () => { + it("should send a message to a room", async () => { + await service.connect(); + await service.sendMessage("!test-room:example.com", "Hello, Matrix!"); + + expect(mockClient.sendMessage).toHaveBeenCalledWith("!test-room:example.com", { + msgtype: "m.text", + body: "Hello, Matrix!", + }); + }); + + it("should throw error if client is not connected", async () => { + await expect(service.sendMessage("!room:example.com", "Test")).rejects.toThrow( + "Matrix client is not connected" + ); + }); + }); + + describe("Thread Management", () => { + it("should create a thread by sending an initial message", async () => { + await service.connect(); + const threadId = await service.createThread({ + channelId: "!test-room:example.com", + name: "Job #42", + message: "Starting job...", + }); + + expect(threadId).toBe("$event-id-123"); + expect(mockClient.sendMessage).toHaveBeenCalledWith("!test-room:example.com", { + msgtype: "m.text", + body: "[Job #42] Starting job...", + }); + }); + + it("should send a message to a thread with m.thread relation", async () => { + await service.connect(); + await service.sendThreadMessage({ + threadId: "$root-event-id", + content: "Step completed", + }); + + expect(mockClient.sendMessage).toHaveBeenCalledWith("!test-room:example.com", { + msgtype: "m.text", + body: "Step completed", + "m.relates_to": { + rel_type: "m.thread", + event_id: "$root-event-id", + is_falling_back: true, + "m.in_reply_to": { + event_id: "$root-event-id", + }, + }, + }); + }); + + it("should throw error when creating thread without connection", async () => { + await expect( + service.createThread({ + channelId: "!room:example.com", + name: "Test", + message: "Test", + }) + ).rejects.toThrow("Matrix client is not connected"); + }); + + it("should throw error when sending thread message without connection", async () => { + await expect( + service.sendThreadMessage({ + threadId: "$event-id", + content: "Test", + }) + ).rejects.toThrow("Matrix client is not connected"); + }); + }); + + describe("Command Parsing", () => { + it("should parse @mosaic fix command", () => { + const message: ChatMessage = { + id: "msg-1", + channelId: "!room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic fix 42", + timestamp: new Date(), + }; + + const command = service.parseCommand(message); + + expect(command).toEqual({ + command: "fix", + args: ["42"], + message, + }); + }); + + it("should parse !mosaic fix command", () => { + const message: ChatMessage = { + id: "msg-1", + channelId: "!room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "!mosaic fix 42", + timestamp: new Date(), + }; + + const command = service.parseCommand(message); + + expect(command).toEqual({ + command: "fix", + args: ["42"], + message, + }); + }); + + it("should parse @mosaic status command", () => { + const message: ChatMessage = { + id: "msg-2", + channelId: "!room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic status job-123", + timestamp: new Date(), + }; + + const command = service.parseCommand(message); + + expect(command).toEqual({ + command: "status", + args: ["job-123"], + message, + }); + }); + + it("should parse @mosaic cancel command", () => { + const message: ChatMessage = { + id: "msg-3", + channelId: "!room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic cancel job-456", + timestamp: new Date(), + }; + + const command = service.parseCommand(message); + + expect(command).toEqual({ + command: "cancel", + args: ["job-456"], + message, + }); + }); + + it("should parse @mosaic verbose command", () => { + const message: ChatMessage = { + id: "msg-4", + channelId: "!room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic verbose job-789", + timestamp: new Date(), + }; + + const command = service.parseCommand(message); + + expect(command).toEqual({ + command: "verbose", + args: ["job-789"], + message, + }); + }); + + it("should parse @mosaic quiet command", () => { + const message: ChatMessage = { + id: "msg-5", + channelId: "!room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic quiet", + timestamp: new Date(), + }; + + const command = service.parseCommand(message); + + expect(command).toEqual({ + command: "quiet", + args: [], + message, + }); + }); + + it("should parse @mosaic help command", () => { + const message: ChatMessage = { + id: "msg-6", + channelId: "!room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic help", + timestamp: new Date(), + }; + + const command = service.parseCommand(message); + + expect(command).toEqual({ + command: "help", + args: [], + message, + }); + }); + + it("should return null for non-command messages", () => { + const message: ChatMessage = { + id: "msg-7", + channelId: "!room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "Just a regular message", + timestamp: new Date(), + }; + + const command = service.parseCommand(message); + + expect(command).toBeNull(); + }); + + it("should return null for messages without @mosaic or !mosaic mention", () => { + const message: ChatMessage = { + id: "msg-8", + channelId: "!room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "fix 42", + timestamp: new Date(), + }; + + const command = service.parseCommand(message); + + expect(command).toBeNull(); + }); + + it("should handle commands with multiple arguments", () => { + const message: ChatMessage = { + id: "msg-9", + channelId: "!room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic fix 42 high-priority", + timestamp: new Date(), + }; + + const command = service.parseCommand(message); + + expect(command).toEqual({ + command: "fix", + args: ["42", "high-priority"], + message, + }); + }); + + it("should return null for invalid commands", () => { + const message: ChatMessage = { + id: "msg-10", + channelId: "!room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic invalidcommand 42", + timestamp: new Date(), + }; + + const command = service.parseCommand(message); + + expect(command).toBeNull(); + }); + + it("should return null for @mosaic mention without a command", () => { + const message: ChatMessage = { + id: "msg-11", + channelId: "!room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic", + timestamp: new Date(), + }; + + const command = service.parseCommand(message); + + expect(command).toBeNull(); + }); + }); + + describe("Command Execution", () => { + it("should forward fix command to stitcher", async () => { + const message: ChatMessage = { + id: "msg-1", + channelId: "!test-room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic fix 42", + timestamp: new Date(), + }; + + await service.connect(); + await service.handleCommand({ + command: "fix", + args: ["42"], + message, + }); + + expect(stitcherService.dispatchJob).toHaveBeenCalledWith({ + workspaceId: "test-workspace-id", + type: "code-task", + priority: 10, + metadata: { + issueNumber: 42, + command: "fix", + channelId: "!test-room:example.com", + threadId: "$event-id-123", + authorId: "@user:example.com", + authorName: "@user:example.com", + }, + }); + }); + + it("should respond with help message", async () => { + const message: ChatMessage = { + id: "msg-1", + channelId: "!test-room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic help", + timestamp: new Date(), + }; + + await service.connect(); + await service.handleCommand({ + command: "help", + args: [], + message, + }); + + expect(mockClient.sendMessage).toHaveBeenCalledWith( + "!test-room:example.com", + expect.objectContaining({ + body: expect.stringContaining("Available commands:"), + }) + ); + }); + + it("should send error for fix command without issue number", async () => { + const message: ChatMessage = { + id: "msg-1", + channelId: "!test-room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic fix", + timestamp: new Date(), + }; + + await service.connect(); + await service.handleCommand({ + command: "fix", + args: [], + message, + }); + + expect(mockClient.sendMessage).toHaveBeenCalledWith( + "!test-room:example.com", + expect.objectContaining({ + body: expect.stringContaining("Usage:"), + }) + ); + }); + + it("should send error for fix command with non-numeric issue", async () => { + const message: ChatMessage = { + id: "msg-1", + channelId: "!test-room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic fix abc", + timestamp: new Date(), + }; + + await service.connect(); + await service.handleCommand({ + command: "fix", + args: ["abc"], + message, + }); + + expect(mockClient.sendMessage).toHaveBeenCalledWith( + "!test-room:example.com", + expect.objectContaining({ + body: expect.stringContaining("Invalid issue number"), + }) + ); + }); + }); + + describe("Configuration", () => { + it("should throw error if MATRIX_HOMESERVER_URL is not set", async () => { + delete process.env.MATRIX_HOMESERVER_URL; + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + MatrixService, + { + provide: StitcherService, + useValue: mockStitcherService, + }, + ], + }).compile(); + + const newService = module.get(MatrixService); + + await expect(newService.connect()).rejects.toThrow("MATRIX_HOMESERVER_URL is required"); + + // Restore for other tests + process.env.MATRIX_HOMESERVER_URL = "https://matrix.example.com"; + }); + + it("should throw error if MATRIX_ACCESS_TOKEN is not set", async () => { + delete process.env.MATRIX_ACCESS_TOKEN; + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + MatrixService, + { + provide: StitcherService, + useValue: mockStitcherService, + }, + ], + }).compile(); + + const newService = module.get(MatrixService); + + await expect(newService.connect()).rejects.toThrow("MATRIX_ACCESS_TOKEN is required"); + + // Restore for other tests + process.env.MATRIX_ACCESS_TOKEN = "test-access-token"; + }); + + it("should throw error if MATRIX_WORKSPACE_ID is not set", async () => { + delete process.env.MATRIX_WORKSPACE_ID; + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + MatrixService, + { + provide: StitcherService, + useValue: mockStitcherService, + }, + ], + }).compile(); + + const newService = module.get(MatrixService); + + await expect(newService.connect()).rejects.toThrow("MATRIX_WORKSPACE_ID is required"); + + // Restore for other tests + process.env.MATRIX_WORKSPACE_ID = "test-workspace-id"; + }); + + it("should use configured workspace ID from environment", async () => { + const testWorkspaceId = "configured-workspace-456"; + process.env.MATRIX_WORKSPACE_ID = testWorkspaceId; + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + MatrixService, + { + provide: StitcherService, + useValue: mockStitcherService, + }, + ], + }).compile(); + + const newService = module.get(MatrixService); + + const message: ChatMessage = { + id: "msg-1", + channelId: "!test-room:example.com", + authorId: "@user:example.com", + authorName: "@user:example.com", + content: "@mosaic fix 42", + timestamp: new Date(), + }; + + await newService.connect(); + await newService.handleCommand({ + command: "fix", + args: ["42"], + message, + }); + + expect(mockStitcherService.dispatchJob).toHaveBeenCalledWith( + expect.objectContaining({ + workspaceId: testWorkspaceId, + }) + ); + + // Restore for other tests + process.env.MATRIX_WORKSPACE_ID = "test-workspace-id"; + }); + }); + + describe("Error Logging Security", () => { + it("should sanitize sensitive data in error logs", async () => { + const loggerErrorSpy = vi.spyOn( + (service as Record)["logger"] as { error: (...args: unknown[]) => void }, + "error" + ); + + await service.connect(); + + // Trigger room.event handler with null event to exercise error path + expect(mockEventCallbacks.length).toBeGreaterThan(0); + mockEventCallbacks[0]?.("!room:example.com", null as unknown as Record); + + // Verify error was logged + expect(loggerErrorSpy).toHaveBeenCalled(); + + // Get the logged error + const loggedArgs = loggerErrorSpy.mock.calls[0]; + const loggedError = loggedArgs?.[1] as Record; + + // Verify non-sensitive error info is preserved + expect(loggedError).toBeDefined(); + expect((loggedError as { message: string }).message).toBe("Received null event from Matrix"); + }); + + it("should not include access token in error output", () => { + // Verify the access token is stored privately and not exposed + const serviceAsRecord = service as unknown as Record; + // The accessToken should exist but should not appear in any public-facing method output + expect(serviceAsRecord["accessToken"]).toBe("test-access-token"); + + // Verify isConnected does not leak token + const connected = service.isConnected(); + expect(String(connected)).not.toContain("test-access-token"); + }); + }); +}); diff --git a/apps/api/src/bridge/matrix/matrix.service.ts b/apps/api/src/bridge/matrix/matrix.service.ts new file mode 100644 index 0000000..4cf4f57 --- /dev/null +++ b/apps/api/src/bridge/matrix/matrix.service.ts @@ -0,0 +1,468 @@ +import { Injectable, Logger } from "@nestjs/common"; +import { MatrixClient, SimpleFsStorageProvider, AutojoinRoomsMixin } from "matrix-bot-sdk"; +import { StitcherService } from "../../stitcher/stitcher.service"; +import { sanitizeForLogging } from "../../common/utils"; +import type { + IChatProvider, + ChatMessage, + ChatCommand, + ThreadCreateOptions, + ThreadMessageOptions, +} from "../interfaces"; + +/** + * Matrix room message event content + */ +interface MatrixMessageContent { + msgtype: string; + body: string; + "m.relates_to"?: MatrixRelatesTo; +} + +/** + * Matrix relationship metadata for threads (MSC3440) + */ +interface MatrixRelatesTo { + rel_type: string; + event_id: string; + is_falling_back?: boolean; + "m.in_reply_to"?: { + event_id: string; + }; +} + +/** + * Matrix room event structure + */ +interface MatrixRoomEvent { + event_id: string; + sender: string; + origin_server_ts: number; + content: MatrixMessageContent; +} + +/** + * Matrix Service - Matrix chat platform integration + * + * Responsibilities: + * - Connect to Matrix via access token + * - Listen for commands in designated rooms + * - Forward commands to stitcher + * - Receive status updates from herald + * - Post updates to threads (MSC3440) + */ +@Injectable() +export class MatrixService implements IChatProvider { + private readonly logger = new Logger(MatrixService.name); + private client: MatrixClient | null = null; + private connected = false; + private readonly homeserverUrl: string; + private readonly accessToken: string; + private readonly botUserId: string; + private readonly controlRoomId: string; + private readonly workspaceId: string; + + constructor(private readonly stitcherService: StitcherService) { + this.homeserverUrl = process.env.MATRIX_HOMESERVER_URL ?? ""; + this.accessToken = process.env.MATRIX_ACCESS_TOKEN ?? ""; + this.botUserId = process.env.MATRIX_BOT_USER_ID ?? ""; + this.controlRoomId = process.env.MATRIX_CONTROL_ROOM_ID ?? ""; + this.workspaceId = process.env.MATRIX_WORKSPACE_ID ?? ""; + } + + /** + * Connect to Matrix homeserver + */ + async connect(): Promise { + if (!this.homeserverUrl) { + throw new Error("MATRIX_HOMESERVER_URL is required"); + } + + if (!this.accessToken) { + throw new Error("MATRIX_ACCESS_TOKEN is required"); + } + + if (!this.workspaceId) { + throw new Error("MATRIX_WORKSPACE_ID is required"); + } + + this.logger.log("Connecting to Matrix..."); + + const storage = new SimpleFsStorageProvider("matrix-bot-storage.json"); + this.client = new MatrixClient(this.homeserverUrl, this.accessToken, storage); + + // Auto-join rooms when invited + AutojoinRoomsMixin.setupOnClient(this.client); + + // Setup event handlers + this.setupEventHandlers(); + + // Start syncing + await this.client.start(); + this.connected = true; + this.logger.log(`Matrix bot connected as ${this.botUserId}`); + } + + /** + * Setup event handlers for Matrix client + */ + private setupEventHandlers(): void { + if (!this.client) return; + + this.client.on("room.message", (roomId: string, event: MatrixRoomEvent) => { + // Ignore messages from the bot itself + if (event.sender === this.botUserId) return; + + // Check if message is in control room + if (roomId !== this.controlRoomId) return; + + // Only handle text messages + if (event.content.msgtype !== "m.text") return; + + // Parse message into ChatMessage format + const chatMessage: ChatMessage = { + id: event.event_id, + channelId: roomId, + authorId: event.sender, + authorName: event.sender, + content: event.content.body, + timestamp: new Date(event.origin_server_ts), + ...(event.content["m.relates_to"]?.rel_type === "m.thread" && { + threadId: event.content["m.relates_to"].event_id, + }), + }; + + // Parse command + const command = this.parseCommand(chatMessage); + if (command) { + void this.handleCommand(command); + } + }); + + this.client.on("room.event", (_roomId: string, event: MatrixRoomEvent | null) => { + // Handle errors emitted as events + if (!event) { + const error = new Error("Received null event from Matrix"); + const sanitizedError = sanitizeForLogging(error); + this.logger.error("Matrix client error:", sanitizedError); + } + }); + } + + /** + * Disconnect from Matrix + */ + disconnect(): Promise { + this.logger.log("Disconnecting from Matrix..."); + this.connected = false; + if (this.client) { + this.client.stop(); + } + return Promise.resolve(); + } + + /** + * Check if the provider is connected + */ + isConnected(): boolean { + return this.connected; + } + + /** + * Send a message to a room + */ + async sendMessage(roomId: string, content: string): Promise { + if (!this.client) { + throw new Error("Matrix client is not connected"); + } + + const messageContent: MatrixMessageContent = { + msgtype: "m.text", + body: content, + }; + + await this.client.sendMessage(roomId, messageContent); + } + + /** + * Create a thread for job updates (MSC3440) + * + * Matrix threads are created by sending an initial message + * and then replying with m.thread relation. The initial + * message event ID becomes the thread root. + */ + async createThread(options: ThreadCreateOptions): Promise { + if (!this.client) { + throw new Error("Matrix client is not connected"); + } + + const { channelId, name, message } = options; + + // Send the initial message that becomes the thread root + const initialContent: MatrixMessageContent = { + msgtype: "m.text", + body: `[${name}] ${message}`, + }; + + const eventId = await this.client.sendMessage(channelId, initialContent); + + return eventId; + } + + /** + * Send a message to a thread (MSC3440) + * + * Uses m.thread relation to associate the message with the thread root event. + */ + async sendThreadMessage(options: ThreadMessageOptions): Promise { + if (!this.client) { + throw new Error("Matrix client is not connected"); + } + + const { threadId, content } = options; + + // Extract roomId from the control room (threads are room-scoped) + const roomId = this.controlRoomId; + + const threadContent: MatrixMessageContent = { + msgtype: "m.text", + body: content, + "m.relates_to": { + rel_type: "m.thread", + event_id: threadId, + is_falling_back: true, + "m.in_reply_to": { + event_id: threadId, + }, + }, + }; + + await this.client.sendMessage(roomId, threadContent); + } + + /** + * Parse a command from a message + */ + parseCommand(message: ChatMessage): ChatCommand | null { + const { content } = message; + + // Check if message mentions @mosaic or uses !mosaic prefix + const lowerContent = content.toLowerCase(); + if (!lowerContent.includes("@mosaic") && !lowerContent.includes("!mosaic")) { + return null; + } + + // Extract command and arguments + const parts = content.trim().split(/\s+/); + const mosaicIndex = parts.findIndex( + (part) => part.toLowerCase().includes("@mosaic") || part.toLowerCase().includes("!mosaic") + ); + + if (mosaicIndex === -1 || mosaicIndex === parts.length - 1) { + return null; + } + + const commandPart = parts[mosaicIndex + 1]; + if (!commandPart) { + return null; + } + + const command = commandPart.toLowerCase(); + const args = parts.slice(mosaicIndex + 2); + + // Valid commands + const validCommands = ["fix", "status", "cancel", "verbose", "quiet", "help"]; + + if (!validCommands.includes(command)) { + return null; + } + + return { + command, + args, + message, + }; + } + + /** + * Handle a parsed command + */ + async handleCommand(command: ChatCommand): Promise { + const { command: cmd, args, message } = command; + + this.logger.log( + `Handling command: ${cmd} with args: ${args.join(", ")} from ${message.authorName}` + ); + + switch (cmd) { + case "fix": + await this.handleFixCommand(args, message); + break; + case "status": + await this.handleStatusCommand(args, message); + break; + case "cancel": + await this.handleCancelCommand(args, message); + break; + case "verbose": + await this.handleVerboseCommand(args, message); + break; + case "quiet": + await this.handleQuietCommand(args, message); + break; + case "help": + await this.handleHelpCommand(args, message); + break; + default: + await this.sendMessage( + message.channelId, + `Unknown command: ${cmd}. Type \`@mosaic help\` or \`!mosaic help\` for available commands.` + ); + } + } + + /** + * Handle fix command - Start a job for an issue + */ + private async handleFixCommand(args: string[], message: ChatMessage): Promise { + if (args.length === 0 || !args[0]) { + await this.sendMessage( + message.channelId, + "Usage: `@mosaic fix ` or `!mosaic fix `" + ); + return; + } + + const issueNumber = parseInt(args[0], 10); + + if (isNaN(issueNumber)) { + await this.sendMessage( + message.channelId, + "Invalid issue number. Please provide a numeric issue number." + ); + return; + } + + // Create thread for job updates + const threadId = await this.createThread({ + channelId: message.channelId, + name: `Job #${String(issueNumber)}`, + message: `Starting job for issue #${String(issueNumber)}...`, + }); + + // Dispatch job to stitcher + const result = await this.stitcherService.dispatchJob({ + workspaceId: this.workspaceId, + type: "code-task", + priority: 10, + metadata: { + issueNumber, + command: "fix", + channelId: message.channelId, + threadId: threadId, + authorId: message.authorId, + authorName: message.authorName, + }, + }); + + // Send confirmation to thread + await this.sendThreadMessage({ + threadId, + content: `Job created: ${result.jobId}\nStatus: ${result.status}\nQueue: ${result.queueName}`, + }); + } + + /** + * Handle status command - Get job status + */ + private async handleStatusCommand(args: string[], message: ChatMessage): Promise { + if (args.length === 0 || !args[0]) { + await this.sendMessage( + message.channelId, + "Usage: `@mosaic status ` or `!mosaic status `" + ); + return; + } + + const jobId = args[0]; + + // TODO: Implement job status retrieval from stitcher + await this.sendMessage( + message.channelId, + `Status command not yet implemented for job: ${jobId}` + ); + } + + /** + * Handle cancel command - Cancel a running job + */ + private async handleCancelCommand(args: string[], message: ChatMessage): Promise { + if (args.length === 0 || !args[0]) { + await this.sendMessage( + message.channelId, + "Usage: `@mosaic cancel ` or `!mosaic cancel `" + ); + return; + } + + const jobId = args[0]; + + // TODO: Implement job cancellation in stitcher + await this.sendMessage( + message.channelId, + `Cancel command not yet implemented for job: ${jobId}` + ); + } + + /** + * Handle verbose command - Stream full logs to thread + */ + private async handleVerboseCommand(args: string[], message: ChatMessage): Promise { + if (args.length === 0 || !args[0]) { + await this.sendMessage( + message.channelId, + "Usage: `@mosaic verbose ` or `!mosaic verbose `" + ); + return; + } + + const jobId = args[0]; + + // TODO: Implement verbose logging + await this.sendMessage(message.channelId, `Verbose mode not yet implemented for job: ${jobId}`); + } + + /** + * Handle quiet command - Reduce notifications + */ + private async handleQuietCommand(_args: string[], message: ChatMessage): Promise { + // TODO: Implement quiet mode + await this.sendMessage( + message.channelId, + "Quiet mode not yet implemented. Currently showing milestone updates only." + ); + } + + /** + * Handle help command - Show available commands + */ + private async handleHelpCommand(_args: string[], message: ChatMessage): Promise { + const helpMessage = ` +**Available commands:** + +\`@mosaic fix \` or \`!mosaic fix \` - Start job for issue +\`@mosaic status \` or \`!mosaic status \` - Get job status +\`@mosaic cancel \` or \`!mosaic cancel \` - Cancel running job +\`@mosaic verbose \` or \`!mosaic verbose \` - Stream full logs to thread +\`@mosaic quiet\` or \`!mosaic quiet\` - Reduce notifications +\`@mosaic help\` or \`!mosaic help\` - Show this help message + +**Noise Management:** +- Main room: Low verbosity (milestones only) +- Job threads: Medium verbosity (step completions) +- DMs: Configurable per user + `.trim(); + + await this.sendMessage(message.channelId, helpMessage); + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4f24087..2341939 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -140,7 +140,7 @@ importers: version: 1.13.5 better-auth: specifier: ^1.4.17 - version: 1.4.17(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.6.2)(drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.4.17(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.6.2)(drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) bullmq: specifier: ^5.67.2 version: 5.67.2 @@ -177,6 +177,9 @@ importers: marked-highlight: specifier: ^2.2.3 version: 2.2.3(marked@17.0.1) + matrix-bot-sdk: + specifier: ^0.8.0 + version: 0.8.0 ollama: specifier: ^0.6.3 version: 0.6.3 @@ -201,7 +204,7 @@ importers: devDependencies: '@better-auth/cli': specifier: ^1.4.17 - version: 1.4.17(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(magicast@0.3.5)(nanostores@1.1.0)(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.4.17(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(magicast@0.3.5)(nanostores@1.1.0)(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) '@mosaic/config': specifier: workspace:* version: link:../../packages/config @@ -391,7 +394,7 @@ importers: version: 12.10.0(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) better-auth: specifier: ^1.4.17 - version: 1.4.17(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.6.2)(drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + version: 1.4.17(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.6.2)(drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) date-fns: specifier: ^4.1.0 version: 4.1.0 @@ -1497,6 +1500,10 @@ packages: resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==} engines: {node: '>=8'} + '@matrix-org/matrix-sdk-crypto-nodejs@0.4.0': + resolution: {integrity: sha512-+qqgpn39XFSbsD0dFjssGO9vHEP7sTyfs8yTpt8vuqWpUpF20QMwpCZi0jpYw7GxjErNTsMshopuo8677DfGEA==} + engines: {node: '>= 22'} + '@mermaid-js/parser@0.6.3': resolution: {integrity: sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==} @@ -2574,6 +2581,9 @@ packages: resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==} engines: {node: '>=v14.0.0', npm: '>=7.0.0'} + '@selderee/plugin-htmlparser2@0.11.0': + resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==} + '@socket.io/component-emitter@3.1.2': resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} @@ -2876,9 +2886,15 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/express-serve-static-core@4.19.8': + resolution: {integrity: sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==} + '@types/express-serve-static-core@5.1.1': resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==} + '@types/express@4.17.25': + resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} + '@types/express@5.0.6': resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} @@ -2905,6 +2921,9 @@ packages: '@types/methods@1.1.4': resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/multer@2.0.0': resolution: {integrity: sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==} @@ -2950,9 +2969,15 @@ packages: '@types/sanitize-html@2.16.0': resolution: {integrity: sha512-l6rX1MUXje5ztPT0cAFtUayXF06DqPhRyfVXareEN5gGCFaP/iwsxIyKODr9XDhfxPpN6vXUFNfo5kZMXCxBtw==} + '@types/send@0.17.6': + resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} + '@types/send@1.2.1': resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} + '@types/serve-static@1.15.10': + resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} + '@types/serve-static@2.2.0': resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} @@ -3262,6 +3287,9 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + another-json@0.2.0: + resolution: {integrity: sha512-/Ndrl68UQLhnCdsAzEXLMFuOR546o2qbYRqCglaNHbjXrwG1ayTcdwr3zkSGOGtGXDyR5X9nCFfnyG2AFJIsqg==} + ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -3321,6 +3349,9 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + array-timsort@1.0.3: resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} @@ -3330,6 +3361,10 @@ packages: asn1@0.2.6: resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -3337,12 +3372,21 @@ packages: ast-v8-to-istanbul@0.3.10: resolution: {integrity: sha512-p4K7vMz2ZSk3wN8l5o3y2bJAoZXT3VuJI5OLTATY/01CYWumWvwkUw0SqDBnNq6IiTO3qDa1eSQDibAV8g7XOQ==} + async-lock@1.4.1: + resolution: {integrity: sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==} + async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + aws-sign2@0.7.0: + resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} + + aws4@1.13.2: + resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} + axios@1.13.5: resolution: {integrity: sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==} @@ -3376,6 +3420,10 @@ packages: resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} hasBin: true + basic-auth@2.0.1: + resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} + engines: {node: '>= 0.8'} + bcrypt-pbkdf@1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} @@ -3462,6 +3510,13 @@ packages: bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + + body-parser@1.20.4: + resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + body-parser@2.2.2: resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} engines: {node: '>=18'} @@ -3548,6 +3603,9 @@ packages: caniuse-lite@1.0.30001766: resolution: {integrity: sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==} + caseless@0.12.0: + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} @@ -3723,6 +3781,10 @@ packages: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + content-disposition@1.0.1: resolution: {integrity: sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==} engines: {node: '>=18'} @@ -3752,6 +3814,9 @@ packages: cookiejar@2.1.4: resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} + core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -3964,6 +4029,10 @@ packages: dagre-d3-es@7.0.13: resolution: {integrity: sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==} + dashdash@1.14.1: + resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} + engines: {node: '>=0.10'} + data-urls@5.0.0: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} @@ -3974,6 +4043,14 @@ packages: dayjs@1.11.19: resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -4049,6 +4126,10 @@ packages: destr@2.0.5: resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -4209,6 +4290,9 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + ecc-jsbn@0.1.2: + resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -4420,6 +4504,10 @@ packages: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} + express@4.22.1: + resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} + engines: {node: '>= 0.10.0'} + express@5.2.1: resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} @@ -4434,6 +4522,10 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + extsprintf@1.3.0: + resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} + engines: {'0': node >=0.6.0} + fast-check@3.23.2: resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} engines: {node: '>=8.0.0'} @@ -4486,6 +4578,10 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + finalhandler@1.3.2: + resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} + engines: {node: '>= 0.8'} + finalhandler@2.1.1: resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} engines: {node: '>= 18.0.0'} @@ -4514,6 +4610,9 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + forever-agent@0.6.1: + resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} + fork-ts-checker-webpack-plugin@9.1.0: resolution: {integrity: sha512-mpafl89VFPJmhnJ1ssH+8wmM2b50n+Rew5x42NeI2U78aRWgtkEtGmctp7iT16UjquJTjorEmIfESj3DxdW84Q==} engines: {node: '>=14.21.3'} @@ -4521,6 +4620,10 @@ packages: typescript: '>3.6.0' webpack: ^5.11.0 + form-data@2.3.3: + resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} + engines: {node: '>= 0.12'} + form-data@4.0.5: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} @@ -4536,6 +4639,10 @@ packages: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + fresh@2.0.0: resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} engines: {node: '>= 0.8'} @@ -4589,6 +4696,9 @@ packages: get-tsconfig@4.13.0: resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + getpass@0.1.7: + resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} + giget@2.0.0: resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==} hasBin: true @@ -4636,6 +4746,15 @@ packages: hachure-fill@0.5.2: resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} + har-schema@2.0.0: + resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} + engines: {node: '>=4'} + + har-validator@5.1.5: + resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} + engines: {node: '>=6'} + deprecated: this library is no longer supported + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -4648,6 +4767,9 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} + hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -4663,6 +4785,13 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html-to-text@9.0.5: + resolution: {integrity: sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==} + engines: {node: '>=14'} + + htmlencode@0.0.4: + resolution: {integrity: sha512-0uDvNVpzj/E2TfvLLyyXhKBRvF1y84aZsyRxRXFsQobnHaL4pcaXk+Y9cnFlvnxrBLeXDNq/VJBD+ngdBgQG1w==} + htmlparser2@8.0.2: resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} @@ -4674,6 +4803,10 @@ packages: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} + http-signature@1.2.0: + resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} + engines: {node: '>=0.8', npm: '>=1.3.7'} + https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} @@ -4683,6 +4816,10 @@ packages: engines: {node: '>=18'} hasBin: true + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -4790,6 +4927,9 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} @@ -4797,6 +4937,9 @@ packages: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} + is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} @@ -4811,6 +4954,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -4859,6 +5005,9 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true + jsbn@0.1.1: + resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} + jsdom@26.1.0: resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} engines: {node: '>=18'} @@ -4892,9 +5041,15 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -4906,6 +5061,10 @@ packages: jsonfile@6.2.0: resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + jsprim@1.4.2: + resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} + engines: {node: '>=0.6.0'} + katex@0.16.28: resolution: {integrity: sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg==} hasBin: true @@ -4942,6 +5101,9 @@ packages: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} engines: {node: '>= 0.6.3'} + leac@0.6.0: + resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -5020,6 +5182,10 @@ packages: loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + lowdb@1.0.0: + resolution: {integrity: sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==} + engines: {node: '>=4'} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -5089,6 +5255,10 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + matrix-bot-sdk@0.8.0: + resolution: {integrity: sha512-sCY5UvZfsZhJdCjSc8wZhGhIHOe5cSFSILxx9Zp5a/NEXtmQ6W/bIhefIk4zFAZXetFwXsgvKh1960k1hG5WDw==} + engines: {node: '>=22.0.0'} + media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -5101,6 +5271,9 @@ packages: resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} engines: {node: '>= 4.0.0'} + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + merge-descriptors@2.0.0: resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} engines: {node: '>=18'} @@ -5135,6 +5308,11 @@ packages: resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} engines: {node: '>=18'} + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + mime@2.6.0: resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} engines: {node: '>=4.0.0'} @@ -5156,6 +5334,9 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + minimatch@10.1.1: resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} engines: {node: 20 || >=22} @@ -5185,12 +5366,24 @@ packages: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + mlly@1.8.0: resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} module-details-from-path@1.0.4: resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} + morgan@1.10.1: + resolution: {integrity: sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==} + engines: {node: '>= 0.8.0'} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -5270,6 +5463,11 @@ packages: node-abort-controller@3.1.1: resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} + node-downloader-helper@2.1.10: + resolution: {integrity: sha512-8LdieUd4Bqw/CzfZLf30h+1xSAq3riWSDfWKsPJYz8EULoWxjS1vw6BGLYFZDxQgXjDR7UmC9UpQ0oV93U98Fg==} + engines: {node: '>=14.18'} + hasBin: true + node-emoji@1.11.0: resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} @@ -5304,6 +5502,9 @@ packages: engines: {node: '>=18'} hasBin: true + oauth-sign@0.9.0: + resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -5325,10 +5526,18 @@ packages: ollama@0.6.3: resolution: {integrity: sha512-KEWEhIqE5wtfzEIZbDCLH51VFZ6Z3ZSa6sIOg/E/tBV8S51flyqBOXi+bRxlOYKDf8i327zG9eSTb8IJxvm3Zg==} + on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} + on-headers@1.1.0: + resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==} + engines: {node: '>= 0.8'} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -5392,6 +5601,9 @@ packages: parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + parseley@0.12.1: + resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -5418,6 +5630,9 @@ packages: resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} engines: {node: 20 || >=22} + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + path-to-regexp@8.3.0: resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} @@ -5432,12 +5647,18 @@ packages: resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} engines: {node: '>= 14.16'} + peberminta@0.9.0: + resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} + perfect-debounce@1.0.0: resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} perfect-debounce@2.1.0: resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==} + performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + pg-cloudflare@1.3.0: resolution: {integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==} @@ -5492,6 +5713,10 @@ packages: engines: {node: '>=0.10'} hasBin: true + pify@3.0.0: + resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} + engines: {node: '>=4'} + pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -5532,6 +5757,10 @@ packages: resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} engines: {node: '>=0.10.0'} + postgres@3.4.8: + resolution: {integrity: sha512-d+JFcLM17njZaOLkv6SCev7uoLaBtfK86vMUXhW1Z4glPWh4jozno9APvW/XKFJ3CCxVoC7OL38BqRydtu5nGg==} + engines: {node: '>=12'} + prebuild-install@7.1.3: resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} engines: {node: '>=10'} @@ -5589,6 +5818,9 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + pump@3.0.3: resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} @@ -5603,6 +5835,10 @@ packages: resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} engines: {node: '>=0.6'} + qs@6.5.5: + resolution: {integrity: sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==} + engines: {node: '>=0.6'} + randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} @@ -5610,6 +5846,10 @@ packages: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} + raw-body@2.5.3: + resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} + engines: {node: '>= 0.8'} + raw-body@3.0.2: resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} engines: {node: '>= 0.10'} @@ -5702,6 +5942,24 @@ packages: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true + request-promise-core@1.1.4: + resolution: {integrity: sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==} + engines: {node: '>=0.10.0'} + peerDependencies: + request: ^2.34 + + request-promise@4.2.6: + resolution: {integrity: sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==} + engines: {node: '>=0.10.0'} + deprecated: request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142 + peerDependencies: + request: ^2.34 + + request@2.88.2: + resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} + engines: {node: '>= 6'} + deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -5808,6 +6066,9 @@ packages: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} engines: {node: '>=4'} + selderee@0.11.0: + resolution: {integrity: sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -5817,6 +6078,10 @@ packages: engines: {node: '>=10'} hasBin: true + send@0.19.2: + resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} + engines: {node: '>= 0.8.0'} + send@1.2.1: resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} engines: {node: '>= 18'} @@ -5824,6 +6089,10 @@ packages: serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + serve-static@1.16.3: + resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} + engines: {node: '>= 0.8.0'} + serve-static@2.2.1: resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} engines: {node: '>= 18'} @@ -5939,6 +6208,11 @@ packages: resolution: {integrity: sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==} engines: {node: '>=10.16.0'} + sshpk@1.18.0: + resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} + engines: {node: '>=0.10.0'} + hasBin: true + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -5952,6 +6226,13 @@ packages: std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + stealthy-require@1.1.1: + resolution: {integrity: sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==} + engines: {node: '>=0.10.0'} + + steno@0.4.4: + resolution: {integrity: sha512-EEHMVYHNXFHfGtgjNITnka0aHhiAlo93F7z2/Pwd+g0teG9CnM3JIINM7hVVB5/rhw9voufD7Wukwgtw2uqh6w==} + streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} @@ -6158,6 +6439,10 @@ packages: resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} engines: {node: '>=14.16'} + tough-cookie@2.5.0: + resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} + engines: {node: '>=0.8'} + tough-cookie@5.1.2: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} @@ -6337,6 +6622,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + uuid@10.0.0: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true @@ -6345,6 +6634,11 @@ packages: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true + uuid@3.4.0: + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true @@ -6360,6 +6654,10 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + verror@1.10.0: + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} + engines: {'0': node >=0.6.0} + vite-node@3.2.4: resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -7023,7 +7321,7 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} - '@better-auth/cli@1.4.17(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(magicast@0.3.5)(nanostores@1.1.0)(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': + '@better-auth/cli@1.4.17(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(magicast@0.3.5)(nanostores@1.1.0)(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@babel/core': 7.28.6 '@babel/preset-react': 7.28.5(@babel/core@7.28.6) @@ -7035,13 +7333,13 @@ snapshots: '@mrleebo/prisma-ast': 0.13.1 '@prisma/client': 5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)) '@types/pg': 8.16.0 - better-auth: 1.4.17(@prisma/client@5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(better-sqlite3@12.6.2)(drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + better-auth: 1.4.17(@prisma/client@5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(better-sqlite3@12.6.2)(drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) better-sqlite3: 12.6.2 c12: 3.3.3(magicast@0.3.5) chalk: 5.6.2 commander: 12.1.0 dotenv: 17.2.4 - drizzle-orm: 0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)) + drizzle-orm: 0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)) open: 10.2.0 pg: 8.17.2 prettier: 3.8.1 @@ -7728,6 +8026,13 @@ snapshots: '@lukeed/csprng@1.1.0': {} + '@matrix-org/matrix-sdk-crypto-nodejs@0.4.0': + dependencies: + https-proxy-agent: 7.0.6 + node-downloader-helper: 2.1.10 + transitivePeerDependencies: + - supports-color + '@mermaid-js/parser@0.6.3': dependencies: langium: 3.3.1 @@ -8990,6 +9295,11 @@ snapshots: '@sapphire/snowflake@3.5.3': {} + '@selderee/plugin-htmlparser2@0.11.0': + dependencies: + domhandler: 5.0.3 + selderee: 0.11.0 + '@socket.io/component-emitter@3.1.2': {} '@standard-schema/spec@1.1.0': {} @@ -9315,6 +9625,13 @@ snapshots: '@types/estree@1.0.8': {} + '@types/express-serve-static-core@4.19.8': + dependencies: + '@types/node': 22.19.7 + '@types/qs': 6.14.0 + '@types/range-parser': 1.2.7 + '@types/send': 1.2.1 + '@types/express-serve-static-core@5.1.1': dependencies: '@types/node': 22.19.7 @@ -9322,6 +9639,13 @@ snapshots: '@types/range-parser': 1.2.7 '@types/send': 1.2.1 + '@types/express@4.17.25': + dependencies: + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 4.19.8 + '@types/qs': 6.14.0 + '@types/serve-static': 1.15.10 + '@types/express@5.0.6': dependencies: '@types/body-parser': 1.19.6 @@ -9348,6 +9672,8 @@ snapshots: '@types/methods@1.1.4': {} + '@types/mime@1.3.5': {} + '@types/multer@2.0.0': dependencies: '@types/express': 5.0.6 @@ -9407,10 +9733,21 @@ snapshots: dependencies: htmlparser2: 8.0.2 + '@types/send@0.17.6': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 22.19.7 + '@types/send@1.2.1': dependencies: '@types/node': 22.19.7 + '@types/serve-static@1.15.10': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 22.19.7 + '@types/send': 0.17.6 + '@types/serve-static@2.2.0': dependencies: '@types/http-errors': 2.0.5 @@ -9850,6 +10187,8 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + another-json@0.2.0: {} + ansi-colors@4.1.3: {} ansi-escapes@7.2.0: @@ -9909,6 +10248,8 @@ snapshots: aria-query@5.3.2: {} + array-flatten@1.1.1: {} + array-timsort@1.0.3: {} asap@2.0.6: {} @@ -9917,6 +10258,8 @@ snapshots: dependencies: safer-buffer: 2.1.2 + assert-plus@1.0.0: {} + assertion-error@2.0.1: {} ast-v8-to-istanbul@0.3.10: @@ -9925,10 +10268,16 @@ snapshots: estree-walker: 3.0.3 js-tokens: 9.0.1 + async-lock@1.4.1: {} + async@3.2.6: {} asynckit@0.4.0: {} + aws-sign2@0.7.0: {} + + aws4@1.13.2: {} + axios@1.13.5: dependencies: follow-redirects: 1.15.11 @@ -9949,11 +10298,15 @@ snapshots: baseline-browser-mapping@2.9.19: {} + basic-auth@2.0.1: + dependencies: + safe-buffer: 5.1.2 + bcrypt-pbkdf@1.0.2: dependencies: tweetnacl: 0.14.5 - better-auth@1.4.17(@prisma/client@5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(better-sqlite3@12.6.2)(drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)): + better-auth@1.4.17(@prisma/client@5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(better-sqlite3@12.6.2)(drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)): dependencies: '@better-auth/core': 1.4.17(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0) '@better-auth/telemetry': 1.4.17(@better-auth/core@1.4.17(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)) @@ -9970,7 +10323,7 @@ snapshots: optionalDependencies: '@prisma/client': 5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)) better-sqlite3: 12.6.2 - drizzle-orm: 0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)) + drizzle-orm: 0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)) next: 16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) pg: 8.17.2 prisma: 6.19.2(magicast@0.3.5)(typescript@5.9.3) @@ -9978,7 +10331,7 @@ snapshots: react-dom: 19.2.4(react@19.2.4) vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) - better-auth@1.4.17(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.6.2)(drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)): + better-auth@1.4.17(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.6.2)(drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)): dependencies: '@better-auth/core': 1.4.17(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0) '@better-auth/telemetry': 1.4.17(@better-auth/core@1.4.17(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)) @@ -9995,7 +10348,7 @@ snapshots: optionalDependencies: '@prisma/client': 6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3) better-sqlite3: 12.6.2 - drizzle-orm: 0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)) + drizzle-orm: 0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)) next: 16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) pg: 8.17.2 prisma: 6.19.2(magicast@0.3.5)(typescript@5.9.3) @@ -10003,7 +10356,7 @@ snapshots: react-dom: 19.2.4(react@19.2.4) vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) - better-auth@1.4.17(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.6.2)(drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)): + better-auth@1.4.17(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(better-sqlite3@12.6.2)(drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)))(next@16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@3.2.4(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)): dependencies: '@better-auth/core': 1.4.17(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0) '@better-auth/telemetry': 1.4.17(@better-auth/core@1.4.17(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)) @@ -10020,7 +10373,7 @@ snapshots: optionalDependencies: '@prisma/client': 6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3) better-sqlite3: 12.6.2 - drizzle-orm: 0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)) + drizzle-orm: 0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)) next: 16.1.6(@babel/core@7.28.6)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) pg: 8.17.2 prisma: 6.19.2(magicast@0.3.5)(typescript@5.9.3) @@ -10054,6 +10407,25 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 + bluebird@3.7.2: {} + + body-parser@1.20.4: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.14.1 + raw-body: 2.5.3 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + body-parser@2.2.2: dependencies: bytes: 3.1.2 @@ -10178,6 +10550,8 @@ snapshots: caniuse-lite@1.0.30001766: {} + caseless@0.12.0: {} + chai@5.3.3: dependencies: assertion-error: 2.0.1 @@ -10344,6 +10718,10 @@ snapshots: consola@3.4.2: {} + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + content-disposition@1.0.1: {} content-type@1.0.5: {} @@ -10363,6 +10741,8 @@ snapshots: cookiejar@2.1.4: {} + core-util-is@1.0.2: {} + core-util-is@1.0.3: {} cors@2.8.5: @@ -10605,6 +10985,10 @@ snapshots: d3: 7.9.0 lodash-es: 4.17.23 + dashdash@1.14.1: + dependencies: + assert-plus: 1.0.0 + data-urls@5.0.0: dependencies: whatwg-mimetype: 4.0.0 @@ -10614,6 +10998,10 @@ snapshots: dayjs@1.11.19: {} + debug@2.6.9: + dependencies: + ms: 2.0.0 + debug@4.4.3: dependencies: ms: 2.1.3 @@ -10663,6 +11051,8 @@ snapshots: destr@2.0.5: {} + destroy@1.2.0: {} + detect-libc@2.1.2: {} dezalgo@1.0.4: @@ -10750,7 +11140,7 @@ snapshots: dotenv@17.2.4: {} - drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)): + drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(postgres@3.4.8)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)): optionalDependencies: '@opentelemetry/api': 1.9.0 '@prisma/client': 6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3) @@ -10758,6 +11148,7 @@ snapshots: better-sqlite3: 12.6.2 kysely: 0.28.10 pg: 8.17.2 + postgres: 3.4.8 prisma: 6.19.2(magicast@0.3.5)(typescript@5.9.3) dunder-proto@1.0.1: @@ -10768,6 +11159,11 @@ snapshots: eastasianwidth@0.2.0: {} + ecc-jsbn@0.1.2: + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + ee-first@1.1.1: {} effect@3.18.4: @@ -11011,6 +11407,42 @@ snapshots: expect-type@1.3.0: {} + express@4.22.1: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.4 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.2 + fresh: 0.5.2 + http-errors: 2.0.1 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: 2.0.7 + qs: 6.14.1 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.2 + serve-static: 1.16.3 + setprototypeof: 1.2.0 + statuses: 2.0.2 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + express@5.2.1: dependencies: accepts: 2.0.0 @@ -11052,6 +11484,8 @@ snapshots: extend@3.0.2: {} + extsprintf@1.3.0: {} + fast-check@3.23.2: dependencies: pure-rand: 6.1.0 @@ -11095,6 +11529,18 @@ snapshots: dependencies: to-regex-range: 5.0.1 + finalhandler@1.3.2: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + finalhandler@2.1.1: dependencies: debug: 4.4.3 @@ -11125,6 +11571,8 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + forever-agent@0.6.1: {} + fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.104.1(@swc/core@1.15.11)): dependencies: '@babel/code-frame': 7.29.0 @@ -11142,6 +11590,12 @@ snapshots: typescript: 5.9.3 webpack: 5.104.1(@swc/core@1.15.11) + form-data@2.3.3: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + form-data@4.0.5: dependencies: asynckit: 0.4.0 @@ -11160,6 +11614,8 @@ snapshots: forwarded@0.2.0: {} + fresh@0.5.2: {} + fresh@2.0.0: {} fs-constants@1.0.0: {} @@ -11225,6 +11681,10 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 + getpass@0.1.7: + dependencies: + assert-plus: 1.0.0 + giget@2.0.0: dependencies: citty: 0.1.6 @@ -11276,6 +11736,13 @@ snapshots: hachure-fill@0.5.2: {} + har-schema@2.0.0: {} + + har-validator@5.1.5: + dependencies: + ajv: 6.12.6 + har-schema: 2.0.0 + has-flag@4.0.0: {} has-symbols@1.1.0: {} @@ -11284,6 +11751,11 @@ snapshots: dependencies: has-symbols: 1.1.0 + hash.js@1.1.7: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -11296,6 +11768,16 @@ snapshots: html-escaper@2.0.2: {} + html-to-text@9.0.5: + dependencies: + '@selderee/plugin-htmlparser2': 0.11.0 + deepmerge: 4.3.1 + dom-serializer: 2.0.0 + htmlparser2: 8.0.2 + selderee: 0.11.0 + + htmlencode@0.0.4: {} + htmlparser2@8.0.2: dependencies: domelementtype: 2.3.0 @@ -11318,6 +11800,12 @@ snapshots: transitivePeerDependencies: - supports-color + http-signature@1.2.0: + dependencies: + assert-plus: 1.0.0 + jsprim: 1.4.2 + sshpk: 1.18.0 + https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.4 @@ -11327,6 +11815,10 @@ snapshots: husky@9.1.7: {} + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -11415,10 +11907,14 @@ snapshots: is-potential-custom-element-name@1.0.1: {} + is-promise@2.2.2: {} + is-promise@4.0.0: {} is-stream@2.0.1: {} + is-typedarray@1.0.0: {} + is-unicode-supported@0.1.0: {} is-wsl@3.1.0: @@ -11429,6 +11925,8 @@ snapshots: isexe@2.0.0: {} + isstream@0.1.2: {} + istanbul-lib-coverage@3.2.2: {} istanbul-lib-report@3.0.1: @@ -11481,6 +11979,8 @@ snapshots: dependencies: argparse: 2.0.1 + jsbn@0.1.1: {} + jsdom@26.1.0: dependencies: cssstyle: 4.6.0 @@ -11527,8 +12027,12 @@ snapshots: json-schema-traverse@1.0.0: {} + json-schema@0.4.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} + json-stringify-safe@5.0.1: {} + json5@2.2.3: {} jsonc-parser@3.3.1: {} @@ -11539,6 +12043,13 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jsprim@1.4.2: + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + katex@0.16.28: dependencies: commander: 8.3.0 @@ -11571,6 +12082,8 @@ snapshots: dependencies: readable-stream: 2.3.8 + leac@0.6.0: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -11646,6 +12159,14 @@ snapshots: loupe@3.2.1: {} + lowdb@1.0.0: + dependencies: + graceful-fs: 4.2.11 + is-promise: 2.2.2 + lodash: 4.17.23 + pify: 3.0.0 + steno: 0.4.4 + lru-cache@10.4.3: {} lru-cache@11.2.5: {} @@ -11705,6 +12226,29 @@ snapshots: math-intrinsics@1.1.0: {} + matrix-bot-sdk@0.8.0: + dependencies: + '@matrix-org/matrix-sdk-crypto-nodejs': 0.4.0 + '@types/express': 4.17.25 + another-json: 0.2.0 + async-lock: 1.4.1 + chalk: 4.1.2 + express: 4.22.1 + glob-to-regexp: 0.4.1 + hash.js: 1.1.7 + html-to-text: 9.0.5 + htmlencode: 0.0.4 + lowdb: 1.0.0 + lru-cache: 10.4.3 + mkdirp: 3.0.1 + morgan: 1.10.1 + postgres: 3.4.8 + request: 2.88.2 + request-promise: 4.2.6(request@2.88.2) + sanitize-html: 2.17.0 + transitivePeerDependencies: + - supports-color + media-typer@0.3.0: {} media-typer@1.1.0: {} @@ -11713,6 +12257,8 @@ snapshots: dependencies: fs-monkey: 1.1.0 + merge-descriptors@1.0.3: {} + merge-descriptors@2.0.0: {} merge-stream@2.0.0: {} @@ -11759,6 +12305,8 @@ snapshots: dependencies: mime-db: 1.54.0 + mime@1.6.0: {} + mime@2.6.0: {} mimic-fn@2.1.0: {} @@ -11769,6 +12317,8 @@ snapshots: min-indent@1.0.1: {} + minimalistic-assert@1.0.1: {} + minimatch@10.1.1: dependencies: '@isaacs/brace-expansion': 5.0.1 @@ -11795,6 +12345,8 @@ snapshots: dependencies: minimist: 1.2.8 + mkdirp@3.0.1: {} + mlly@1.8.0: dependencies: acorn: 8.15.0 @@ -11804,6 +12356,18 @@ snapshots: module-details-from-path@1.0.4: {} + morgan@1.10.1: + dependencies: + basic-auth: 2.0.1 + debug: 2.6.9 + depd: 2.0.0 + on-finished: 2.3.0 + on-headers: 1.1.0 + transitivePeerDependencies: + - supports-color + + ms@2.0.0: {} + ms@2.1.3: {} msgpackr-extract@3.0.3: @@ -11884,6 +12448,8 @@ snapshots: node-abort-controller@3.1.1: {} + node-downloader-helper@2.1.10: {} + node-emoji@1.11.0: dependencies: lodash: 4.17.23 @@ -11911,6 +12477,8 @@ snapshots: pathe: 2.0.3 tinyexec: 1.0.2 + oauth-sign@0.9.0: {} + object-assign@4.1.1: {} object-hash@3.0.0: {} @@ -11925,10 +12493,16 @@ snapshots: dependencies: whatwg-fetch: 3.6.20 + on-finished@2.3.0: + dependencies: + ee-first: 1.1.1 + on-finished@2.4.1: dependencies: ee-first: 1.1.1 + on-headers@1.1.0: {} + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -12003,6 +12577,11 @@ snapshots: dependencies: entities: 6.0.1 + parseley@0.12.1: + dependencies: + leac: 0.6.0 + peberminta: 0.9.0 + parseurl@1.3.3: {} path-data-parser@0.1.0: {} @@ -12023,6 +12602,8 @@ snapshots: lru-cache: 11.2.5 minipass: 7.1.2 + path-to-regexp@0.1.12: {} + path-to-regexp@8.3.0: {} path-type@4.0.0: {} @@ -12031,10 +12612,14 @@ snapshots: pathval@2.0.1: {} + peberminta@0.9.0: {} + perfect-debounce@1.0.0: {} perfect-debounce@2.1.0: {} + performance-now@2.1.0: {} + pg-cloudflare@1.3.0: optional: true @@ -12080,6 +12665,8 @@ snapshots: pidtree@0.6.0: {} + pify@3.0.0: {} + pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -12123,6 +12710,8 @@ snapshots: dependencies: xtend: 4.0.2 + postgres@3.4.8: {} + prebuild-install@7.1.3: dependencies: detect-libc: 2.1.2 @@ -12198,6 +12787,10 @@ snapshots: proxy-from-env@1.1.0: {} + psl@1.15.0: + dependencies: + punycode: 2.3.1 + pump@3.0.3: dependencies: end-of-stream: 1.4.5 @@ -12211,12 +12804,21 @@ snapshots: dependencies: side-channel: 1.1.0 + qs@6.5.5: {} + randombytes@2.1.0: dependencies: safe-buffer: 5.2.1 range-parser@1.2.1: {} + raw-body@2.5.3: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + raw-body@3.0.2: dependencies: bytes: 3.1.2 @@ -12323,6 +12925,42 @@ snapshots: regexp-tree@0.1.27: {} + request-promise-core@1.1.4(request@2.88.2): + dependencies: + lodash: 4.17.23 + request: 2.88.2 + + request-promise@4.2.6(request@2.88.2): + dependencies: + bluebird: 3.7.2 + request: 2.88.2 + request-promise-core: 1.1.4(request@2.88.2) + stealthy-require: 1.1.1 + tough-cookie: 2.5.0 + + request@2.88.2: + dependencies: + aws-sign2: 0.7.0 + aws4: 1.13.2 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 2.3.3 + har-validator: 5.1.5 + http-signature: 1.2.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.35 + oauth-sign: 0.9.0 + performance-now: 2.1.0 + qs: 6.5.5 + safe-buffer: 5.2.1 + tough-cookie: 2.5.0 + tunnel-agent: 0.6.0 + uuid: 3.4.0 + require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -12468,10 +13106,32 @@ snapshots: extend-shallow: 2.0.1 kind-of: 6.0.3 + selderee@0.11.0: + dependencies: + parseley: 0.12.1 + semver@6.3.1: {} semver@7.7.3: {} + send@0.19.2: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + send@1.2.1: dependencies: debug: 4.4.3 @@ -12492,6 +13152,15 @@ snapshots: dependencies: randombytes: 2.1.0 + serve-static@1.16.3: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.2 + transitivePeerDependencies: + - supports-color + serve-static@2.2.1: dependencies: encodeurl: 2.0.0 @@ -12670,6 +13339,18 @@ snapshots: cpu-features: 0.0.10 nan: 2.25.0 + sshpk@1.18.0: + dependencies: + asn1: 0.2.6 + assert-plus: 1.0.0 + bcrypt-pbkdf: 1.0.2 + dashdash: 1.14.1 + ecc-jsbn: 0.1.2 + getpass: 0.1.7 + jsbn: 0.1.1 + safer-buffer: 2.1.2 + tweetnacl: 0.14.5 + stackback@0.0.2: {} standard-as-callback@2.1.0: {} @@ -12678,6 +13359,12 @@ snapshots: std-env@3.10.0: {} + stealthy-require@1.1.1: {} + + steno@0.4.4: + dependencies: + graceful-fs: 4.2.11 + streamsearch@1.1.0: {} streamx@2.23.0: @@ -12892,6 +13579,11 @@ snapshots: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 + tough-cookie@2.5.0: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + tough-cookie@5.1.2: dependencies: tldts: 6.1.86 @@ -13067,10 +13759,14 @@ snapshots: util-deprecate@1.0.2: {} + utils-merge@1.0.1: {} + uuid@10.0.0: {} uuid@11.1.0: {} + uuid@3.4.0: {} + uuid@9.0.1: {} v8-compile-cache-lib@3.0.1: {} @@ -13079,6 +13775,12 @@ snapshots: vary@1.1.2: {} + verror@1.10.0: + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + vite-node@3.2.4(@types/node@22.19.7)(jiti@2.6.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2): dependencies: cac: 6.7.14