listModels method
override
Fetch available models from the provider's API.
Implementation
@override
Future<List<AiModel>> listModels() async {
try {
final token = await _auth.getAccessToken();
// Web: api.openai.com blocks browser requests at the CORS preflight.
// Route through the ai-proxy Edge Function instead.
if (kIsWeb) {
if (token.isEmpty) return const [];
final models = await listModelsViaProxy(
dio: _dio,
provider: 'openai',
credential: token,
);
if (models.isNotEmpty) return models;
return _provider.availableModels
.map((m) => AiModel(id: m.id, name: m.name))
.toList();
}
final response = await _dio.get(
'https://api.openai.com/v1/models',
options: Options(headers: {'Authorization': 'Bearer $token'}),
);
final data = response.data as Map<String, dynamic>;
final models = data['data'] as List<dynamic>;
final result = <AiModel>[];
for (final model in models) {
final m = model as Map<String, dynamic>;
final id = m['id'] as String;
// Filter to chat-compatible models.
if (!id.startsWith('gpt-') &&
!id.startsWith('o1-') &&
!id.startsWith('o3-') &&
!id.startsWith('o4-') &&
!id.startsWith('chatgpt-')) {
continue;
}
// Skip snapshot/dated variants (e.g. gpt-4-0613).
if (RegExp(r'-\d{4}$').hasMatch(id)) continue;
result.add(AiModel(id: id, name: id));
}
result.sort((a, b) => a.id.compareTo(b.id));
return result;
} catch (e) {
dev.log('Failed to list OpenAI models: $e', name: 'OpenAiDatasource');
return _provider.availableModels
.map((m) => AiModel(id: m.id, name: m.name))
.toList();
}
}