AIProviderSelector Impl & AI Models added to RequestModel

This commit is contained in:
Manas Hejmadi
2025-07-09 15:08:06 +05:30
parent 90b4b99135
commit d923996dc8
10 changed files with 159 additions and 7 deletions

View File

@@ -34,6 +34,7 @@ Map<String, dynamic> _$$HistoryMetaModelImplToJson(
const _$APITypeEnumMap = {
APIType.rest: 'rest',
APIType.ai: 'ai',
APIType.graphql: 'graphql',
};

View File

@@ -1,4 +1,5 @@
import 'package:apidash_core/apidash_core.dart';
import 'package:genai/genai.dart';
part 'request_model.freezed.dart';
@@ -25,6 +26,8 @@ class RequestModel with _$RequestModel {
@JsonKey(includeToJson: false) @Default(false) bool isStreaming,
String? preRequestScript,
String? postRequestScript,
AIRequestModel? aiRequestModel,
AIResponseModel? aiResponseModel,
}) = _RequestModel;
factory RequestModel.fromJson(Map<String, Object?> json) =>

View File

@@ -39,6 +39,8 @@ mixin _$RequestModel {
bool get isStreaming => throw _privateConstructorUsedError;
String? get preRequestScript => throw _privateConstructorUsedError;
String? get postRequestScript => throw _privateConstructorUsedError;
AIRequestModel? get aiRequestModel => throw _privateConstructorUsedError;
AIResponseModel? get aiResponseModel => throw _privateConstructorUsedError;
/// Serializes this RequestModel to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@@ -70,10 +72,14 @@ abstract class $RequestModelCopyWith<$Res> {
@JsonKey(includeToJson: false) DateTime? sendingTime,
@JsonKey(includeToJson: false) bool isStreaming,
String? preRequestScript,
String? postRequestScript});
String? postRequestScript,
AIRequestModel? aiRequestModel,
AIResponseModel? aiResponseModel});
$HttpRequestModelCopyWith<$Res>? get httpRequestModel;
$HttpResponseModelCopyWith<$Res>? get httpResponseModel;
$AIRequestModelCopyWith<$Res>? get aiRequestModel;
$AIResponseModelCopyWith<$Res>? get aiResponseModel;
}
/// @nodoc
@@ -105,6 +111,8 @@ class _$RequestModelCopyWithImpl<$Res, $Val extends RequestModel>
Object? isStreaming = null,
Object? preRequestScript = freezed,
Object? postRequestScript = freezed,
Object? aiRequestModel = freezed,
Object? aiResponseModel = freezed,
}) {
return _then(_value.copyWith(
id: null == id
@@ -163,6 +171,14 @@ class _$RequestModelCopyWithImpl<$Res, $Val extends RequestModel>
? _value.postRequestScript
: postRequestScript // ignore: cast_nullable_to_non_nullable
as String?,
aiRequestModel: freezed == aiRequestModel
? _value.aiRequestModel
: aiRequestModel // ignore: cast_nullable_to_non_nullable
as AIRequestModel?,
aiResponseModel: freezed == aiResponseModel
? _value.aiResponseModel
: aiResponseModel // ignore: cast_nullable_to_non_nullable
as AIResponseModel?,
) as $Val);
}
@@ -193,6 +209,34 @@ class _$RequestModelCopyWithImpl<$Res, $Val extends RequestModel>
return _then(_value.copyWith(httpResponseModel: value) as $Val);
});
}
/// Create a copy of RequestModel
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$AIRequestModelCopyWith<$Res>? get aiRequestModel {
if (_value.aiRequestModel == null) {
return null;
}
return $AIRequestModelCopyWith<$Res>(_value.aiRequestModel!, (value) {
return _then(_value.copyWith(aiRequestModel: value) as $Val);
});
}
/// Create a copy of RequestModel
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$AIResponseModelCopyWith<$Res>? get aiResponseModel {
if (_value.aiResponseModel == null) {
return null;
}
return $AIResponseModelCopyWith<$Res>(_value.aiResponseModel!, (value) {
return _then(_value.copyWith(aiResponseModel: value) as $Val);
});
}
}
/// @nodoc
@@ -217,12 +261,18 @@ abstract class _$$RequestModelImplCopyWith<$Res>
@JsonKey(includeToJson: false) DateTime? sendingTime,
@JsonKey(includeToJson: false) bool isStreaming,
String? preRequestScript,
String? postRequestScript});
String? postRequestScript,
AIRequestModel? aiRequestModel,
AIResponseModel? aiResponseModel});
@override
$HttpRequestModelCopyWith<$Res>? get httpRequestModel;
@override
$HttpResponseModelCopyWith<$Res>? get httpResponseModel;
@override
$AIRequestModelCopyWith<$Res>? get aiRequestModel;
@override
$AIResponseModelCopyWith<$Res>? get aiResponseModel;
}
/// @nodoc
@@ -252,6 +302,8 @@ class __$$RequestModelImplCopyWithImpl<$Res>
Object? isStreaming = null,
Object? preRequestScript = freezed,
Object? postRequestScript = freezed,
Object? aiRequestModel = freezed,
Object? aiResponseModel = freezed,
}) {
return _then(_$RequestModelImpl(
id: null == id
@@ -309,6 +361,14 @@ class __$$RequestModelImplCopyWithImpl<$Res>
? _value.postRequestScript
: postRequestScript // ignore: cast_nullable_to_non_nullable
as String?,
aiRequestModel: freezed == aiRequestModel
? _value.aiRequestModel
: aiRequestModel // ignore: cast_nullable_to_non_nullable
as AIRequestModel?,
aiResponseModel: freezed == aiResponseModel
? _value.aiResponseModel
: aiResponseModel // ignore: cast_nullable_to_non_nullable
as AIResponseModel?,
));
}
}
@@ -331,7 +391,9 @@ class _$RequestModelImpl implements _RequestModel {
@JsonKey(includeToJson: false) this.sendingTime,
@JsonKey(includeToJson: false) this.isStreaming = false,
this.preRequestScript,
this.postRequestScript});
this.postRequestScript,
this.aiRequestModel,
this.aiResponseModel});
factory _$RequestModelImpl.fromJson(Map<String, dynamic> json) =>
_$$RequestModelImplFromJson(json);
@@ -371,10 +433,14 @@ class _$RequestModelImpl implements _RequestModel {
final String? preRequestScript;
@override
final String? postRequestScript;
@override
final AIRequestModel? aiRequestModel;
@override
final AIResponseModel? aiResponseModel;
@override
String toString() {
return 'RequestModel(id: $id, apiType: $apiType, name: $name, description: $description, requestTabIndex: $requestTabIndex, httpRequestModel: $httpRequestModel, responseStatus: $responseStatus, message: $message, httpResponseModel: $httpResponseModel, isWorking: $isWorking, sendingTime: $sendingTime, isStreaming: $isStreaming, preRequestScript: $preRequestScript, postRequestScript: $postRequestScript)';
return 'RequestModel(id: $id, apiType: $apiType, name: $name, description: $description, requestTabIndex: $requestTabIndex, httpRequestModel: $httpRequestModel, responseStatus: $responseStatus, message: $message, httpResponseModel: $httpResponseModel, isWorking: $isWorking, sendingTime: $sendingTime, isStreaming: $isStreaming, preRequestScript: $preRequestScript, postRequestScript: $postRequestScript, aiRequestModel: $aiRequestModel, aiResponseModel: $aiResponseModel)';
}
@override
@@ -405,7 +471,11 @@ class _$RequestModelImpl implements _RequestModel {
(identical(other.preRequestScript, preRequestScript) ||
other.preRequestScript == preRequestScript) &&
(identical(other.postRequestScript, postRequestScript) ||
other.postRequestScript == postRequestScript));
other.postRequestScript == postRequestScript) &&
(identical(other.aiRequestModel, aiRequestModel) ||
other.aiRequestModel == aiRequestModel) &&
(identical(other.aiResponseModel, aiResponseModel) ||
other.aiResponseModel == aiResponseModel));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -425,7 +495,9 @@ class _$RequestModelImpl implements _RequestModel {
sendingTime,
isStreaming,
preRequestScript,
postRequestScript);
postRequestScript,
aiRequestModel,
aiResponseModel);
/// Create a copy of RequestModel
/// with the given fields replaced by the non-null parameter values.
@@ -458,7 +530,9 @@ abstract class _RequestModel implements RequestModel {
@JsonKey(includeToJson: false) final DateTime? sendingTime,
@JsonKey(includeToJson: false) final bool isStreaming,
final String? preRequestScript,
final String? postRequestScript}) = _$RequestModelImpl;
final String? postRequestScript,
final AIRequestModel? aiRequestModel,
final AIResponseModel? aiResponseModel}) = _$RequestModelImpl;
factory _RequestModel.fromJson(Map<String, dynamic> json) =
_$RequestModelImpl.fromJson;
@@ -495,6 +569,10 @@ abstract class _RequestModel implements RequestModel {
String? get preRequestScript;
@override
String? get postRequestScript;
@override
AIRequestModel? get aiRequestModel;
@override
AIResponseModel? get aiResponseModel;
/// Create a copy of RequestModel
/// with the given fields replaced by the non-null parameter values.

View File

@@ -30,6 +30,14 @@ _$RequestModelImpl _$$RequestModelImplFromJson(Map json) => _$RequestModelImpl(
isStreaming: json['isStreaming'] as bool? ?? false,
preRequestScript: json['preRequestScript'] as String?,
postRequestScript: json['postRequestScript'] as String?,
aiRequestModel: json['aiRequestModel'] == null
? null
: AIRequestModel.fromJson(
Map<String, Object?>.from(json['aiRequestModel'] as Map)),
aiResponseModel: json['aiResponseModel'] == null
? null
: AIResponseModel.fromJson(
Map<String, Object?>.from(json['aiResponseModel'] as Map)),
);
Map<String, dynamic> _$$RequestModelImplToJson(_$RequestModelImpl instance) =>
@@ -44,9 +52,12 @@ Map<String, dynamic> _$$RequestModelImplToJson(_$RequestModelImpl instance) =>
'httpResponseModel': instance.httpResponseModel?.toJson(),
'preRequestScript': instance.preRequestScript,
'postRequestScript': instance.postRequestScript,
'aiRequestModel': instance.aiRequestModel?.toJson(),
'aiResponseModel': instance.aiResponseModel?.toJson(),
};
const _$APITypeEnumMap = {
APIType.rest: 'rest',
APIType.ai: 'ai',
APIType.graphql: 'graphql',
};

View File

@@ -3,6 +3,8 @@ import 'package:apidash_core/apidash_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:apidash/consts.dart';
import 'package:genai/genai.dart';
import 'package:genai/models/ai_request_model.dart';
import 'providers.dart';
import '../models/models.dart';
import '../services/services.dart';
@@ -226,6 +228,8 @@ class CollectionStateNotifier
HttpResponseModel? httpResponseModel,
String? preRequestScript,
String? postRequestScript,
AIRequestModel? aiRequestModel,
AIResponseModel? aiResponseModel,
}) {
final rId = id ?? ref.read(selectedIdStateProvider);
if (rId == null) {
@@ -260,6 +264,8 @@ class CollectionStateNotifier
httpResponseModel: httpResponseModel ?? currentModel.httpResponseModel,
preRequestScript: preRequestScript ?? currentModel.preRequestScript,
postRequestScript: postRequestScript ?? currentModel.postRequestScript,
aiRequestModel: aiRequestModel ?? currentModel.aiRequestModel,
aiResponseModel: aiResponseModel ?? currentModel.aiResponseModel,
);
var map = {...state!};

View File

@@ -4,6 +4,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:apidash/providers/providers.dart';
import 'package:apidash/widgets/widgets.dart';
import 'package:genai/genai.dart';
import 'package:genai/widgets/llm_selector.dart';
import '../../common_widgets/common_widgets.dart';
class EditorPaneRequestURLCard extends ConsumerWidget {
@@ -35,6 +37,7 @@ class EditorPaneRequestURLCard extends ConsumerWidget {
switch (apiType) {
APIType.rest => const DropdownButtonHTTPMethod(),
APIType.graphql => kSizedBoxEmpty,
APIType.ai => const AIProviderSelector(),
null => kSizedBoxEmpty,
},
switch (apiType) {
@@ -51,6 +54,7 @@ class EditorPaneRequestURLCard extends ConsumerWidget {
switch (apiType) {
APIType.rest => const DropdownButtonHTTPMethod(),
APIType.graphql => kSizedBoxEmpty,
APIType.ai => const AIProviderSelector(),
null => kSizedBoxEmpty,
},
switch (apiType) {
@@ -145,3 +149,48 @@ class SendRequestButton extends ConsumerWidget {
);
}
}
class AIProviderSelector extends ConsumerWidget {
const AIProviderSelector({
super.key,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final selectedId = ref.watch(selectedIdStateProvider);
final req = ref.watch(collectionStateNotifierProvider)![selectedId]!;
final aiRequestModel = req.aiRequestModel;
final defaultLLMSO = aiRequestModel == null
? ref
.read(settingsProvider.notifier)
.settingsModel
?.defaultLLMSaveObject
: LLMSaveObject(
endpoint: aiRequestModel.payload.endpoint,
credential: aiRequestModel.payload.credential,
configMap: aiRequestModel.payload.configMap,
selectedLLM: aiRequestModel.model,
provider: aiRequestModel.provider,
);
return DefaultLLMSelectorButton(
key: ValueKey(ref.watch(selectedIdStateProvider)),
defaultLLM: defaultLLMSO,
onDefaultLLMUpdated: (llmso) {
ref.read(collectionStateNotifierProvider.notifier).update(
aiRequestModel: AIRequestModel(
model: llmso.selectedLLM,
provider: llmso.provider,
payload: LLMInputPayload(
endpoint: llmso.endpoint,
credential: llmso.credential,
systemPrompt: aiRequestModel?.payload.systemPrompt ?? '',
userPrompt: aiRequestModel?.payload.userPrompt ?? '',
configMap: llmso.configMap,
),
),
);
},
);
}
}

View File

@@ -36,6 +36,7 @@ Color getAPIColor(
method,
),
APIType.graphql => kColorGQL,
APIType.ai => Colors.amber,
};
if (brightness == Brightness.dark) {
col = col.toDark;

View File

@@ -20,6 +20,7 @@ class SidebarRequestCardTextBox extends StatelessWidget {
switch (apiType) {
APIType.rest => method.abbr,
APIType.graphql => apiType.abbr,
APIType.ai => apiType.abbr,
},
textAlign: TextAlign.center,
style: TextStyle(

View File

@@ -2,6 +2,7 @@ import 'dart:convert';
enum APIType {
rest("HTTP", "HTTP"),
ai("AI", "AI"),
graphql("GraphQL", "GQL");
const APIType(this.label, this.abbr);

View File

@@ -93,6 +93,7 @@ String? getRequestBody(APIType type, HttpRequestModel httpRequestModel) {
? httpRequestModel.body
: null,
APIType.graphql => getGraphQLBody(httpRequestModel),
APIType.ai => null, //TODO: TAKE A LOOK
};
}