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.
48 lines
1.4 KiB
Dart
48 lines
1.4 KiB
Dart
import 'http_client.dart';
|
|
import 'http_util.dart';
|
|
import 'models.dart';
|
|
import 'providers/base_provider.dart';
|
|
|
|
/// Port of g4f `IterListProvider`: try each provider until one returns content.
|
|
class IterListProvider {
|
|
IterListProvider(this.providers);
|
|
|
|
final List<BaseProvider> providers;
|
|
|
|
Future<String> create({
|
|
required List<Message> messages,
|
|
String? model,
|
|
}) async {
|
|
final exceptions = <String, Object>{};
|
|
final ordered = [
|
|
...providers.where((p) => p.working && !p.isWebView),
|
|
...providers.where((p) => p.working && p.isWebView),
|
|
];
|
|
|
|
for (final provider in ordered) {
|
|
final alias = provider.resolveModel(model);
|
|
try {
|
|
await warmupOrigin(provider.url);
|
|
final result = await provider.complete(alias, messages);
|
|
if (looksLikeModelOutput(result)) {
|
|
return result.trim();
|
|
}
|
|
exceptions[provider.name] = 'unusable text (${result.trim().length} chars)';
|
|
} catch (e) {
|
|
exceptions[provider.name] = e;
|
|
print('Provider ${provider.name} failed: $e');
|
|
}
|
|
}
|
|
|
|
if (exceptions.isEmpty) {
|
|
throw Exception('No G4F providers available.');
|
|
}
|
|
if (exceptions.length == 1) {
|
|
throw Exception('${exceptions.keys.first}: ${exceptions.values.first}');
|
|
}
|
|
throw Exception(
|
|
'RetryProvider failed:\n${exceptions.entries.map((e) => '${e.key}: ${e.value}').join('\n')}',
|
|
);
|
|
}
|
|
}
|