listModels method

  1. @override
Future<List<String>> listModels(
  1. String apiKey
)
override

Models suitable for chat / completion, newest first. Returns an empty list for an unset / invalid key. Each provider filters out embeddings / vision / audio-only models so the dropdown isn't flooded with irrelevant entries.

Implementation

@override
Future<List<String>> listModels(String apiKey) async {
  if (apiKey.isEmpty) return const [];
  final ids = <String>{};
  String? pageToken;
  for (var page = 0; page < 5; page++) {
    final query = <String, String>{
      'pageSize': '50',
      if (pageToken != null) 'pageToken': pageToken,
    };
    final uri = Uri.parse('$_baseUrl/models').replace(queryParameters: query);
    final res =
        await _http.get(uri, headers: _authHeaders(apiKey)).timeout(_timeout);
    if (res.statusCode >= 400) return const [];
    final body = jsonDecode(res.body) as Map<String, Object?>;
    final models = body['models'] as List<Object?>? ?? const [];
    for (final m in models) {
      if (m is! Map<String, Object?>) continue;
      final name = m['name'] as String?;
      if (name == null) continue;
      final bare = name.startsWith('models/') ? name.substring(7) : name;
      if (!bare.startsWith('gemini-')) continue;
      final methods =
          (m['supportedGenerationMethods'] as List<Object?>?) ?? const [];
      if (!methods.contains('generateContent')) continue;
      ids.add(bare);
    }
    pageToken = body['nextPageToken'] as String?;
    if (pageToken == null || pageToken.isEmpty) break;
  }
  return ids.toList()..sort((a, b) => b.compareTo(a));
}