import '../http_util.dart'; import '../models.dart'; import 'base_provider.dart'; import 'openai_compat.dart'; /// Python `KiloCode` — OpenAI-compat gateway, no key for `kilo-auto/free`. class KiloCode extends OpenAiCompatProvider { KiloCode() : super( providerName: 'KiloCode', apiBase: 'https://api.kilo.ai/api/gateway', fallbackModel: 'kilo-auto/free', supportedModels: const ['kilo-auto/free', 'kilo-auto'], ); @override String get url => 'https://kilo.ai'; } /// Python `OpenCode` — `https://opencode.ai/zen/v1`, default `big-pickle`. class OpenCode extends OpenAiCompatProvider { OpenCode() : super( providerName: 'OpenCode', apiBase: 'https://opencode.ai/zen/v1', fallbackModel: 'big-pickle', supportedModels: const ['big-pickle'], ); @override String get url => 'https://opencode.ai'; } /// Python `G4FSpace` / `ClientFactory("default")`. /// Anonymous calls currently return 402 cake-credits; still tried so a baked /// session cookie or future free window works without a code change. class G4FSpace extends BaseProvider { @override String get name => 'G4FSpace'; @override String get url => 'https://g4f.space'; @override bool get working => true; @override List get models => const ['auto', 'gpt-4o', 'openai']; @override String get defaultModel => 'auto'; static const _bases = [ 'https://g4f.space/api/auto', 'https://g4f.space/api/pollinations', 'https://g4f.space/v1', ]; @override Stream createAsyncGenerator( String model, List messages, { bool stream = false, }) async* { final errors = []; for (final base in _bases) { try { final inner = OpenAiCompatProvider( providerName: 'G4FSpace', apiBase: base, fallbackModel: model.isEmpty ? defaultModel : model, supportedModels: models, ); final text = await inner .complete(model.isEmpty ? defaultModel : model, messages) .timeout(requestTimeout); if (looksLikeModelOutput(text)) { yield text; return; } errors.add('$base unusable'); } catch (e) { errors.add('$base: $e'); } } throw Exception('G4FSpace failed: ${errors.join(' | ')}'); } }