import 'dart:convert'; import '../http_client.dart'; import '../http_util.dart'; import '../models.dart'; import '../sse.dart'; import 'base_provider.dart'; /// Port of g4f.Provider.You (default youchat mode, no login). class YouChat extends BaseProvider { @override String get name => 'You'; @override bool get working => true; @override List get models => ['gpt-3.5-turbo', 'gpt-4o']; @override String get defaultModel => 'gpt-3.5-turbo'; @override Stream createAsyncGenerator( String model, List messages, { bool stream = false, }) async* { final res = await g4fHttp .post( Uri.parse('https://you.com/api/streamingSearch'), headers: browserHeaders( origin: 'https://you.com', referer: 'https://you.com/search?fromSearchBar=true&tbm=youchat', accept: 'text/event-stream', ), body: { 'q': formatPrompt(messages), 'domain': 'youchat', 'selectedChatMode': 'default', 'chat': '[]', }, ) .timeout(requestTimeout); if (res.statusCode != 200) { throw Exception('You ${res.statusCode}'); } final raw = res.body; final buf = StringBuffer(); String? event; for (final line in raw.split(RegExp(r'\r?\n'))) { if (line.startsWith('event:')) { event = line.substring(6).trim(); } else if (line.startsWith('data:')) { final dataStr = line.substring(5).trim(); try { final data = jsonDecode(dataStr); if (data is Map) { if (event == 'youChatToken' && data['youChatToken'] is String) { buf.write(data['youChatToken']); } else if (event == 'youChatUpdate' && data['t'] is String) { buf.write(data['t']); } } } catch (_) {} } } var text = buf.toString().trim(); if (!looksLikeModelOutput(text)) { text = extractAllSseContent(raw).join().trim(); } if (!looksLikeModelOutput(text)) throw Exception('You empty'); yield text; } }