diff --git a/docs/MATRIX_BOT_ARCHITECTURE.md b/docs/MATRIX_BOT_ARCHITECTURE.md index 1cb12c0ee..f0327fd0e 100644 --- a/docs/MATRIX_BOT_ARCHITECTURE.md +++ b/docs/MATRIX_BOT_ARCHITECTURE.md @@ -181,12 +181,16 @@ User → matrix-mana-bot → @manacore/bot-services → Multiple Backends Das Package `@manacore/bot-services` stellt transport-agnostische Geschäftslogik bereit: ```typescript -// Exportierte Services +// Business Logic Services export { TodoModule, TodoService } from './todo'; export { CalendarModule, CalendarService } from './calendar'; export { AiModule, AiService } from './ai'; export { ClockModule, ClockService } from './clock'; +// Infrastructure Services (NEU: Konsolidiert aus 11+ Bots) +export { SessionModule, SessionService } from './session'; // Auth via mana-core-auth +export { TranscriptionModule, TranscriptionService } from './transcription'; // STT via mana-stt + // Storage Provider (pluggable) export { FileStorageProvider } from './shared/storage/file-storage.provider'; export { MemoryStorageProvider } from './shared/storage/memory-storage.provider'; @@ -196,6 +200,15 @@ export { generateId, getTodayISO, formatDateDE } from './shared/utils'; export { parseGermanDateKeyword } from './shared/date-parser'; ``` +### 3.1.1 Konsolidierte Services + +Die folgenden Services wurden aus den einzelnen Bots konsolidiert: + +| Service | Vorher | Nachher | Bots | +|---------|--------|---------|------| +| `SessionService` | 11x dupliziert | 1x in bot-services | picture, contacts, chat, zitare, ... | +| `TranscriptionService` | 6x dupliziert | 1x in bot-services | todo, clock, zitare, nutriphi, ... | + ### 3.2 TodoService Vollständige Aufgabenverwaltung mit deutscher Sprachunterstützung: diff --git a/packages/bot-services/CLAUDE.md b/packages/bot-services/CLAUDE.md index 365ae6a3b..6ac473294 100644 --- a/packages/bot-services/CLAUDE.md +++ b/packages/bot-services/CLAUDE.md @@ -35,16 +35,30 @@ This package provides **transport-agnostic** services that contain all business ## Available Services +### Business Logic Services + | Service | Storage | Description | |---------|---------|-------------| | `TodoService` | File (JSON) | Task management with projects, priorities, dates | | `CalendarService` | File (JSON) | Events, calendars, reminders | | `AiService` | In-memory | Ollama LLM integration, chat sessions, vision | | `ClockService` | External API | Timers, alarms, world clocks | -| `NutritionService` | Placeholder | Meal tracking (to be implemented) | -| `QuotesService` | Placeholder | Daily quotes (to be implemented) | -| `StatsService` | Placeholder | Analytics reports (to be implemented) | -| `DocsService` | Placeholder | Documentation generation (to be implemented) | + +### Infrastructure Services + +| Service | Storage | Description | +|---------|---------|-------------| +| `SessionService` | In-memory | User authentication via mana-core-auth | +| `TranscriptionService` | External API | Speech-to-text via mana-stt service | + +### Placeholder Services (to be implemented) + +| Service | Description | +|---------|-------------| +| `NutritionService` | Meal tracking | +| `QuotesService` | Daily quotes | +| `StatsService` | Analytics reports | +| `DocsService` | Documentation generation | ## Usage @@ -52,7 +66,14 @@ This package provides **transport-agnostic** services that contain all business ```typescript import { Module } from '@nestjs/common'; -import { TodoModule, CalendarModule, AiModule, ClockModule } from '@manacore/bot-services'; +import { + TodoModule, + CalendarModule, + AiModule, + ClockModule, + SessionModule, + TranscriptionModule, +} from '@manacore/bot-services'; @Module({ imports: [ @@ -63,11 +84,59 @@ import { TodoModule, CalendarModule, AiModule, ClockModule } from '@manacore/bot // External services AiModule.register({ baseUrl: 'http://ollama:11434' }), ClockModule.register({ apiUrl: 'http://clock-backend:3017/api/v1' }), + + // Infrastructure services (use ConfigService by default) + SessionModule.forRoot(), + TranscriptionModule.forRoot(), ], }) export class AppModule {} ``` +### Session Service (Authentication) + +```typescript +import { SessionService } from '@manacore/bot-services'; + +// Login a Matrix user +const result = await sessionService.login( + '@user:matrix.org', + 'email@example.com', + 'password' +); + +if (result.success) { + // Get token for API calls + const token = sessionService.getToken('@user:matrix.org'); + + // Check if logged in + const isLoggedIn = sessionService.isLoggedIn('@user:matrix.org'); +} + +// Logout +sessionService.logout('@user:matrix.org'); + +// Store custom session data +sessionService.setSessionData('@user:matrix.org', 'currentConversationId', 'abc123'); +const convId = sessionService.getSessionData('@user:matrix.org', 'currentConversationId'); +``` + +### Transcription Service (Speech-to-Text) + +```typescript +import { TranscriptionService } from '@manacore/bot-services'; + +// Transcribe audio buffer +const text = await transcriptionService.transcribe(audioBuffer, { language: 'de' }); + +// Get full response with metadata +const result = await transcriptionService.transcribeWithMetadata(audioBuffer); +console.log(result.text, result.language, result.model); + +// Health check +const isHealthy = await transcriptionService.checkHealth(); +``` + ### Direct Service Usage ```typescript @@ -162,15 +231,86 @@ packages/bot-services/ │ │ ├── utils.ts # Utility functions │ │ └── index.ts │ ├── todo/ -│ │ ├── types.ts -│ │ ├── todo.service.ts -│ │ ├── todo.module.ts -│ │ └── index.ts │ ├── calendar/ │ ├── ai/ │ ├── clock/ +│ ├── session/ # NEW: User authentication +│ │ ├── types.ts +│ │ ├── session.service.ts +│ │ ├── session.module.ts +│ │ └── index.ts +│ ├── transcription/ # NEW: Speech-to-text +│ │ ├── types.ts +│ │ ├── transcription.service.ts +│ │ ├── transcription.module.ts +│ │ └── index.ts │ └── ... ├── package.json ├── tsconfig.json └── CLAUDE.md ``` + +## Migrating Bots to Shared Services + +To migrate a bot from local services to shared services: + +### 1. Add dependency + +```bash +# In package.json +"dependencies": { + "@manacore/bot-services": "workspace:*", + ... +} +``` + +### 2. Update module imports + +```typescript +// bot.module.ts - BEFORE +import { SessionModule } from '../session/session.module'; +import { TranscriptionModule } from '../transcription/transcription.module'; + +@Module({ + imports: [SessionModule, TranscriptionModule], +}) + +// bot.module.ts - AFTER +import { SessionModule, TranscriptionModule } from '@manacore/bot-services'; + +@Module({ + imports: [SessionModule.forRoot(), TranscriptionModule.forRoot()], +}) +``` + +### 3. Update service imports + +```typescript +// matrix.service.ts - BEFORE +import { SessionService } from '../session/session.service'; +import { TranscriptionService } from '../transcription/transcription.service'; + +// matrix.service.ts - AFTER +import { SessionService, TranscriptionService } from '@manacore/bot-services'; +``` + +### 4. Delete local modules + +```bash +rm -rf src/session/ +rm -rf src/transcription/ +``` + +### Migrated Bots + +| Bot | SessionService | TranscriptionService | +|-----|----------------|---------------------| +| matrix-todo-bot | - | ✅ | +| matrix-picture-bot | ✅ | - | +| matrix-clock-bot | - | ✅ | +| matrix-zitare-bot | ✅ | ✅ | +| matrix-chat-bot | TODO | - | +| matrix-contacts-bot | TODO | - | +| matrix-nutriphi-bot | TODO | TODO | +| matrix-project-doc-bot | - | TODO | +| ... | ... | ... | diff --git a/packages/bot-services/package.json b/packages/bot-services/package.json index 018dc0407..0c138462f 100644 --- a/packages/bot-services/package.json +++ b/packages/bot-services/package.json @@ -11,6 +11,8 @@ "./calendar": "./src/calendar/index.ts", "./clock": "./src/clock/index.ts", "./ai": "./src/ai/index.ts", + "./session": "./src/session/index.ts", + "./transcription": "./src/transcription/index.ts", "./nutrition": "./src/nutrition/index.ts", "./quotes": "./src/quotes/index.ts", "./stats": "./src/stats/index.ts", diff --git a/packages/bot-services/src/index.ts b/packages/bot-services/src/index.ts index cbe209317..cf7fda0f3 100644 --- a/packages/bot-services/src/index.ts +++ b/packages/bot-services/src/index.ts @@ -40,7 +40,12 @@ export type { } from './todo'; // Calendar -export { CalendarModule, CalendarModuleOptions, CalendarService, CALENDAR_STORAGE_PROVIDER } from './calendar'; +export { + CalendarModule, + CalendarModuleOptions, + CalendarService, + CALENDAR_STORAGE_PROVIDER, +} from './calendar'; export type { CalendarEvent, Calendar, @@ -79,6 +84,23 @@ export type { TimeTrackingSummary, } from './clock'; +// Session (User authentication via mana-core-auth) +export { + SessionModule, + SessionService, + SESSION_MODULE_OPTIONS, + DEFAULT_SESSION_EXPIRY_MS, +} from './session'; +export type { UserSession, LoginResult, SessionStats, SessionModuleOptions } from './session'; + +// Transcription (Speech-to-Text via mana-stt) +export { TranscriptionModule, TranscriptionService, STT_MODULE_OPTIONS } from './transcription'; +export type { + SttResponse, + TranscriptionOptions, + TranscriptionModuleOptions, +} from './transcription'; + // ===== Placeholder Services (to be implemented) ===== export { NutritionModule } from './nutrition'; @@ -96,7 +118,18 @@ export type { DocsServiceConfig, ProjectDoc } from './docs'; // ===== Shared Utilities ===== export { FileStorageProvider, MemoryStorageProvider } from './shared'; -export type { StorageProvider, BaseEntity, UserEntity, ServiceConfig, Result, PaginationOptions, PaginatedResult, DateRange, Priority, ServiceStats } from './shared'; +export type { + StorageProvider, + BaseEntity, + UserEntity, + ServiceConfig, + Result, + PaginationOptions, + PaginatedResult, + DateRange, + Priority, + ServiceStats, +} from './shared'; export { generateId, getTodayISO, diff --git a/packages/bot-services/src/session/index.ts b/packages/bot-services/src/session/index.ts new file mode 100644 index 000000000..c3203d6d5 --- /dev/null +++ b/packages/bot-services/src/session/index.ts @@ -0,0 +1,4 @@ +export { SessionService } from './session.service'; +export { SessionModule } from './session.module'; +export type { UserSession, LoginResult, SessionStats, SessionModuleOptions } from './types'; +export { SESSION_MODULE_OPTIONS, DEFAULT_SESSION_EXPIRY_MS } from './types'; diff --git a/packages/bot-services/src/session/session.module.ts b/packages/bot-services/src/session/session.module.ts new file mode 100644 index 000000000..dd06bab35 --- /dev/null +++ b/packages/bot-services/src/session/session.module.ts @@ -0,0 +1,62 @@ +import { Module, DynamicModule, Global } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { SessionService } from './session.service'; +import { SessionModuleOptions, SESSION_MODULE_OPTIONS } from './types'; + +/** + * Shared session management module for Matrix bots + * + * Provides SessionService for managing user authentication sessions. + * Links Matrix user IDs to mana-core-auth JWT tokens. + * + * @example + * ```typescript + * // With explicit configuration + * @Module({ + * imports: [ + * SessionModule.register({ + * authUrl: 'http://mana-core-auth:3001', + * sessionExpiryMs: 7 * 24 * 60 * 60 * 1000 // 7 days + * }) + * ] + * }) + * + * // With ConfigService (reads from auth.url or MANA_CORE_AUTH_URL) + * @Module({ + * imports: [SessionModule.forRoot()] + * }) + * ``` + */ +@Global() +@Module({}) +export class SessionModule { + /** + * Register module with explicit options + */ + static register(options: SessionModuleOptions = {}): DynamicModule { + return { + module: SessionModule, + imports: [ConfigModule], + providers: [ + { + provide: SESSION_MODULE_OPTIONS, + useValue: options, + }, + SessionService, + ], + exports: [SessionService], + }; + } + + /** + * Register module with ConfigService (reads auth.url or MANA_CORE_AUTH_URL from config) + */ + static forRoot(): DynamicModule { + return { + module: SessionModule, + imports: [ConfigModule], + providers: [SessionService], + exports: [SessionService], + }; + } +} diff --git a/packages/bot-services/src/session/session.service.ts b/packages/bot-services/src/session/session.service.ts new file mode 100644 index 000000000..86a83c38c --- /dev/null +++ b/packages/bot-services/src/session/session.service.ts @@ -0,0 +1,235 @@ +import { Injectable, Inject, Logger, Optional } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { + UserSession, + LoginResult, + SessionStats, + SessionModuleOptions, + SESSION_MODULE_OPTIONS, + DEFAULT_SESSION_EXPIRY_MS, +} from './types'; + +/** + * Shared session management service for Matrix bots + * + * Manages user authentication sessions linking Matrix user IDs to mana-core-auth JWT tokens. + * Sessions are stored in-memory and automatically expire. + * + * @example + * ```typescript + * // In NestJS module + * imports: [SessionModule.register({ authUrl: 'http://mana-core-auth:3001' })] + * + * // In service/controller + * const result = await sessionService.login(matrixUserId, email, password); + * const token = sessionService.getToken(matrixUserId); + * ``` + */ +@Injectable() +export class SessionService { + private readonly logger = new Logger(SessionService.name); + private sessions: Map = new Map(); + private readonly authUrl: string; + private readonly sessionExpiryMs: number; + private readonly loginPath: string; + + constructor( + @Optional() private configService: ConfigService, + @Optional() @Inject(SESSION_MODULE_OPTIONS) private options?: SessionModuleOptions + ) { + // Priority: module options > config > environment > default + this.authUrl = + options?.authUrl || + this.configService?.get('auth.url') || + this.configService?.get('MANA_CORE_AUTH_URL') || + 'http://localhost:3001'; + + this.sessionExpiryMs = options?.sessionExpiryMs || DEFAULT_SESSION_EXPIRY_MS; + this.loginPath = options?.loginPath || '/api/v1/auth/login'; + + this.logger.log(`Auth URL: ${this.authUrl}`); + } + + /** + * Login a Matrix user with mana-core-auth credentials + * + * @param matrixUserId - Matrix user ID (e.g., "@user:matrix.mana.how") + * @param email - User's email + * @param password - User's password + * @returns Login result with success status + */ + async login(matrixUserId: string, email: string, password: string): Promise { + try { + const response = await fetch(`${this.authUrl}${this.loginPath}`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email, password }), + }); + + if (!response.ok) { + const errorData = (await response.json().catch(() => ({}))) as { message?: string }; + return { + success: false, + error: errorData.message || 'Authentifizierung fehlgeschlagen', + }; + } + + const data = (await response.json()) as { accessToken?: string; token?: string }; + const token = data.accessToken || data.token; + + if (!token) { + return { success: false, error: 'Kein Token erhalten' }; + } + + // Store session with expiry + this.sessions.set(matrixUserId, { + token, + email, + expiresAt: new Date(Date.now() + this.sessionExpiryMs), + }); + + this.logger.log(`User ${matrixUserId} logged in as ${email}`); + return { success: true, email }; + } catch (error) { + this.logger.error(`Login failed for ${matrixUserId}:`, error); + return { + success: false, + error: 'Verbindung zum Auth-Server fehlgeschlagen', + }; + } + } + + /** + * Logout a Matrix user + */ + logout(matrixUserId: string): void { + this.sessions.delete(matrixUserId); + this.logger.log(`User ${matrixUserId} logged out`); + } + + /** + * Get JWT token for a Matrix user (null if not logged in or expired) + */ + getToken(matrixUserId: string): string | null { + const session = this.sessions.get(matrixUserId); + + if (!session) return null; + + // Check if token expired + if (session.expiresAt < new Date()) { + this.sessions.delete(matrixUserId); + return null; + } + + return session.token; + } + + /** + * Check if a Matrix user is logged in + */ + isLoggedIn(matrixUserId: string): boolean { + return this.getToken(matrixUserId) !== null; + } + + /** + * Get the full session object for a Matrix user + */ + getSession(matrixUserId: string): UserSession | null { + const token = this.getToken(matrixUserId); // This handles expiry check + if (!token) return null; + return this.sessions.get(matrixUserId) || null; + } + + /** + * Get email for a logged-in Matrix user + */ + getEmail(matrixUserId: string): string | null { + const session = this.getSession(matrixUserId); + return session?.email || null; + } + + /** + * Store custom data in a user's session + */ + setSessionData(matrixUserId: string, key: string, value: unknown): void { + const session = this.sessions.get(matrixUserId); + if (session) { + session.data = session.data || {}; + session.data[key] = value; + } + } + + /** + * Get custom data from a user's session + */ + getSessionData(matrixUserId: string, key: string): T | null { + const session = this.getSession(matrixUserId); + return (session?.data?.[key] as T) || null; + } + + /** + * Get total session count (including expired) + */ + getSessionCount(): number { + return this.sessions.size; + } + + /** + * Get count of active (non-expired) sessions + */ + getActiveSessionCount(): number { + const now = new Date(); + let count = 0; + for (const session of this.sessions.values()) { + if (session.expiresAt > now) count++; + } + return count; + } + + /** + * Get session statistics + */ + getStats(): SessionStats { + return { + total: this.getSessionCount(), + active: this.getActiveSessionCount(), + }; + } + + /** + * Clean up expired sessions (can be called periodically) + */ + cleanupExpiredSessions(): number { + const now = new Date(); + let cleaned = 0; + + for (const [userId, session] of this.sessions.entries()) { + if (session.expiresAt < now) { + this.sessions.delete(userId); + cleaned++; + } + } + + if (cleaned > 0) { + this.logger.log(`Cleaned up ${cleaned} expired sessions`); + } + + return cleaned; + } + + /** + * Get all active session user IDs + */ + getActiveUserIds(): string[] { + const now = new Date(); + const userIds: string[] = []; + + for (const [userId, session] of this.sessions.entries()) { + if (session.expiresAt > now) { + userIds.push(userId); + } + } + + return userIds; + } +} diff --git a/packages/bot-services/src/session/types.ts b/packages/bot-services/src/session/types.ts new file mode 100644 index 000000000..2b664c997 --- /dev/null +++ b/packages/bot-services/src/session/types.ts @@ -0,0 +1,55 @@ +/** + * Types for Matrix user session management + */ + +/** + * User session data stored per Matrix user + */ +export interface UserSession { + /** JWT token from mana-core-auth */ + token: string; + /** User's email address */ + email: string; + /** Token expiration time */ + expiresAt: Date; + /** Additional session data (bot-specific) */ + data?: Record; +} + +/** + * Login result + */ +export interface LoginResult { + success: boolean; + error?: string; + email?: string; +} + +/** + * Session statistics + */ +export interface SessionStats { + /** Total sessions (including expired) */ + total: number; + /** Active (non-expired) sessions */ + active: number; +} + +/** + * Session module configuration options + */ +export interface SessionModuleOptions { + /** Mana Core Auth URL */ + authUrl?: string; + /** Session expiry in milliseconds (default: 7 days) */ + sessionExpiryMs?: number; + /** Custom login endpoint path */ + loginPath?: string; +} + +export const SESSION_MODULE_OPTIONS = 'SESSION_MODULE_OPTIONS'; + +/** + * Default session expiry: 7 days in milliseconds + */ +export const DEFAULT_SESSION_EXPIRY_MS = 7 * 24 * 60 * 60 * 1000; diff --git a/packages/bot-services/src/transcription/index.ts b/packages/bot-services/src/transcription/index.ts new file mode 100644 index 000000000..26f9080c9 --- /dev/null +++ b/packages/bot-services/src/transcription/index.ts @@ -0,0 +1,4 @@ +export { TranscriptionService } from './transcription.service'; +export { TranscriptionModule } from './transcription.module'; +export type { SttResponse, TranscriptionOptions, TranscriptionModuleOptions } from './types'; +export { STT_MODULE_OPTIONS } from './types'; diff --git a/packages/bot-services/src/transcription/transcription.module.ts b/packages/bot-services/src/transcription/transcription.module.ts new file mode 100644 index 000000000..2f0a2ef91 --- /dev/null +++ b/packages/bot-services/src/transcription/transcription.module.ts @@ -0,0 +1,61 @@ +import { Module, DynamicModule, Global } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import { TranscriptionService } from './transcription.service'; +import { TranscriptionModuleOptions, STT_MODULE_OPTIONS } from './types'; + +/** + * Shared Speech-to-Text transcription module + * + * Provides TranscriptionService for voice command processing in Matrix bots. + * + * @example + * ```typescript + * // With explicit configuration + * @Module({ + * imports: [ + * TranscriptionModule.register({ + * sttUrl: 'http://mana-stt:3020', + * defaultLanguage: 'de' + * }) + * ] + * }) + * + * // With ConfigService (reads from stt.url or STT_URL) + * @Module({ + * imports: [TranscriptionModule.forRoot()] + * }) + * ``` + */ +@Global() +@Module({}) +export class TranscriptionModule { + /** + * Register module with explicit options + */ + static register(options: TranscriptionModuleOptions = {}): DynamicModule { + return { + module: TranscriptionModule, + imports: [ConfigModule], + providers: [ + { + provide: STT_MODULE_OPTIONS, + useValue: options, + }, + TranscriptionService, + ], + exports: [TranscriptionService], + }; + } + + /** + * Register module with ConfigService (reads stt.url or STT_URL from config) + */ + static forRoot(): DynamicModule { + return { + module: TranscriptionModule, + imports: [ConfigModule], + providers: [TranscriptionService], + exports: [TranscriptionService], + }; + } +} diff --git a/packages/bot-services/src/transcription/transcription.service.ts b/packages/bot-services/src/transcription/transcription.service.ts new file mode 100644 index 000000000..6db7237b9 --- /dev/null +++ b/packages/bot-services/src/transcription/transcription.service.ts @@ -0,0 +1,140 @@ +import { Injectable, Inject, Logger, Optional } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { + SttResponse, + TranscriptionOptions, + STT_MODULE_OPTIONS, + TranscriptionModuleOptions, +} from './types'; + +/** + * Shared Speech-to-Text transcription service + * + * Connects to mana-stt service to transcribe audio files. + * Used by Matrix bots for voice command processing. + * + * @example + * ```typescript + * // In NestJS module + * imports: [TranscriptionModule.register({ sttUrl: 'http://mana-stt:3020' })] + * + * // In service + * const text = await transcriptionService.transcribe(audioBuffer, { language: 'de' }); + * ``` + */ +@Injectable() +export class TranscriptionService { + private readonly logger = new Logger(TranscriptionService.name); + private readonly sttUrl: string; + private readonly defaultLanguage: string; + + constructor( + @Optional() private configService: ConfigService, + @Optional() @Inject(STT_MODULE_OPTIONS) private options?: TranscriptionModuleOptions + ) { + // Priority: module options > config > environment > default + this.sttUrl = + options?.sttUrl || + this.configService?.get('stt.url') || + this.configService?.get('STT_URL') || + 'http://localhost:3020'; + + this.defaultLanguage = options?.defaultLanguage || 'de'; + + this.logger.log(`STT Service URL: ${this.sttUrl}`); + } + + /** + * Transcribe audio buffer to text + * + * @param audioBuffer - Audio data (supports ogg, wav, mp3, etc.) + * @param options - Transcription options (language, model) + * @returns Transcribed text + */ + async transcribe(audioBuffer: Buffer, options?: TranscriptionOptions): Promise { + const language = options?.language || this.defaultLanguage; + + const formData = new FormData(); + const blob = new Blob([new Uint8Array(audioBuffer)], { type: 'audio/ogg' }); + formData.append('file', blob, 'audio.ogg'); + formData.append('language', language); + + if (options?.model) { + formData.append('model', options.model); + } + + try { + const response = await fetch(`${this.sttUrl}/transcribe`, { + method: 'POST', + body: formData, + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`STT service error: ${response.status} - ${errorText}`); + } + + const result = (await response.json()) as SttResponse; + this.logger.log(`Transcription completed: ${result.text.substring(0, 50)}...`); + return result.text; + } catch (error) { + this.logger.error('Transcription failed:', error); + throw error; + } + } + + /** + * Transcribe audio and return full response with metadata + */ + async transcribeWithMetadata( + audioBuffer: Buffer, + options?: TranscriptionOptions + ): Promise { + const language = options?.language || this.defaultLanguage; + + const formData = new FormData(); + const blob = new Blob([new Uint8Array(audioBuffer)], { type: 'audio/ogg' }); + formData.append('file', blob, 'audio.ogg'); + formData.append('language', language); + + if (options?.model) { + formData.append('model', options.model); + } + + try { + const response = await fetch(`${this.sttUrl}/transcribe`, { + method: 'POST', + body: formData, + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(`STT service error: ${response.status} - ${errorText}`); + } + + return (await response.json()) as SttResponse; + } catch (error) { + this.logger.error('Transcription failed:', error); + throw error; + } + } + + /** + * Check if STT service is healthy + */ + async checkHealth(): Promise { + try { + const response = await fetch(`${this.sttUrl}/health`); + return response.ok; + } catch { + return false; + } + } + + /** + * Get STT service URL (for debugging/logging) + */ + getSttUrl(): string { + return this.sttUrl; + } +} diff --git a/packages/bot-services/src/transcription/types.ts b/packages/bot-services/src/transcription/types.ts new file mode 100644 index 000000000..58c4d4565 --- /dev/null +++ b/packages/bot-services/src/transcription/types.ts @@ -0,0 +1,22 @@ +/** + * Types for Speech-to-Text transcription service + */ + +export interface SttResponse { + text: string; + language?: string; + model?: string; + duration?: number; +} + +export interface TranscriptionOptions { + language?: string; + model?: string; +} + +export interface TranscriptionModuleOptions { + sttUrl?: string; + defaultLanguage?: string; +} + +export const STT_MODULE_OPTIONS = 'STT_MODULE_OPTIONS'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 610cb9fe0..bfff99bbc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -137,7 +137,7 @@ importers: devDependencies: '@nestjs/cli': specifier: ^10.4.9 - version: 10.4.9(esbuild@0.19.12) + version: 10.4.9 '@nestjs/schematics': specifier: ^10.2.3 version: 10.2.3(chokidar@3.6.0)(typescript@5.9.3) @@ -185,10 +185,10 @@ importers: version: 0.5.21 ts-jest: specifier: ^29.2.5 - version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.19.12)(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) ts-loader: specifier: ^9.5.1 - version: 9.5.4(typescript@5.9.3)(webpack@5.97.1(esbuild@0.19.12)) + version: 9.5.4(typescript@5.9.3)(webpack@5.100.2) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@22.19.1)(typescript@5.9.3) @@ -212,14 +212,14 @@ importers: version: link:../../../../packages/shared-landing-ui astro: specifier: ^5.16.0 - version: 5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.9.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1) + version: 5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1) typescript: specifier: ^5.9.2 version: 5.9.3 devDependencies: '@astrojs/tailwind': specifier: ^6.0.2 - version: 6.0.2(astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.9.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3)) + version: 6.0.2(astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3)) '@tailwindcss/typography': specifier: ^0.5.18 version: 0.5.19(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1)) @@ -228,13 +228,13 @@ importers: version: 20.19.25 eslint: specifier: ^9.0.0 - version: 9.39.1(jiti@1.21.7) + version: 9.39.1(jiti@2.6.1) eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.2(eslint@9.39.1(jiti@1.21.7)) + version: 9.1.2(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-astro: specifier: ^1.0.0 - version: 1.5.0(eslint@9.39.1(jiti@1.21.7)) + version: 1.5.0(eslint@9.39.1(jiti@2.6.1)) prettier: specifier: ^3.6.2 version: 3.6.2 @@ -609,19 +609,19 @@ importers: version: 18.3.27 '@typescript-eslint/eslint-plugin': specifier: ^7.7.0 - version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) + version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) '@typescript-eslint/parser': specifier: ^7.7.0 - version: 7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) + version: 7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) dotenv: specifier: ^16.4.7 version: 16.6.1 eslint: specifier: ^9.39.1 - version: 9.39.1(jiti@2.6.1) + version: 9.39.1(jiti@1.21.7) eslint-config-universe: specifier: ^12.0.1 - version: 12.1.0(@types/eslint@9.6.1)(eslint@9.39.1(jiti@2.6.1))(prettier@3.6.2)(typescript@5.3.3) + version: 12.1.0(@types/eslint@9.6.1)(eslint@9.39.1(jiti@1.21.7))(prettier@3.6.2)(typescript@5.3.3) prettier: specifier: ^3.2.5 version: 3.6.2 @@ -2333,7 +2333,7 @@ importers: version: 0.5.21 ts-jest: specifier: ^29.2.5 - version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.19.12)(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) ts-loader: specifier: ^9.5.1 version: 9.5.4(typescript@5.9.3)(webpack@5.100.2) @@ -5208,7 +5208,7 @@ importers: version: 1.57.0 jest: specifier: ^29.0.0 - version: 29.7.0(@types/node@24.10.1) + version: 29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)) vitest: specifier: ^3.0.0 version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@27.2.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) @@ -5340,7 +5340,7 @@ importers: version: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) ts-jest: specifier: ^29.2.5 - version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.19.12)(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@22.19.1)(typescript@5.9.3) @@ -5500,7 +5500,7 @@ importers: version: 7.1.4 ts-jest: specifier: ^29.2.5 - version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.19.12)(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) ts-loader: specifier: ^9.5.1 version: 9.5.4(typescript@5.9.3)(webpack@5.100.2) @@ -5612,7 +5612,7 @@ importers: version: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) ts-jest: specifier: ^29.2.5 - version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.19.12)(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@22.19.1)(typescript@5.9.3) @@ -5712,7 +5712,7 @@ importers: version: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) ts-jest: specifier: ^29.2.5 - version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.19.12)(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@22.19.1)(typescript@5.9.3) @@ -5785,7 +5785,7 @@ importers: version: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) ts-jest: specifier: ^29.2.5 - version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.19.12)(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@22.19.1)(typescript@5.9.3) @@ -5866,6 +5866,9 @@ importers: services/matrix-clock-bot: dependencies: + '@manacore/bot-services': + specifier: workspace:* + version: link:../../packages/bot-services '@nestjs/common': specifier: ^10.4.17 version: 10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -6079,6 +6082,9 @@ importers: services/matrix-picture-bot: dependencies: + '@manacore/bot-services': + specifier: workspace:* + version: link:../../packages/bot-services '@nestjs/common': specifier: ^10.4.15 version: 10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -6387,6 +6393,9 @@ importers: services/matrix-todo-bot: dependencies: + '@manacore/bot-services': + specifier: workspace:* + version: link:../../packages/bot-services '@nestjs/common': specifier: ^10.4.15 version: 10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -6458,6 +6467,9 @@ importers: services/matrix-zitare-bot: dependencies: + '@manacore/bot-services': + specifier: workspace:* + version: link:../../packages/bot-services '@nestjs/common': specifier: ^10.4.15 version: 10.4.20(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -8849,7 +8861,7 @@ packages: '@expo/bunyan@4.0.1': resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==} - engines: {'0': node >=0.10.0} + engines: {node: '>=0.10.0'} '@expo/cli@0.22.26': resolution: {integrity: sha512-I689wc8Fn/AX7aUGiwrh3HnssiORMJtR2fpksX+JIe8Cj/EDleblYMSwRPd0025wrwOV9UN1KM/RuEt/QjCS3Q==} @@ -23299,16 +23311,6 @@ snapshots: transitivePeerDependencies: - ts-node - '@astrojs/tailwind@6.0.2(astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.9.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3))': - dependencies: - astro: 5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.9.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1) - autoprefixer: 10.4.22(postcss@8.5.6) - postcss: 8.5.6 - postcss-load-config: 4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3)) - tailwindcss: 3.4.18(tsx@4.20.6)(yaml@2.8.1) - transitivePeerDependencies: - - ts-node - '@astrojs/tailwind@6.0.2(astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3))': dependencies: astro: 5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1) @@ -26378,7 +26380,7 @@ snapshots: wrap-ansi: 7.0.0 ws: 8.18.3 optionalDependencies: - expo-router: 6.0.15(7mqaurqidri6vkknnsci36yp4e) + expo-router: 6.0.15(vmxlpuhz6xqbe2ee7fdabyqx3y) react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0) transitivePeerDependencies: - '@modelcontextprotocol/sdk' @@ -27686,7 +27688,7 @@ snapshots: jest-util: 30.2.0 slash: 3.0.0 - '@jest/core@29.7.0': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -27700,7 +27702,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.19.1) + jest-config: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -27721,7 +27723,7 @@ snapshots: - supports-color - ts-node - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -27735,7 +27737,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) + jest-config: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -28274,32 +28276,6 @@ snapshots: - uglify-js - webpack-cli - '@nestjs/cli@10.4.9(esbuild@0.19.12)': - dependencies: - '@angular-devkit/core': 17.3.11(chokidar@3.6.0) - '@angular-devkit/schematics': 17.3.11(chokidar@3.6.0) - '@angular-devkit/schematics-cli': 17.3.11(chokidar@3.6.0) - '@nestjs/schematics': 10.2.3(chokidar@3.6.0)(typescript@5.7.2) - chalk: 4.1.2 - chokidar: 3.6.0 - cli-table3: 0.6.5 - commander: 4.1.1 - fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.7.2)(webpack@5.97.1(esbuild@0.19.12)) - glob: 10.4.5 - inquirer: 8.2.6 - node-emoji: 1.11.0 - ora: 5.4.1 - tree-kill: 1.2.2 - tsconfig-paths: 4.2.0 - tsconfig-paths-webpack-plugin: 4.2.0 - typescript: 5.7.2 - webpack: 5.97.1(esbuild@0.19.12) - webpack-node-externals: 3.0.0 - transitivePeerDependencies: - - esbuild - - uglify-js - - webpack-cli - '@nestjs/cli@10.4.9(esbuild@0.27.0)': dependencies: '@angular-devkit/core': 17.3.11(chokidar@3.6.0) @@ -31895,19 +31871,6 @@ snapshots: picocolors: 1.1.1 pretty-format: 27.5.1 - '@testing-library/react-native@13.3.3(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0)': - dependencies: - jest-matcher-utils: 30.2.0 - picocolors: 1.1.1 - pretty-format: 30.2.0 - react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0) - react-test-renderer: 19.1.0(react@19.1.0) - redent: 3.0.0 - optionalDependencies: - jest: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) - optional: true - '@testing-library/react-native@13.3.3(jest@30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: jest-matcher-utils: 30.2.0 @@ -32478,16 +32441,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) - '@typescript-eslint/utils': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/type-utils': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) + '@typescript-eslint/utils': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) '@typescript-eslint/visitor-keys': 6.21.0 debug: 4.4.3 - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.1(jiti@1.21.7) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -32536,15 +32499,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/parser': 7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) '@typescript-eslint/scope-manager': 7.18.0 - '@typescript-eslint/type-utils': 7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) - '@typescript-eslint/utils': 7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/type-utils': 7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) + '@typescript-eslint/utils': 7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) '@typescript-eslint/visitor-keys': 7.18.0 - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.1(jiti@1.21.7) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -32636,14 +32599,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)': dependencies: '@typescript-eslint/scope-manager': 6.21.0 '@typescript-eslint/types': 6.21.0 '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) '@typescript-eslint/visitor-keys': 6.21.0 debug: 4.4.3 - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.1(jiti@1.21.7) optionalDependencies: typescript: 5.3.3 transitivePeerDependencies: @@ -32675,14 +32638,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/parser@7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)': dependencies: '@typescript-eslint/scope-manager': 7.18.0 '@typescript-eslint/types': 7.18.0 '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.3.3) '@typescript-eslint/visitor-keys': 7.18.0 debug: 4.4.3 - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.1(jiti@1.21.7) optionalDependencies: typescript: 5.3.3 transitivePeerDependencies: @@ -32808,12 +32771,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/type-utils@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)': dependencies: '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) - '@typescript-eslint/utils': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/utils': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) debug: 4.4.3 - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.1(jiti@1.21.7) ts-api-utils: 1.4.3(typescript@5.3.3) optionalDependencies: typescript: 5.3.3 @@ -32844,12 +32807,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/type-utils@7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)': dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.3.3) - '@typescript-eslint/utils': 7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/utils': 7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) debug: 4.4.3 - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.1(jiti@1.21.7) ts-api-utils: 1.4.3(typescript@5.3.3) optionalDependencies: typescript: 5.3.3 @@ -33031,15 +32994,15 @@ snapshots: - supports-color - typescript - '@typescript-eslint/utils@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/utils@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@1.21.7)) '@types/json-schema': 7.0.15 '@types/semver': 7.7.1 '@typescript-eslint/scope-manager': 6.21.0 '@typescript-eslint/types': 6.21.0 '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.1(jiti@1.21.7) semver: 7.7.3 transitivePeerDependencies: - supports-color @@ -33070,13 +33033,13 @@ snapshots: - supports-color - typescript - '@typescript-eslint/utils@7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)': + '@typescript-eslint/utils@7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@1.21.7)) '@typescript-eslint/scope-manager': 7.18.0 '@typescript-eslint/types': 7.18.0 '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.3.3) - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.1(jiti@1.21.7) transitivePeerDependencies: - supports-color - typescript @@ -33975,108 +33938,6 @@ snapshots: transitivePeerDependencies: - supports-color - astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.9.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1): - dependencies: - '@astrojs/compiler': 2.13.0 - '@astrojs/internal-helpers': 0.7.5 - '@astrojs/markdown-remark': 6.3.9 - '@astrojs/telemetry': 3.3.0 - '@capsizecss/unpack': 3.0.1 - '@oslojs/encoding': 1.1.0 - '@rollup/pluginutils': 5.3.0(rollup@4.53.3) - acorn: 8.15.0 - aria-query: 5.3.2 - axobject-query: 4.1.0 - boxen: 8.0.1 - ci-info: 4.3.1 - clsx: 2.1.1 - common-ancestor-path: 1.0.1 - cookie: 1.1.0 - cssesc: 3.0.0 - debug: 4.4.3 - deterministic-object-hash: 2.0.2 - devalue: 5.5.0 - diff: 5.2.0 - dlv: 1.1.3 - dset: 3.1.4 - es-module-lexer: 1.7.0 - esbuild: 0.25.12 - estree-walker: 3.0.3 - flattie: 1.1.1 - fontace: 0.3.1 - github-slugger: 2.0.0 - html-escaper: 3.0.3 - http-cache-semantics: 4.2.0 - import-meta-resolve: 4.2.0 - js-yaml: 4.1.1 - magic-string: 0.30.21 - magicast: 0.5.1 - mrmime: 2.0.1 - neotraverse: 0.6.18 - p-limit: 6.2.0 - p-queue: 8.1.1 - package-manager-detector: 1.5.0 - piccolore: 0.1.3 - picomatch: 4.0.3 - prompts: 2.4.2 - rehype: 13.0.2 - semver: 7.7.3 - shiki: 3.15.0 - smol-toml: 1.5.2 - svgo: 4.0.0 - tinyexec: 1.0.2 - tinyglobby: 0.2.15 - tsconfck: 3.1.6(typescript@5.9.3) - ultrahtml: 1.6.0 - unifont: 0.6.0 - unist-util-visit: 5.0.0 - unstorage: 1.17.3(@netlify/blobs@10.4.1)(ioredis@5.9.2) - vfile: 6.0.3 - vite: 6.4.1(@types/node@20.19.25)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - vitefu: 1.1.1(vite@6.4.1(@types/node@20.19.25)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) - xxhash-wasm: 1.1.0 - yargs-parser: 21.1.1 - yocto-spinner: 0.2.3 - zod: 3.25.76 - zod-to-json-schema: 3.25.0(zod@3.25.76) - zod-to-ts: 1.2.0(typescript@5.9.3)(zod@3.25.76) - optionalDependencies: - sharp: 0.34.5 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@types/node' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' - - aws4fetch - - db0 - - idb-keyval - - ioredis - - jiti - - less - - lightningcss - - rollup - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - typescript - - uploadthing - - yaml - astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1): dependencies: '@astrojs/compiler': 2.13.0 @@ -35363,13 +35224,13 @@ snapshots: - supports-color - ts-node - create-jest@29.7.0(@types/node@24.10.1): + create-jest@29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@24.10.1) + jest-config: 29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -36473,11 +36334,6 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-compat-utils@0.6.5(eslint@9.39.1(jiti@1.21.7)): - dependencies: - eslint: 9.39.1(jiti@1.21.7) - semver: 7.7.3 - eslint-compat-utils@0.6.5(eslint@9.39.1(jiti@2.6.1)): dependencies: eslint: 9.39.1(jiti@2.6.1) @@ -36488,9 +36344,9 @@ snapshots: '@typescript-eslint/eslint-plugin': 8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) eslint: 9.39.1(jiti@2.6.1) - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-expo: 1.0.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-react: 7.37.5(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.39.1(jiti@2.6.1)) globals: 16.5.0 @@ -36505,9 +36361,9 @@ snapshots: '@typescript-eslint/eslint-plugin': 8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) '@typescript-eslint/parser': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) eslint: 9.39.1(jiti@2.6.1) - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-expo: 0.1.4(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-react: 7.37.5(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.39.1(jiti@2.6.1)) globals: 16.5.0 @@ -36525,14 +36381,14 @@ snapshots: dependencies: eslint: 8.57.1 + eslint-config-prettier@8.10.2(eslint@9.39.1(jiti@1.21.7)): + dependencies: + eslint: 9.39.1(jiti@1.21.7) + eslint-config-prettier@8.10.2(eslint@9.39.1(jiti@2.6.1)): dependencies: eslint: 9.39.1(jiti@2.6.1) - eslint-config-prettier@9.1.2(eslint@9.39.1(jiti@1.21.7)): - dependencies: - eslint: 9.39.1(jiti@1.21.7) - eslint-config-prettier@9.1.2(eslint@9.39.1(jiti@2.6.1)): dependencies: eslint: 9.39.1(jiti@2.6.1) @@ -36557,17 +36413,17 @@ snapshots: - supports-color - typescript - eslint-config-universe@12.1.0(@types/eslint@9.6.1)(eslint@9.39.1(jiti@2.6.1))(prettier@3.6.2)(typescript@5.3.3): + eslint-config-universe@12.1.0(@types/eslint@9.6.1)(eslint@9.39.1(jiti@1.21.7))(prettier@3.6.2)(typescript@5.3.3): dependencies: - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) - '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) - eslint: 9.39.1(jiti@2.6.1) - eslint-config-prettier: 8.10.2(eslint@9.39.1(jiti@2.6.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.1(jiti@2.6.1)) - eslint-plugin-node: 11.1.0(eslint@9.39.1(jiti@2.6.1)) - eslint-plugin-prettier: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@8.10.2(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(prettier@3.6.2) - eslint-plugin-react: 7.37.5(eslint@9.39.1(jiti@2.6.1)) - eslint-plugin-react-hooks: 4.6.2(eslint@9.39.1(jiti@2.6.1)) + '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) + '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) + eslint: 9.39.1(jiti@1.21.7) + eslint-config-prettier: 8.10.2(eslint@9.39.1(jiti@1.21.7)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.1(jiti@1.21.7)) + eslint-plugin-node: 11.1.0(eslint@9.39.1(jiti@1.21.7)) + eslint-plugin-prettier: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@8.10.2(eslint@9.39.1(jiti@1.21.7)))(eslint@9.39.1(jiti@1.21.7))(prettier@3.6.2) + eslint-plugin-react: 7.37.5(eslint@9.39.1(jiti@1.21.7)) + eslint-plugin-react-hooks: 4.6.2(eslint@9.39.1(jiti@1.21.7)) optionalDependencies: prettier: 3.6.2 transitivePeerDependencies: @@ -36605,7 +36461,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 @@ -36616,22 +36472,7 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)) - transitivePeerDependencies: - - supports-color - - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)): - dependencies: - '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.3 - eslint: 9.39.1(jiti@2.6.1) - get-tsconfig: 4.13.0 - is-bun-module: 2.0.0 - stable-hash: 0.0.5 - tinyglobby: 0.2.15 - unrs-resolver: 1.11.1 - optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)) transitivePeerDependencies: - supports-color @@ -36645,12 +36486,12 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1(jiti@1.21.7)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) - eslint: 9.39.1(jiti@2.6.1) + '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) + eslint: 9.39.1(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color @@ -36665,39 +36506,25 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) eslint: 9.39.1(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) eslint: 9.39.1(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)) - transitivePeerDependencies: - - supports-color - - eslint-plugin-astro@1.5.0(eslint@9.39.1(jiti@1.21.7)): - dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@1.21.7)) - '@jridgewell/sourcemap-codec': 1.5.5 - '@typescript-eslint/types': 8.48.0 - astro-eslint-parser: 1.2.2 - eslint: 9.39.1(jiti@1.21.7) - eslint-compat-utils: 0.6.5(eslint@9.39.1(jiti@1.21.7)) - globals: 16.5.0 - postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)) transitivePeerDependencies: - supports-color @@ -36721,6 +36548,12 @@ snapshots: eslint-utils: 2.1.0 regexpp: 3.2.0 + eslint-plugin-es@3.0.1(eslint@9.39.1(jiti@1.21.7)): + dependencies: + eslint: 9.39.1(jiti@1.21.7) + eslint-utils: 2.1.0 + regexpp: 3.2.0 + eslint-plugin-es@3.0.1(eslint@9.39.1(jiti@2.6.1)): dependencies: eslint: 9.39.1(jiti@2.6.1) @@ -36774,7 +36607,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.1(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.1(jiti@1.21.7)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -36783,9 +36616,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.1(jiti@1.21.7) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1(jiti@1.21.7)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -36797,7 +36630,7 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3) + '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -36832,7 +36665,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -36843,7 +36676,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.39.1(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -36861,7 +36694,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -36872,7 +36705,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.39.1(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -36900,6 +36733,16 @@ snapshots: resolve: 1.22.11 semver: 6.3.1 + eslint-plugin-node@11.1.0(eslint@9.39.1(jiti@1.21.7)): + dependencies: + eslint: 9.39.1(jiti@1.21.7) + eslint-plugin-es: 3.0.1(eslint@9.39.1(jiti@1.21.7)) + eslint-utils: 2.1.0 + ignore: 5.3.2 + minimatch: 3.1.2 + resolve: 1.22.11 + semver: 6.3.1 + eslint-plugin-node@11.1.0(eslint@9.39.1(jiti@2.6.1)): dependencies: eslint: 9.39.1(jiti@2.6.1) @@ -36930,6 +36773,16 @@ snapshots: '@types/eslint': 9.6.1 eslint-config-prettier: 8.10.2(eslint@8.57.1) + eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@8.10.2(eslint@9.39.1(jiti@1.21.7)))(eslint@9.39.1(jiti@1.21.7))(prettier@3.6.2): + dependencies: + eslint: 9.39.1(jiti@1.21.7) + prettier: 3.6.2 + prettier-linter-helpers: 1.0.0 + synckit: 0.11.11 + optionalDependencies: + '@types/eslint': 9.6.1 + eslint-config-prettier: 8.10.2(eslint@9.39.1(jiti@1.21.7)) + eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@8.10.2(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(prettier@3.6.2): dependencies: eslint: 9.39.1(jiti@2.6.1) @@ -36954,6 +36807,10 @@ snapshots: dependencies: eslint: 8.57.1 + eslint-plugin-react-hooks@4.6.2(eslint@9.39.1(jiti@1.21.7)): + dependencies: + eslint: 9.39.1(jiti@1.21.7) + eslint-plugin-react-hooks@4.6.2(eslint@9.39.1(jiti@2.6.1)): dependencies: eslint: 9.39.1(jiti@2.6.1) @@ -36984,6 +36841,28 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 + eslint-plugin-react@7.37.5(eslint@9.39.1(jiti@1.21.7)): + dependencies: + array-includes: 3.1.9 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.2.1 + eslint: 9.39.1(jiti@1.21.7) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + eslint-plugin-react@7.37.5(eslint@9.39.1(jiti@2.6.1)): dependencies: array-includes: 3.1.9 @@ -38126,53 +38005,6 @@ snapshots: - react-native - supports-color - expo-router@6.0.15(7mqaurqidri6vkknnsci36yp4e): - dependencies: - '@expo/metro-runtime': 6.1.2(expo@54.0.25)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) - '@expo/schema-utils': 0.1.7 - '@radix-ui/react-slot': 1.2.0(@types/react@19.2.7)(react@19.1.0) - '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-navigation/bottom-tabs': 7.8.6(@react-navigation/native@7.1.21(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) - '@react-navigation/native': 7.1.21(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) - '@react-navigation/native-stack': 7.8.0(@react-navigation/native@7.1.21(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) - client-only: 0.0.1 - debug: 4.4.3 - escape-string-regexp: 4.0.0 - expo: 54.0.25(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.15)(react-native-webview@13.12.2(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) - expo-constants: 18.0.10(expo@54.0.25)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0)) - expo-linking: 8.0.9(expo@54.0.25)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) - expo-server: 1.0.4 - fast-deep-equal: 3.1.3 - invariant: 2.2.4 - nanoid: 3.3.11 - query-string: 7.1.3 - react: 19.1.0 - react-fast-compare: 3.2.2 - react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0) - react-native-is-edge-to-edge: 1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) - react-native-safe-area-context: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) - react-native-screens: 4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) - semver: 7.6.3 - server-only: 0.0.1 - sf-symbols-typescript: 2.1.0 - shallowequal: 1.1.0 - use-latest-callback: 0.2.6(react@19.1.0) - vaul: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - optionalDependencies: - '@react-navigation/drawer': 7.7.4(@react-navigation/native@7.1.21(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-gesture-handler@2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-reanimated@4.1.5(@babel/core@7.28.5)(react-native-worklets@0.6.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) - '@testing-library/react-native': 13.3.3(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0) - react-dom: 19.1.0(react@19.1.0) - react-native-gesture-handler: 2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) - react-native-reanimated: 4.1.5(@babel/core@7.28.5)(react-native-worklets@0.6.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) - react-native-web: 0.21.2(encoding@0.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react-server-dom-webpack: 19.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.97.1(esbuild@0.19.12)) - transitivePeerDependencies: - - '@react-native-masked-view/masked-view' - - '@types/react' - - '@types/react-dom' - - supports-color - optional: true - expo-router@6.0.15(k2muy65dii4k2uiuhg4mwyy6ki): dependencies: '@expo/metro-runtime': 6.1.2(expo@54.0.25)(react-dom@19.1.0(react@18.3.1))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@18.3.27)(react@18.3.1))(react@18.3.1) @@ -39295,23 +39127,6 @@ snapshots: forever-agent@0.6.1: {} - fork-ts-checker-webpack-plugin@9.0.2(typescript@5.7.2)(webpack@5.97.1(esbuild@0.19.12)): - dependencies: - '@babel/code-frame': 7.27.1 - chalk: 4.1.2 - chokidar: 3.6.0 - cosmiconfig: 8.3.6(typescript@5.7.2) - deepmerge: 4.3.1 - fs-extra: 10.1.0 - memfs: 3.5.3 - minimatch: 3.1.2 - node-abort-controller: 3.1.1 - schema-utils: 3.3.0 - semver: 7.7.3 - tapable: 2.3.0 - typescript: 5.7.2 - webpack: 5.97.1(esbuild@0.19.12) - fork-ts-checker-webpack-plugin@9.0.2(typescript@5.7.2)(webpack@5.97.1(esbuild@0.27.0)): dependencies: '@babel/code-frame': 7.27.1 @@ -40767,16 +40582,16 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@24.10.1): + jest-cli@29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)): dependencies: - '@jest/core': 29.7.0 + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@24.10.1) + create-jest: 29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@24.10.1) + jest-config: 29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -40864,36 +40679,6 @@ snapshots: - ts-node optional: true - jest-config@29.7.0(@types/node@22.19.1): - dependencies: - '@babel/core': 7.28.5 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.28.5) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 22.19.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - jest-config@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)): dependencies: '@babel/core': 7.28.5 @@ -40925,7 +40710,38 @@ snapshots: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@24.10.1): + jest-config@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)): + dependencies: + '@babel/core': 7.28.5 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.28.5) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 22.19.1 + ts-node: 10.9.2(@types/node@24.10.1)(typescript@5.9.3) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-config@29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)): dependencies: '@babel/core': 7.28.5 '@jest/test-sequencer': 29.7.0 @@ -40951,6 +40767,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 24.10.1 + ts-node: 10.9.2(@types/node@24.10.1)(typescript@5.9.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -41537,12 +41354,12 @@ snapshots: - supports-color - ts-node - jest@29.7.0(@types/node@24.10.1): + jest@29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)): dependencies: - '@jest/core': 29.7.0 + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@24.10.1) + jest-cli: 29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -45916,16 +45733,6 @@ snapshots: webpack-sources: 3.3.3 optional: true - react-server-dom-webpack@19.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.97.1(esbuild@0.19.12)): - dependencies: - acorn-loose: 8.5.2 - neo-async: 2.6.2 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - webpack: 5.97.1(esbuild@0.19.12) - webpack-sources: 3.3.3 - optional: true - react-style-singleton@2.2.3(@types/react@18.3.27)(react@18.3.1): dependencies: get-nonce: 1.0.1 @@ -47387,17 +47194,6 @@ snapshots: ansi-escapes: 4.3.2 supports-hyperlinks: 2.3.0 - terser-webpack-plugin@5.3.14(esbuild@0.19.12)(webpack@5.97.1(esbuild@0.19.12)): - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - jest-worker: 27.5.1 - schema-utils: 4.3.3 - serialize-javascript: 6.0.2 - terser: 5.44.1 - webpack: 5.97.1(esbuild@0.19.12) - optionalDependencies: - esbuild: 0.19.12 - terser-webpack-plugin@5.3.14(esbuild@0.27.0)(webpack@5.100.2(esbuild@0.27.0)): dependencies: '@jridgewell/trace-mapping': 0.3.31 @@ -47598,27 +47394,6 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.19.12)(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3): - dependencies: - bs-logger: 0.2.6 - fast-json-stable-stringify: 2.1.0 - handlebars: 4.7.8 - jest: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.7.3 - type-fest: 4.41.0 - typescript: 5.9.3 - yargs-parser: 21.1.1 - optionalDependencies: - '@babel/core': 7.28.5 - '@jest/transform': 30.2.0 - '@jest/types': 30.2.0 - babel-jest: 30.2.0(@babel/core@7.28.5) - esbuild: 0.19.12 - jest-util: 30.2.0 - ts-jest@29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.27.0)(jest-util@30.2.0)(jest@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3): dependencies: bs-logger: 0.2.6 @@ -47661,6 +47436,26 @@ snapshots: esbuild: 0.27.0 jest-util: 30.2.0 + ts-jest@29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3): + dependencies: + bs-logger: 0.2.6 + fast-json-stable-stringify: 2.1.0 + handlebars: 4.7.8 + jest: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.7.3 + type-fest: 4.41.0 + typescript: 5.9.3 + yargs-parser: 21.1.1 + optionalDependencies: + '@babel/core': 7.28.5 + '@jest/transform': 30.2.0 + '@jest/types': 30.2.0 + babel-jest: 30.2.0(@babel/core@7.28.5) + jest-util: 30.2.0 + ts-loader@9.5.4(typescript@5.9.3)(webpack@5.100.2(esbuild@0.27.0)): dependencies: chalk: 4.1.2 @@ -47681,16 +47476,6 @@ snapshots: typescript: 5.9.3 webpack: 5.100.2 - ts-loader@9.5.4(typescript@5.9.3)(webpack@5.97.1(esbuild@0.19.12)): - dependencies: - chalk: 4.1.2 - enhanced-resolve: 5.18.3 - micromatch: 4.0.8 - semver: 7.7.3 - source-map: 0.7.6 - typescript: 5.9.3 - webpack: 5.97.1(esbuild@0.19.12) - ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3): dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -48371,23 +48156,6 @@ snapshots: lightningcss: 1.30.2 terser: 5.44.1 - vite@6.4.1(@types/node@20.19.25)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1): - dependencies: - esbuild: 0.25.12 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.53.3 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 20.19.25 - fsevents: 2.3.3 - jiti: 1.21.7 - lightningcss: 1.30.2 - terser: 5.44.1 - tsx: 4.20.6 - yaml: 2.8.1 - vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1): dependencies: esbuild: 0.25.12 @@ -48491,10 +48259,6 @@ snapshots: tsx: 4.20.6 yaml: 2.8.1 - vitefu@1.1.1(vite@6.4.1(@types/node@20.19.25)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)): - optionalDependencies: - vite: 6.4.1(@types/node@20.19.25)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - vitefu@1.1.1(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)): optionalDependencies: vite: 6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) @@ -48949,36 +48713,6 @@ snapshots: - esbuild - uglify-js - webpack@5.97.1(esbuild@0.19.12): - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.8 - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/wasm-edit': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.15.0 - browserslist: 4.28.0 - chrome-trace-event: 1.0.4 - enhanced-resolve: 5.18.3 - es-module-lexer: 1.7.0 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.1 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.3.0 - terser-webpack-plugin: 5.3.14(esbuild@0.19.12)(webpack@5.97.1(esbuild@0.19.12)) - watchpack: 2.4.4 - webpack-sources: 3.3.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - webpack@5.97.1(esbuild@0.27.0): dependencies: '@types/eslint-scope': 3.7.7 diff --git a/services/matrix-clock-bot/package.json b/services/matrix-clock-bot/package.json index 74e1ecaea..75a2f66ad 100644 --- a/services/matrix-clock-bot/package.json +++ b/services/matrix-clock-bot/package.json @@ -24,6 +24,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { + "@manacore/bot-services": "workspace:*", "@nestjs/common": "^10.4.17", "@nestjs/config": "^3.3.0", "@nestjs/core": "^10.4.17", diff --git a/services/matrix-clock-bot/src/bot/bot.module.ts b/services/matrix-clock-bot/src/bot/bot.module.ts index a3d2e67ab..d5325eec7 100644 --- a/services/matrix-clock-bot/src/bot/bot.module.ts +++ b/services/matrix-clock-bot/src/bot/bot.module.ts @@ -1,10 +1,10 @@ import { Module } from '@nestjs/common'; import { MatrixService } from './matrix.service'; import { ClockModule } from '../clock/clock.module'; -import { TranscriptionModule } from '../transcription/transcription.module'; +import { TranscriptionModule } from '@manacore/bot-services'; @Module({ - imports: [ClockModule, TranscriptionModule], + imports: [ClockModule, TranscriptionModule.forRoot()], providers: [MatrixService], exports: [MatrixService], }) diff --git a/services/matrix-clock-bot/src/bot/matrix.service.ts b/services/matrix-clock-bot/src/bot/matrix.service.ts index 430be0fd3..08b5fb9dc 100644 --- a/services/matrix-clock-bot/src/bot/matrix.service.ts +++ b/services/matrix-clock-bot/src/bot/matrix.service.ts @@ -9,7 +9,7 @@ import { import * as path from 'path'; import * as fs from 'fs'; import { ClockService, Timer, Alarm } from '../clock/clock.service'; -import { TranscriptionService } from '../transcription/transcription.service'; +import { TranscriptionService } from '@manacore/bot-services'; import { HELP_TEXT, WELCOME_TEXT } from '../config/configuration'; // Natural language keywords diff --git a/services/matrix-clock-bot/src/transcription/transcription.module.ts b/services/matrix-clock-bot/src/transcription/transcription.module.ts deleted file mode 100644 index fb5aeeaf1..000000000 --- a/services/matrix-clock-bot/src/transcription/transcription.module.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TranscriptionService } from './transcription.service'; - -@Module({ - providers: [TranscriptionService], - exports: [TranscriptionService], -}) -export class TranscriptionModule {} diff --git a/services/matrix-clock-bot/src/transcription/transcription.service.ts b/services/matrix-clock-bot/src/transcription/transcription.service.ts deleted file mode 100644 index 85296cf98..000000000 --- a/services/matrix-clock-bot/src/transcription/transcription.service.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; - -interface SttResponse { - text: string; - language?: string; - model?: string; -} - -@Injectable() -export class TranscriptionService { - private readonly logger = new Logger(TranscriptionService.name); - private readonly sttUrl: string; - - constructor(private configService: ConfigService) { - this.sttUrl = this.configService.get('stt.url') || 'http://localhost:3020'; - this.logger.log(`STT Service URL: ${this.sttUrl}`); - } - - async transcribe(audioBuffer: Buffer, language: string = 'de'): Promise { - const formData = new FormData(); - const blob = new Blob([new Uint8Array(audioBuffer)], { type: 'audio/ogg' }); - formData.append('file', blob, 'audio.ogg'); - formData.append('language', language); - - try { - const response = await fetch(`${this.sttUrl}/transcribe`, { - method: 'POST', - body: formData, - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error(`STT service error: ${response.status} - ${errorText}`); - } - - const result: SttResponse = await response.json(); - this.logger.log(`Transcription completed: ${result.text.substring(0, 50)}...`); - return result.text; - } catch (error) { - this.logger.error('Transcription failed:', error); - throw error; - } - } - - async checkHealth(): Promise { - try { - const response = await fetch(`${this.sttUrl}/health`); - return response.ok; - } catch { - return false; - } - } -} diff --git a/services/matrix-picture-bot/package.json b/services/matrix-picture-bot/package.json index 845a17699..15012907d 100644 --- a/services/matrix-picture-bot/package.json +++ b/services/matrix-picture-bot/package.json @@ -5,7 +5,9 @@ "private": true, "main": "dist/main.js", "pnpm": { - "neverBuiltDependencies": ["@matrix-org/matrix-sdk-crypto-nodejs"], + "neverBuiltDependencies": [ + "@matrix-org/matrix-sdk-crypto-nodejs" + ], "overrides": { "@matrix-org/matrix-sdk-crypto-nodejs": "npm:empty-npm-package@1.0.0" } @@ -22,6 +24,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { + "@manacore/bot-services": "workspace:*", "@nestjs/common": "^10.4.15", "@nestjs/config": "^3.3.0", "@nestjs/core": "^10.4.15", diff --git a/services/matrix-picture-bot/src/bot/bot.module.ts b/services/matrix-picture-bot/src/bot/bot.module.ts index c72f5b4e0..49958a851 100644 --- a/services/matrix-picture-bot/src/bot/bot.module.ts +++ b/services/matrix-picture-bot/src/bot/bot.module.ts @@ -1,10 +1,10 @@ import { Module } from '@nestjs/common'; import { MatrixService } from './matrix.service'; import { PictureModule } from '../picture/picture.module'; -import { SessionModule } from '../session/session.module'; +import { SessionModule } from '@manacore/bot-services'; @Module({ - imports: [PictureModule, SessionModule], + imports: [PictureModule, SessionModule.forRoot()], providers: [MatrixService], exports: [MatrixService], }) diff --git a/services/matrix-picture-bot/src/bot/matrix.service.ts b/services/matrix-picture-bot/src/bot/matrix.service.ts index 73e2871e4..0357f2403 100644 --- a/services/matrix-picture-bot/src/bot/matrix.service.ts +++ b/services/matrix-picture-bot/src/bot/matrix.service.ts @@ -8,7 +8,7 @@ import { LogLevel, } from 'matrix-bot-sdk'; import { PictureService } from '../picture/picture.service'; -import { SessionService } from '../session/session.service'; +import { SessionService } from '@manacore/bot-services'; import { HELP_MESSAGE } from '../config/configuration'; // Natural language keywords that trigger commands diff --git a/services/matrix-picture-bot/src/session/session.module.ts b/services/matrix-picture-bot/src/session/session.module.ts deleted file mode 100644 index 834b715eb..000000000 --- a/services/matrix-picture-bot/src/session/session.module.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Module } from '@nestjs/common'; -import { SessionService } from './session.service'; - -@Module({ - providers: [SessionService], - exports: [SessionService], -}) -export class SessionModule {} diff --git a/services/matrix-picture-bot/src/session/session.service.ts b/services/matrix-picture-bot/src/session/session.service.ts deleted file mode 100644 index 7c2064522..000000000 --- a/services/matrix-picture-bot/src/session/session.service.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; - -interface UserSession { - token: string; - email: string; - expiresAt: Date; -} - -@Injectable() -export class SessionService { - private readonly logger = new Logger(SessionService.name); - private sessions: Map = new Map(); - private authUrl: string; - - constructor(private configService: ConfigService) { - this.authUrl = this.configService.get('auth.url') || 'http://localhost:3001'; - } - - async login( - matrixUserId: string, - email: string, - password: string - ): Promise<{ success: boolean; error?: string }> { - try { - const response = await fetch(`${this.authUrl}/api/v1/auth/login`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ email, password }), - }); - - if (!response.ok) { - const errorData = await response.json().catch(() => ({})); - return { - success: false, - error: errorData.message || 'Authentifizierung fehlgeschlagen', - }; - } - - const data = await response.json(); - const token = data.accessToken || data.token; - - if (!token) { - return { success: false, error: 'Kein Token erhalten' }; - } - - // Store session (7 days expiry) - this.sessions.set(matrixUserId, { - token, - email, - expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), - }); - - this.logger.log(`User ${matrixUserId} logged in as ${email}`); - return { success: true }; - } catch (error) { - this.logger.error(`Login failed for ${matrixUserId}:`, error); - return { - success: false, - error: 'Verbindung zum Auth-Server fehlgeschlagen', - }; - } - } - - logout(matrixUserId: string): void { - this.sessions.delete(matrixUserId); - this.logger.log(`User ${matrixUserId} logged out`); - } - - getToken(matrixUserId: string): string | null { - const session = this.sessions.get(matrixUserId); - - if (!session) return null; - - // Check if token expired - if (session.expiresAt < new Date()) { - this.sessions.delete(matrixUserId); - return null; - } - - return session.token; - } - - isLoggedIn(matrixUserId: string): boolean { - return this.getToken(matrixUserId) !== null; - } - - getSessionCount(): number { - return this.sessions.size; - } - - getLoggedInCount(): number { - const now = new Date(); - let count = 0; - for (const session of this.sessions.values()) { - if (session.expiresAt > now) count++; - } - return count; - } -} diff --git a/services/matrix-todo-bot/package.json b/services/matrix-todo-bot/package.json index e70f61c05..c7c18663c 100644 --- a/services/matrix-todo-bot/package.json +++ b/services/matrix-todo-bot/package.json @@ -27,6 +27,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { + "@manacore/bot-services": "workspace:*", "@nestjs/common": "^10.4.15", "@nestjs/config": "^3.3.0", "@nestjs/core": "^10.4.15", diff --git a/services/matrix-todo-bot/src/bot/bot.module.ts b/services/matrix-todo-bot/src/bot/bot.module.ts index ab1832ce3..0ad4c698f 100644 --- a/services/matrix-todo-bot/src/bot/bot.module.ts +++ b/services/matrix-todo-bot/src/bot/bot.module.ts @@ -1,10 +1,10 @@ import { Module } from '@nestjs/common'; import { MatrixService } from './matrix.service'; import { TodoModule } from '../todo/todo.module'; -import { TranscriptionModule } from '../transcription/transcription.module'; +import { TranscriptionModule } from '@manacore/bot-services'; @Module({ - imports: [TodoModule, TranscriptionModule], + imports: [TodoModule, TranscriptionModule.forRoot()], providers: [MatrixService], exports: [MatrixService], }) diff --git a/services/matrix-todo-bot/src/bot/matrix.service.ts b/services/matrix-todo-bot/src/bot/matrix.service.ts index 22a6e1691..4b8cb1fe9 100644 --- a/services/matrix-todo-bot/src/bot/matrix.service.ts +++ b/services/matrix-todo-bot/src/bot/matrix.service.ts @@ -9,7 +9,7 @@ import { import * as path from 'path'; import * as fs from 'fs'; import { TodoService, Task } from '../todo/todo.service'; -import { TranscriptionService } from '../transcription/transcription.service'; +import { TranscriptionService } from '@manacore/bot-services'; import { HELP_TEXT, WELCOME_TEXT, BOT_INTRODUCTION } from '../config/configuration'; // Natural language keywords that trigger commands (German + English) diff --git a/services/matrix-todo-bot/src/transcription/transcription.module.ts b/services/matrix-todo-bot/src/transcription/transcription.module.ts deleted file mode 100644 index fb5aeeaf1..000000000 --- a/services/matrix-todo-bot/src/transcription/transcription.module.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TranscriptionService } from './transcription.service'; - -@Module({ - providers: [TranscriptionService], - exports: [TranscriptionService], -}) -export class TranscriptionModule {} diff --git a/services/matrix-todo-bot/src/transcription/transcription.service.ts b/services/matrix-todo-bot/src/transcription/transcription.service.ts deleted file mode 100644 index 85296cf98..000000000 --- a/services/matrix-todo-bot/src/transcription/transcription.service.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; - -interface SttResponse { - text: string; - language?: string; - model?: string; -} - -@Injectable() -export class TranscriptionService { - private readonly logger = new Logger(TranscriptionService.name); - private readonly sttUrl: string; - - constructor(private configService: ConfigService) { - this.sttUrl = this.configService.get('stt.url') || 'http://localhost:3020'; - this.logger.log(`STT Service URL: ${this.sttUrl}`); - } - - async transcribe(audioBuffer: Buffer, language: string = 'de'): Promise { - const formData = new FormData(); - const blob = new Blob([new Uint8Array(audioBuffer)], { type: 'audio/ogg' }); - formData.append('file', blob, 'audio.ogg'); - formData.append('language', language); - - try { - const response = await fetch(`${this.sttUrl}/transcribe`, { - method: 'POST', - body: formData, - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error(`STT service error: ${response.status} - ${errorText}`); - } - - const result: SttResponse = await response.json(); - this.logger.log(`Transcription completed: ${result.text.substring(0, 50)}...`); - return result.text; - } catch (error) { - this.logger.error('Transcription failed:', error); - throw error; - } - } - - async checkHealth(): Promise { - try { - const response = await fetch(`${this.sttUrl}/health`); - return response.ok; - } catch { - return false; - } - } -} diff --git a/services/matrix-zitare-bot/package.json b/services/matrix-zitare-bot/package.json index 6faaddb82..381b515d1 100644 --- a/services/matrix-zitare-bot/package.json +++ b/services/matrix-zitare-bot/package.json @@ -23,6 +23,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { + "@manacore/bot-services": "workspace:*", "@nestjs/common": "^10.4.15", "@nestjs/config": "^3.3.0", "@nestjs/core": "^10.4.15", diff --git a/services/matrix-zitare-bot/src/bot/bot.module.ts b/services/matrix-zitare-bot/src/bot/bot.module.ts index d58e1b870..bcc227f78 100644 --- a/services/matrix-zitare-bot/src/bot/bot.module.ts +++ b/services/matrix-zitare-bot/src/bot/bot.module.ts @@ -1,11 +1,10 @@ import { Module } from '@nestjs/common'; import { MatrixService } from './matrix.service'; import { QuotesModule } from '../quotes/quotes.module'; -import { SessionModule } from '../session/session.module'; -import { TranscriptionModule } from '../transcription/transcription.module'; +import { SessionModule, TranscriptionModule } from '@manacore/bot-services'; @Module({ - imports: [QuotesModule, SessionModule, TranscriptionModule], + imports: [QuotesModule, SessionModule.forRoot(), TranscriptionModule.forRoot()], providers: [MatrixService], exports: [MatrixService], }) diff --git a/services/matrix-zitare-bot/src/bot/matrix.service.ts b/services/matrix-zitare-bot/src/bot/matrix.service.ts index 67c410402..6f586777e 100644 --- a/services/matrix-zitare-bot/src/bot/matrix.service.ts +++ b/services/matrix-zitare-bot/src/bot/matrix.service.ts @@ -9,8 +9,7 @@ import { } from 'matrix-bot-sdk'; import { QuotesService } from '../quotes/quotes.service'; import { ZitareService } from '../quotes/zitare.service'; -import { SessionService } from '../session/session.service'; -import { TranscriptionService } from '../transcription/transcription.service'; +import { SessionService, TranscriptionService } from '@manacore/bot-services'; import { HELP_MESSAGE, Category } from '../config/configuration'; // Natural language keywords that trigger commands diff --git a/services/matrix-zitare-bot/src/session/session.module.ts b/services/matrix-zitare-bot/src/session/session.module.ts deleted file mode 100644 index 834b715eb..000000000 --- a/services/matrix-zitare-bot/src/session/session.module.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Module } from '@nestjs/common'; -import { SessionService } from './session.service'; - -@Module({ - providers: [SessionService], - exports: [SessionService], -}) -export class SessionModule {} diff --git a/services/matrix-zitare-bot/src/session/session.service.ts b/services/matrix-zitare-bot/src/session/session.service.ts deleted file mode 100644 index 68c047813..000000000 --- a/services/matrix-zitare-bot/src/session/session.service.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; - -interface UserSession { - token: string; - email: string; - expiresAt: Date; - lastQuoteId?: string; -} - -@Injectable() -export class SessionService { - private readonly logger = new Logger(SessionService.name); - private sessions: Map = new Map(); - private authUrl: string; - - constructor(private configService: ConfigService) { - this.authUrl = this.configService.get('auth.url') || 'http://localhost:3001'; - } - - async login( - matrixUserId: string, - email: string, - password: string - ): Promise<{ success: boolean; error?: string }> { - try { - const response = await fetch(`${this.authUrl}/api/v1/auth/login`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ email, password }), - }); - - if (!response.ok) { - const errorData = await response.json().catch(() => ({})); - return { - success: false, - error: errorData.message || 'Authentifizierung fehlgeschlagen', - }; - } - - const data = await response.json(); - const token = data.accessToken || data.token; - - if (!token) { - return { success: false, error: 'Kein Token erhalten' }; - } - - // Store session (7 days expiry) - this.sessions.set(matrixUserId, { - token, - email, - expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), - }); - - this.logger.log(`User ${matrixUserId} logged in as ${email}`); - return { success: true }; - } catch (error) { - this.logger.error(`Login failed for ${matrixUserId}:`, error); - return { - success: false, - error: 'Verbindung zum Auth-Server fehlgeschlagen', - }; - } - } - - logout(matrixUserId: string): void { - this.sessions.delete(matrixUserId); - this.logger.log(`User ${matrixUserId} logged out`); - } - - getToken(matrixUserId: string): string | null { - const session = this.sessions.get(matrixUserId); - - if (!session) return null; - - // Check if token expired - if (session.expiresAt < new Date()) { - this.sessions.delete(matrixUserId); - return null; - } - - return session.token; - } - - isLoggedIn(matrixUserId: string): boolean { - return this.getToken(matrixUserId) !== null; - } - - setLastQuoteId(matrixUserId: string, quoteId: string): void { - const session = this.sessions.get(matrixUserId); - if (session) { - session.lastQuoteId = quoteId; - } - } - - getLastQuoteId(matrixUserId: string): string | null { - const session = this.sessions.get(matrixUserId); - return session?.lastQuoteId || null; - } - - getSessionCount(): number { - return this.sessions.size; - } - - getLoggedInCount(): number { - const now = new Date(); - let count = 0; - for (const session of this.sessions.values()) { - if (session.expiresAt > now) count++; - } - return count; - } -} diff --git a/services/matrix-zitare-bot/src/transcription/transcription.module.ts b/services/matrix-zitare-bot/src/transcription/transcription.module.ts deleted file mode 100644 index fb5aeeaf1..000000000 --- a/services/matrix-zitare-bot/src/transcription/transcription.module.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TranscriptionService } from './transcription.service'; - -@Module({ - providers: [TranscriptionService], - exports: [TranscriptionService], -}) -export class TranscriptionModule {} diff --git a/services/matrix-zitare-bot/src/transcription/transcription.service.ts b/services/matrix-zitare-bot/src/transcription/transcription.service.ts deleted file mode 100644 index fc5e761c4..000000000 --- a/services/matrix-zitare-bot/src/transcription/transcription.service.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; - -@Injectable() -export class TranscriptionService { - private readonly logger = new Logger(TranscriptionService.name); - private readonly sttUrl: string; - - constructor(private configService: ConfigService) { - this.sttUrl = this.configService.get('stt.url') || 'http://localhost:3020'; - } - - async transcribe(audioBuffer: Buffer, language: string = 'de'): Promise { - try { - const formData = new FormData(); - const blob = new Blob([new Uint8Array(audioBuffer)], { type: 'audio/ogg' }); - formData.append('file', blob, 'audio.ogg'); - formData.append('language', language); - - const response = await fetch(`${this.sttUrl}/transcribe`, { - method: 'POST', - body: formData, - }); - - if (!response.ok) { - throw new Error(`STT service error: ${response.status}`); - } - - const result = (await response.json()) as { text: string }; - this.logger.log(`Transcription result: ${result.text}`); - return result.text; - } catch (error) { - this.logger.error('Transcription failed:', error); - throw error; - } - } -}