feat(ai-scribe): Improve data & domain layer for ai scribe
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import 'package:scribe/scribe/ai/domain/model/ai_response.dart';
|
||||
|
||||
abstract class AIDataSource {
|
||||
Future<AIResponse> request(String prompt);
|
||||
Future<AIResponse> generateMessage(String prompt);
|
||||
}
|
||||
|
||||
@@ -1,34 +1,17 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:scribe/scribe/ai/data/datasource/ai_datasource.dart';
|
||||
import 'package:scribe/scribe/ai/data/model/ai_message.dart';
|
||||
import 'package:scribe/scribe/ai/data/model/ai_api_request.dart';
|
||||
import 'package:scribe/scribe/ai/data/network/ai_api.dart';
|
||||
import 'package:scribe/scribe/ai/domain/model/ai_response.dart';
|
||||
|
||||
class AIDataSourceImpl implements AIDataSource {
|
||||
final AIApi _aiApi;
|
||||
|
||||
AIDataSourceImpl({
|
||||
required Dio dio,
|
||||
String? endpoint,
|
||||
}) : _aiApi = AIApi(
|
||||
dio: dio,
|
||||
endpoint: endpoint,
|
||||
);
|
||||
AIDataSourceImpl(this._aiApi);
|
||||
|
||||
@override
|
||||
Future<AIResponse> request(String prompt) async {
|
||||
Future<AIResponse> generateMessage(String prompt) async {
|
||||
try {
|
||||
final aiRequest = AIAPIRequest(
|
||||
messages: [
|
||||
AIMessage(
|
||||
role: 'user',
|
||||
content: prompt,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final apiResponse = await _aiApi.chatCompletion(aiRequest);
|
||||
final apiResponse = await _aiApi.generateMessage(prompt);
|
||||
return AIResponse(result: apiResponse.content);
|
||||
} on DioError catch (e) {
|
||||
throw Exception('Failed to generate AI text: ${e.message}');
|
||||
|
||||
@@ -12,7 +12,13 @@ class AIMessage {
|
||||
required this.content,
|
||||
});
|
||||
|
||||
factory AIMessage.fromJson(Map<String, dynamic> json) => _$AIMessageFromJson(json);
|
||||
factory AIMessage.fromJson(Map<String, dynamic> json) =>
|
||||
_$AIMessageFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$AIMessageToJson(this);
|
||||
|
||||
factory AIMessage.ofUser(String content) => AIMessage(
|
||||
role: 'user',
|
||||
content: content,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,30 +1,22 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:scribe/scribe/ai/data/model/ai_api_response.dart';
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:scribe/scribe/ai/data/model/ai_api_request.dart';
|
||||
import 'package:scribe/scribe/ai/data/model/ai_api_response.dart';
|
||||
import 'package:scribe/scribe/ai/data/model/ai_message.dart';
|
||||
import 'package:scribe/scribe/ai/data/network/ai_api_exception.dart';
|
||||
|
||||
class AIApi {
|
||||
final Dio _dio;
|
||||
final String? _endpoint;
|
||||
final DioClient _dioClient;
|
||||
final String aiEndpoint;
|
||||
|
||||
AIApi({
|
||||
required Dio dio,
|
||||
String? endpoint,
|
||||
}) : _dio = dio,
|
||||
_endpoint = endpoint;
|
||||
AIApi(this._dioClient, this.aiEndpoint);
|
||||
|
||||
Future<AIApiResponse> chatCompletion(
|
||||
AIAPIRequest request
|
||||
) async {
|
||||
final url = _endpoint;
|
||||
Future<AIApiResponse> generateMessage(String prompt) async {
|
||||
final aiRequest = _generateRequest(prompt);
|
||||
|
||||
if (url == null) {
|
||||
throw AIApiNotAvailableException();
|
||||
}
|
||||
|
||||
final response = await _dio.post(
|
||||
url,
|
||||
data: request.toJson(),
|
||||
final response = await _dioClient.post(
|
||||
aiEndpoint,
|
||||
data: aiRequest.toJson(),
|
||||
useJMAPHeader: false,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
@@ -39,4 +31,8 @@ class AIApi {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AIAPIRequest _generateRequest(String prompt) {
|
||||
return AIAPIRequest(messages: [AIMessage.ofUser(prompt)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ import 'package:scribe/scribe/ai/domain/model/ai_response.dart';
|
||||
import 'package:scribe/scribe/ai/domain/repository/ai_scribe_repository.dart';
|
||||
|
||||
class AIScribeRepositoryImpl implements AIScribeRepository {
|
||||
final AIDataSource _dataSource;
|
||||
final AIDataSource _aiDataSource;
|
||||
|
||||
AIScribeRepositoryImpl(this._dataSource);
|
||||
AIScribeRepositoryImpl(this._aiDataSource);
|
||||
|
||||
@override
|
||||
Future<AIResponse> generateText(String prompt) async {
|
||||
return _dataSource.request(prompt);
|
||||
Future<AIResponse> generateMessage(String prompt) {
|
||||
return _aiDataSource.generateMessage(prompt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:scribe/scribe/ai/domain/model/ai_response.dart';
|
||||
|
||||
abstract class AIScribeRepository {
|
||||
Future<AIResponse> generateText(String prompt);
|
||||
Future<AIResponse> generateMessage(String prompt);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:core/presentation/state/failure.dart';
|
||||
import 'package:core/presentation/state/success.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:scribe/scribe/ai/domain/constants/ai_prompts.dart';
|
||||
import 'package:scribe/scribe/ai/domain/repository/ai_scribe_repository.dart';
|
||||
@@ -17,9 +18,8 @@ class GenerateAITextInteractor {
|
||||
) async {
|
||||
try {
|
||||
final prompt = AIPrompts.buildPrompt(action, selectedText);
|
||||
|
||||
final response = await _repository.generateText(prompt);
|
||||
|
||||
log('$runtimeType::execute():prompt: $prompt');
|
||||
final response = await _repository.generateMessage(prompt);
|
||||
return Right(GenerateAITextSuccess(response));
|
||||
} catch (e) {
|
||||
return Left(GenerateAITextFailure(e));
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:core/core.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:scribe/scribe/ai/data/datasource/ai_datasource.dart';
|
||||
import 'package:scribe/scribe/ai/data/datasource_impl/ai_datasource_impl.dart';
|
||||
import 'package:scribe/scribe/ai/data/network/ai_api.dart';
|
||||
import 'package:scribe/scribe/ai/data/repository/ai_repository_impl.dart';
|
||||
import 'package:scribe/scribe/ai/domain/repository/ai_scribe_repository.dart';
|
||||
import 'package:scribe/scribe/ai/domain/usecases/generate_ai_text_interactor.dart';
|
||||
|
||||
class AIScribeBindings extends Bindings {
|
||||
final String? scribeEndpoint;
|
||||
|
||||
AIScribeBindings({this.scribeEndpoint});
|
||||
final String aiEndpoint;
|
||||
|
||||
AIScribeBindings(this.aiEndpoint);
|
||||
|
||||
@override
|
||||
void dependencies() {
|
||||
_bindingsAPI();
|
||||
_bindingsDataSourceImpl();
|
||||
_bindingsDataSource();
|
||||
_bindingsRepositoryImpl();
|
||||
@@ -20,11 +23,12 @@ class AIScribeBindings extends Bindings {
|
||||
_bindingsInteractor();
|
||||
}
|
||||
|
||||
void _bindingsAPI() {
|
||||
Get.lazyPut<AIApi>(() => AIApi(Get.find<DioClient>(), aiEndpoint));
|
||||
}
|
||||
|
||||
void _bindingsDataSourceImpl() {
|
||||
Get.lazyPut<AIDataSourceImpl>(() => AIDataSourceImpl(
|
||||
dio: Get.find<Dio>(),
|
||||
endpoint: scribeEndpoint,
|
||||
));
|
||||
Get.lazyPut<AIDataSourceImpl>(() => AIDataSourceImpl(Get.find<AIApi>()));
|
||||
}
|
||||
|
||||
void _bindingsDataSource() {
|
||||
@@ -32,9 +36,9 @@ class AIScribeBindings extends Bindings {
|
||||
}
|
||||
|
||||
void _bindingsRepositoryImpl() {
|
||||
Get.lazyPut<AIScribeRepositoryImpl>(() => AIScribeRepositoryImpl(
|
||||
Get.find<AIDataSource>(),
|
||||
));
|
||||
Get.lazyPut<AIScribeRepositoryImpl>(
|
||||
() => AIScribeRepositoryImpl(Get.find<AIDataSource>()),
|
||||
);
|
||||
}
|
||||
|
||||
void _bindingsRepository() {
|
||||
@@ -42,8 +46,8 @@ class AIScribeBindings extends Bindings {
|
||||
}
|
||||
|
||||
void _bindingsInteractor() {
|
||||
Get.lazyPut<GenerateAITextInteractor>(() => GenerateAITextInteractor(
|
||||
Get.find<AIScribeRepository>(),
|
||||
));
|
||||
Get.lazyPut<GenerateAITextInteractor>(
|
||||
() => GenerateAITextInteractor(Get.find<AIScribeRepository>()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ class AICapability extends CapabilityProperties {
|
||||
|
||||
factory AICapability.deserialize(Map<String, dynamic> json) => _$AICapabilityFromJson(json);
|
||||
|
||||
bool get isScribeEndpointAvailable => scribeEndpoint?.trim().isNotEmpty == true;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [scribeEndpoint];
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ class _AiScribeSuggestionWidgetModalState
|
||||
}
|
||||
}
|
||||
|
||||
void _getAiSuggestion(
|
||||
Future<void> _getAiSuggestion(
|
||||
GenerateAITextInteractor interactor,
|
||||
AIAction action,
|
||||
String? content,
|
||||
|
||||
Reference in New Issue
Block a user