chore: initial release

This commit is contained in:
cogwheel0
2025-08-10 01:20:45 +05:30
commit 758615813f
218 changed files with 67743 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'chat_message.freezed.dart';
part 'chat_message.g.dart';
@freezed
sealed class ChatMessage with _$ChatMessage {
const factory ChatMessage({
required String id,
required String role, // 'user', 'assistant', 'system'
required String content,
required DateTime timestamp,
String? model,
@Default(false) bool isStreaming,
List<String>? attachmentIds,
Map<String, dynamic>? metadata,
List<Map<String, dynamic>>? sources,
Map<String, dynamic>? usage,
}) = _ChatMessage;
factory ChatMessage.fromJson(Map<String, dynamic> json) =>
_$ChatMessageFromJson(json);
}

View File

@@ -0,0 +1,27 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'chat_message.dart';
part 'conversation.freezed.dart';
part 'conversation.g.dart';
@freezed
sealed class Conversation with _$Conversation {
const factory Conversation({
required String id,
required String title,
required DateTime createdAt,
required DateTime updatedAt,
String? model,
String? systemPrompt,
@Default([]) List<ChatMessage> messages,
@Default({}) Map<String, dynamic> metadata,
@Default(false) bool pinned,
@Default(false) bool archived,
String? shareId,
String? folderId,
@Default([]) List<String> tags,
}) = _Conversation;
factory Conversation.fromJson(Map<String, dynamic> json) =>
_$ConversationFromJson(json);
}

View File

@@ -0,0 +1,23 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'file_info.freezed.dart';
part 'file_info.g.dart';
@freezed
sealed class FileInfo with _$FileInfo {
const factory FileInfo({
required String id,
required String filename,
required String originalFilename,
required int size,
required String mimeType,
required DateTime createdAt,
required DateTime updatedAt,
String? userId,
String? hash,
Map<String, dynamic>? metadata,
}) = _FileInfo;
factory FileInfo.fromJson(Map<String, dynamic> json) =>
_$FileInfoFromJson(json);
}

View File

@@ -0,0 +1,41 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'folder.freezed.dart';
part 'folder.g.dart';
// Timestamp converter for Unix timestamps
class TimestampConverter implements JsonConverter<DateTime, dynamic> {
const TimestampConverter();
@override
DateTime fromJson(dynamic json) {
if (json is String) {
return DateTime.parse(json);
} else if (json is int) {
return DateTime.fromMillisecondsSinceEpoch(json * 1000);
} else {
throw ArgumentError('Invalid date format: $json');
}
}
@override
dynamic toJson(DateTime object) {
return object.millisecondsSinceEpoch ~/ 1000;
}
}
@freezed
sealed class Folder with _$Folder {
const factory Folder({
required String id,
required String name,
@TimestampConverter() required DateTime createdAt,
@TimestampConverter() required DateTime updatedAt,
String? parentId,
@Default([]) List<String> conversationIds,
@Default([]) List<Folder> subfolders,
@Default({}) Map<String, dynamic> metadata,
}) = _Folder;
factory Folder.fromJson(Map<String, dynamic> json) => _$FolderFromJson(json);
}

View File

@@ -0,0 +1,35 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'knowledge_base.freezed.dart';
part 'knowledge_base.g.dart';
@freezed
sealed class KnowledgeBase with _$KnowledgeBase {
const factory KnowledgeBase({
required String id,
required String name,
String? description,
required DateTime createdAt,
required DateTime updatedAt,
@Default(0) int itemCount,
@Default({}) Map<String, dynamic> metadata,
}) = _KnowledgeBase;
factory KnowledgeBase.fromJson(Map<String, dynamic> json) =>
_$KnowledgeBaseFromJson(json);
}
@freezed
sealed class KnowledgeBaseItem with _$KnowledgeBaseItem {
const factory KnowledgeBaseItem({
required String id,
required String content,
String? title,
required DateTime createdAt,
required DateTime updatedAt,
@Default({}) Map<String, dynamic> metadata,
}) = _KnowledgeBaseItem;
factory KnowledgeBaseItem.fromJson(Map<String, dynamic> json) =>
_$KnowledgeBaseItemFromJson(json);
}

View File

@@ -0,0 +1,93 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'model.freezed.dart';
@freezed
sealed class Model with _$Model {
const Model._();
const factory Model({
required String id,
required String name,
String? description,
@Default(false) bool isMultimodal,
@Default(false) bool supportsStreaming,
@Default(false) bool supportsRAG,
Map<String, dynamic>? capabilities,
Map<String, dynamic>? metadata,
List<String>? supportedParameters,
}) = _Model;
factory Model.fromJson(Map<String, dynamic> json) {
// Handle different response formats from OpenWebUI
// Extract architecture info for capabilities
final architecture = json['architecture'] as Map<String, dynamic>?;
final modality = architecture?['modality'] as String?;
final inputModalities = architecture?['input_modalities'] as List?;
// Determine if multimodal based on architecture
final isMultimodal =
modality?.contains('image') == true ||
inputModalities?.contains('image') == true;
// Extract supported parameters robustly (top-level or nested under provider keys)
List? supportedParams =
(json['supported_parameters'] as List?) ??
(json['supportedParameters'] as List?);
if (supportedParams == null) {
const providerKeys = [
'openai',
'anthropic',
'google',
'meta',
'mistral',
'cohere',
'xai',
'perplexity',
'deepseek',
'groq',
];
for (final key in providerKeys) {
final provider = json[key] as Map<String, dynamic>?;
final list =
(provider?['supported_parameters'] as List?) ??
(provider?['supportedParameters'] as List?);
if (list != null) {
supportedParams = list;
break;
}
}
}
// Determine streaming support from supported parameters if known
final supportsStreaming = supportedParams?.contains('stream') ?? true;
// Convert supported parameters to List<String> if present
final supportedParamsList = supportedParams
?.map((e) => e.toString())
.toList();
return Model(
id: json['id'] as String,
name: json['name'] as String,
description: json['description'] as String?,
isMultimodal: isMultimodal,
supportsStreaming: supportsStreaming,
supportsRAG: json['supportsRAG'] as bool? ?? false,
supportedParameters: supportedParamsList,
capabilities: {
'architecture': architecture,
'pricing': json['pricing'],
'context_length': json['context_length'],
'supported_parameters': supportedParamsList ?? supportedParams,
},
metadata: {
'canonical_slug': json['canonical_slug'],
'created': json['created'],
'connection_type': json['connection_type'],
},
);
}
}

View File

@@ -0,0 +1,19 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'server_config.freezed.dart';
part 'server_config.g.dart';
@freezed
sealed class ServerConfig with _$ServerConfig {
const factory ServerConfig({
required String id,
required String name,
required String url,
String? apiKey,
DateTime? lastConnected,
@Default(false) bool isActive,
}) = _ServerConfig;
factory ServerConfig.fromJson(Map<String, dynamic> json) =>
_$ServerConfigFromJson(json);
}

33
lib/core/models/user.dart Normal file
View File

@@ -0,0 +1,33 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
@freezed
sealed class User with _$User {
const User._();
const factory User({
required String id,
required String username,
required String email,
String? name,
String? profileImage,
required String role,
@Default(true) bool isActive,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) {
// Handle different field names from OpenWebUI API
return User(
id: json['id'] as String? ?? '',
username: json['username'] as String? ?? json['name'] as String? ?? '',
email: json['email'] as String? ?? '',
name: json['name'] as String?,
profileImage:
json['profile_image_url'] as String? ??
json['profileImage'] as String?,
role: json['role'] as String? ?? 'user',
isActive: json['is_active'] as bool? ?? json['isActive'] as bool? ?? true,
);
}
}

View File

@@ -0,0 +1,40 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user_settings.freezed.dart';
part 'user_settings.g.dart';
@freezed
sealed class UserSettings with _$UserSettings {
const factory UserSettings({
// Chat preferences
@Default(true) bool showReadReceipts,
@Default(true) bool enableNotifications,
@Default(false) bool enableSounds,
@Default('auto') String theme, // 'light', 'dark', 'auto'
// AI preferences
@Default(0.7) double temperature,
@Default(2048) int maxTokens,
@Default(false) bool streamResponses,
@Default(false) bool webSearchEnabled,
// Privacy settings
@Default(true) bool saveConversations,
@Default(false) bool shareUsageData,
// Interface preferences
@Default('comfortable')
String density, // 'compact', 'comfortable', 'spacious'
@Default(14.0) double fontSize,
@Default('en') String language,
// Accessibility settings
@Default(false) bool reduceMotion,
@Default(true) bool hapticFeedback,
// Advanced settings
@Default({}) Map<String, dynamic> customSettings,
}) = _UserSettings;
factory UserSettings.fromJson(Map<String, dynamic> json) =>
_$UserSettingsFromJson(json);
}