Add default AI model selection to settings

Replaces the previous placeholder for default LLM selection with a working default AI model selector in settings. Updates SettingsModel and related providers to support storing and updating the default AI model as a JSON object. Integrates the selector UI and ensures new AI requests use the default model if set.
This commit is contained in:
Ankit Mahato
2025-08-29 01:27:32 +05:30
parent 7b7daa7dac
commit 9d50e3f09c
6 changed files with 41 additions and 48 deletions

View File

@@ -18,8 +18,7 @@ class SettingsModel {
this.workspaceFolderPath, this.workspaceFolderPath,
this.isSSLDisabled = false, this.isSSLDisabled = false,
this.isDashBotEnabled = true, this.isDashBotEnabled = true,
// TODO: Fix it this.defaultAIModel,
// this.defaultLLMSaveObject,
}); });
final bool isDark; final bool isDark;
@@ -35,8 +34,7 @@ class SettingsModel {
final String? workspaceFolderPath; final String? workspaceFolderPath;
final bool isSSLDisabled; final bool isSSLDisabled;
final bool isDashBotEnabled; final bool isDashBotEnabled;
// TODO: Fix it final Map<String, Object?>? defaultAIModel;
// final LLMSaveObject? defaultLLMSaveObject;
SettingsModel copyWith({ SettingsModel copyWith({
bool? isDark, bool? isDark,
@@ -52,9 +50,7 @@ class SettingsModel {
String? workspaceFolderPath, String? workspaceFolderPath,
bool? isSSLDisabled, bool? isSSLDisabled,
bool? isDashBotEnabled, bool? isDashBotEnabled,
// TODO: Fix it Map<String, Object?>? defaultAIModel,
// LLMSaveObject? def,
// LLMSaveObject? defaultLLMSaveObject,
}) { }) {
return SettingsModel( return SettingsModel(
isDark: isDark ?? this.isDark, isDark: isDark ?? this.isDark,
@@ -72,8 +68,7 @@ class SettingsModel {
workspaceFolderPath: workspaceFolderPath ?? this.workspaceFolderPath, workspaceFolderPath: workspaceFolderPath ?? this.workspaceFolderPath,
isSSLDisabled: isSSLDisabled ?? this.isSSLDisabled, isSSLDisabled: isSSLDisabled ?? this.isSSLDisabled,
isDashBotEnabled: isDashBotEnabled ?? this.isDashBotEnabled, isDashBotEnabled: isDashBotEnabled ?? this.isDashBotEnabled,
// TODO: Fix it defaultAIModel: defaultAIModel ?? this.defaultAIModel,
// defaultLLMSaveObject: defaultLLMSaveObject ?? this.defaultLLMSaveObject,
); );
} }
@@ -94,8 +89,7 @@ class SettingsModel {
workspaceFolderPath: workspaceFolderPath, workspaceFolderPath: workspaceFolderPath,
isSSLDisabled: isSSLDisabled, isSSLDisabled: isSSLDisabled,
isDashBotEnabled: isDashBotEnabled, isDashBotEnabled: isDashBotEnabled,
// TODO: Fix it defaultAIModel: defaultAIModel,
// defaultLLMSaveObject: defaultLLMSaveObject,
); );
} }
@@ -151,14 +145,7 @@ class SettingsModel {
final workspaceFolderPath = data["workspaceFolderPath"] as String?; final workspaceFolderPath = data["workspaceFolderPath"] as String?;
final isSSLDisabled = data["isSSLDisabled"] as bool?; final isSSLDisabled = data["isSSLDisabled"] as bool?;
final isDashBotEnabled = data["isDashBotEnabled"] as bool?; final isDashBotEnabled = data["isDashBotEnabled"] as bool?;
final defaultAIModel = data["defaultAIModel"] as Map<String, Object?>?;
// TODO: Fix it
// LLMSaveObject? defaultLLMSaveObject;
// if (data["defaultLLMSaveObject"] != null) {
// defaultLLMSaveObject =
// LLMSaveObject.fromJSON(data["defaultLLMSaveObject"]);
// }
const sm = SettingsModel(); const sm = SettingsModel();
return sm.copyWith( return sm.copyWith(
@@ -176,8 +163,7 @@ class SettingsModel {
workspaceFolderPath: workspaceFolderPath, workspaceFolderPath: workspaceFolderPath,
isSSLDisabled: isSSLDisabled, isSSLDisabled: isSSLDisabled,
isDashBotEnabled: isDashBotEnabled, isDashBotEnabled: isDashBotEnabled,
// TODO: Fix it defaultAIModel: defaultAIModel,
// defaultLLMSaveObject: defaultLLMSaveObject,
); );
} }
@@ -198,8 +184,7 @@ class SettingsModel {
"workspaceFolderPath": workspaceFolderPath, "workspaceFolderPath": workspaceFolderPath,
"isSSLDisabled": isSSLDisabled, "isSSLDisabled": isSSLDisabled,
"isDashBotEnabled": isDashBotEnabled, "isDashBotEnabled": isDashBotEnabled,
// TODO: Fix it 'defaultLLMSaveObject': defaultAIModel,
// 'defaultLLMSaveObject': defaultLLMSaveObject?.toJSON(),
}; };
} }
@@ -225,10 +210,8 @@ class SettingsModel {
other.historyRetentionPeriod == historyRetentionPeriod && other.historyRetentionPeriod == historyRetentionPeriod &&
other.workspaceFolderPath == workspaceFolderPath && other.workspaceFolderPath == workspaceFolderPath &&
other.isSSLDisabled == isSSLDisabled && other.isSSLDisabled == isSSLDisabled &&
other.isDashBotEnabled == isDashBotEnabled; other.isDashBotEnabled == isDashBotEnabled &&
// TODO: Fix it other.defaultAIModel == defaultAIModel;
// &&
// other.defaultLLMSaveObject == defaultLLMSaveObject;
} }
@override @override
@@ -248,8 +231,7 @@ class SettingsModel {
workspaceFolderPath, workspaceFolderPath,
isSSLDisabled, isSSLDisabled,
isDashBotEnabled, isDashBotEnabled,
// TODO: Fix it defaultAIModel,
// defaultLLMSaveObject,
); );
} }
} }

View File

@@ -245,6 +245,7 @@ class CollectionStateNotifier
RequestModel newModel; RequestModel newModel;
if (apiType != null && currentModel.apiType != apiType) { if (apiType != null && currentModel.apiType != apiType) {
final defaultModel = ref.read(settingsProvider).defaultAIModel;
newModel = switch (apiType) { newModel = switch (apiType) {
APIType.rest || APIType.graphql => currentModel.copyWith( APIType.rest || APIType.graphql => currentModel.copyWith(
apiType: apiType, apiType: apiType,
@@ -257,7 +258,9 @@ class CollectionStateNotifier
name: name ?? currentModel.name, name: name ?? currentModel.name,
description: description ?? currentModel.description, description: description ?? currentModel.description,
httpRequestModel: null, httpRequestModel: null,
aiRequestModel: const AIRequestModel()), aiRequestModel: defaultModel == null
? const AIRequestModel()
: AIRequestModel.fromJson(defaultModel)),
}; };
} else { } else {
newModel = currentModel.copyWith( newModel = currentModel.copyWith(

View File

@@ -34,8 +34,7 @@ class ThemeStateNotifier extends StateNotifier<SettingsModel> {
String? workspaceFolderPath, String? workspaceFolderPath,
bool? isSSLDisabled, bool? isSSLDisabled,
bool? isDashBotEnabled, bool? isDashBotEnabled,
// TODO: Fix it Map<String, Object?>? defaultAIModel,
// LLMSaveObject? defaultLLMSaveObject,
}) async { }) async {
state = state.copyWith( state = state.copyWith(
isDark: isDark, isDark: isDark,
@@ -51,8 +50,7 @@ class ThemeStateNotifier extends StateNotifier<SettingsModel> {
workspaceFolderPath: workspaceFolderPath, workspaceFolderPath: workspaceFolderPath,
isSSLDisabled: isSSLDisabled, isSSLDisabled: isSSLDisabled,
isDashBotEnabled: isDashBotEnabled, isDashBotEnabled: isDashBotEnabled,
// TODO: Fix it defaultAIModel: defaultAIModel,
// defaultLLMSaveObject: defaultLLMSaveObject,
); );
await setSettingsToSharedPrefs(state); await setSettingsToSharedPrefs(state);
} }

View File

@@ -22,6 +22,10 @@ class _AIModelSelectorDialogState extends ConsumerState<AIModelSelectorDialog> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
selectedProvider = widget.aiRequestModel?.modelApiProvider;
if (selectedProvider != null && widget.aiRequestModel?.model != null) {
newAIRequestModel = widget.aiRequestModel?.copyWith();
}
aM = ModelManager.fetchAvailableModels(); aM = ModelManager.fetchAvailableModels();
} }

View File

@@ -29,7 +29,8 @@ class CodePane extends ConsumerWidget {
? getRequestModelFromHistoryModel(selectedHistoryRequestModel!) ? getRequestModelFromHistoryModel(selectedHistoryRequestModel!)
: ref.watch(selectedRequestModelProvider); : ref.watch(selectedRequestModelProvider);
if (selectedRequestModel!.apiType == APIType.ai) { // TODO: Add AI Request Codegen
if (selectedRequestModel?.apiType == APIType.ai) {
return const ErrorMessage( return const ErrorMessage(
message: "Code generation for AI Requests is currently not available.", message: "Code generation for AI Requests is currently not available.",
); );

View File

@@ -1,3 +1,4 @@
import 'package:apidash_core/apidash_core.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -7,6 +8,7 @@ import '../services/services.dart';
import '../utils/utils.dart'; import '../utils/utils.dart';
import '../widgets/widgets.dart'; import '../widgets/widgets.dart';
import '../consts.dart'; import '../consts.dart';
import 'common_widgets/common_widgets.dart';
class SettingsPage extends ConsumerWidget { class SettingsPage extends ConsumerWidget {
const SettingsPage({super.key}); const SettingsPage({super.key});
@@ -114,19 +116,22 @@ class SettingsPage extends ConsumerWidget {
}, },
), ),
), ),
// TODO: Fix it ListTile(
// ListTile( hoverColor: kColorTransparent,
// hoverColor: kColorTransparent, title: const Text('Default Large Language Model (LLM)'),
// title: const Text('Default Large Language Model (LLM)'), trailing: AIModelSelectorButton(
// trailing: DefaultLLMSelectorButton( aiRequestModel:
// defaultLLM: settings.defaultLLMSaveObject, AIRequestModel.fromJson(settings.defaultAIModel ?? {}),
// onDefaultLLMUpdated: (d) { onModelUpdated: (d) {
// ref ref.read(settingsProvider.notifier).update(
// .read(settingsProvider.notifier) defaultAIModel: d.copyWith(
// .update(defaultLLMSaveObject: d); modelConfigs: [],
// }, stream: null,
// ), systemPrompt: '',
// ), userPrompt: '').toJson());
},
),
),
CheckboxListTile( CheckboxListTile(
title: const Text("Save Responses"), title: const Text("Save Responses"),
subtitle: subtitle: