import 'dart:convert'; sealed class WebSocketMessage { const WebSocketMessage(); Map toJson(); String toJsonString() => jsonEncode(toJson()); } final class AudioMessage extends WebSocketMessage { const AudioMessage({required this.data}); final String data; @override Map toJson() => {'type': 'audio', 'data': data}; } final class TranscribeMessage extends WebSocketMessage { const TranscribeMessage(); @override Map toJson() => {'type': 'transcribe'}; } final class ClearMessage extends WebSocketMessage { const ClearMessage(); @override Map toJson() => {'type': 'clear'}; } final class FinalizeMessage extends WebSocketMessage { const FinalizeMessage(); @override Map toJson() => {'type': 'finalize'}; } sealed class ServerMessage { const ServerMessage(); static ServerMessage fromJson(Map json) { final type = json['type'] as String?; switch (type) { case 'connected': return ConnectedMessage( model: json['model'] as Map? ?? const {}, ); case 'partial': return PartialMessage( text: json['text'] as String? ?? '', seq: json['seq'] as int? ?? 0, ); case 'utterance': return UtteranceMessage( text: json['text'] as String? ?? '', seq: json['seq'] as int? ?? 0, ); case 'reply': return ReplyMessage( text: json['text'] as String? ?? '', ); case 'reply_partial': return ReplyPartialMessage( text: json['text'] as String? ?? '', ); case 'cleared': return const ClearedMessage(); case 'error': return ErrorMessage( message: json['message'] as String? ?? 'Unknown error', ); default: return ErrorMessage(message: 'Unknown message type: $type'); } } static ServerMessage fromJsonString(String source) { try { final json = jsonDecode(source) as Map; return fromJson(json); } on FormatException catch (e) { return ErrorMessage(message: 'Invalid JSON: $e'); } } } final class ConnectedMessage extends ServerMessage { const ConnectedMessage({required this.model}); final Map model; } final class PartialMessage extends ServerMessage { const PartialMessage({required this.text, this.seq = 0}); final String text; final int seq; } final class UtteranceMessage extends ServerMessage { const UtteranceMessage({required this.text, this.seq = 0}); final String text; final int seq; } final class ReplyMessage extends ServerMessage { const ReplyMessage({required this.text}); final String text; } final class ReplyPartialMessage extends ServerMessage { const ReplyPartialMessage({required this.text}); final String text; } final class ClearedMessage extends ServerMessage { const ClearedMessage(); } final class ErrorMessage extends ServerMessage { const ErrorMessage({required this.message}); final String message; }