fbf04d90db
Port the Oracle off the Python g4f container onto on-device providers: Chromium HTTP via Cronet, a shared cookie session, IterList retry, hosted OpenAI-compat aggregators, and same-origin WebView fallbacks instead of CORS fetch.
77 lines
2.1 KiB
Dart
77 lines
2.1 KiB
Dart
import 'dart:convert';
|
|
import 'package:http/http.dart' as http;
|
|
import '../http_client.dart';
|
|
import '../http_util.dart';
|
|
import '../models.dart';
|
|
import 'base_provider.dart';
|
|
|
|
/// Faithful port of `g4f.Provider.Yqcloud`.
|
|
class Yqcloud extends BaseProvider {
|
|
@override
|
|
String get name => 'Yqcloud';
|
|
|
|
@override
|
|
String get url => 'https://chat9.yqcloud.top';
|
|
|
|
@override
|
|
bool get working => true;
|
|
|
|
@override
|
|
List<String> get models => const ['gpt-4'];
|
|
|
|
@override
|
|
String get defaultModel => 'gpt-4';
|
|
|
|
@override
|
|
Map<String, String> get modelAliases => const {
|
|
G4FModels.gpt4o: 'gpt-4',
|
|
G4FModels.gpt4oMini: 'gpt-4',
|
|
};
|
|
|
|
static const _endpoint = 'https://api.binjie.fun/api/generateStream';
|
|
|
|
@override
|
|
Stream<String> createAsyncGenerator(
|
|
String model,
|
|
List<Message> messages, {
|
|
bool stream = false,
|
|
}) async* {
|
|
final systemMessage = extractSystemMessage(messages);
|
|
final history = [
|
|
for (final m in messages)
|
|
if (m.role != Role.system) m,
|
|
];
|
|
final prompt = formatPrompt(history, includeSystem: false);
|
|
final userId = '#/chat/${DateTime.now().millisecondsSinceEpoch}';
|
|
|
|
final req = http.Request('POST', Uri.parse(_endpoint));
|
|
req.headers.addAll({
|
|
'accept': 'application/json, text/plain, */*',
|
|
'accept-language': 'en-US,en;q=0.9',
|
|
'content-type': 'application/json',
|
|
'origin': url,
|
|
'referer': '$url/',
|
|
'user-agent': kDesktopUserAgent,
|
|
});
|
|
req.body = jsonEncode({
|
|
'prompt': prompt,
|
|
'userId': userId,
|
|
'network': true,
|
|
'system': systemMessage,
|
|
'withoutContext': false,
|
|
'stream': true,
|
|
});
|
|
|
|
final response = await g4fHttp.send(req).timeout(requestTimeout);
|
|
if (response.statusCode != 200) {
|
|
final err = await response.stream.bytesToString();
|
|
throw Exception('$name returned ${response.statusCode}: $err');
|
|
}
|
|
final fullText = utf8.decode(await response.stream.toBytes()).trim();
|
|
if (!looksLikeModelOutput(fullText) || fullText.contains('Error:')) {
|
|
throw Exception('$name unusable body');
|
|
}
|
|
yield fullText;
|
|
}
|
|
}
|