2025-04-24 10:40:22 +02:00
using BeWo.Core ;
2025-06-11 12:51:32 +02:00
using BeWo.Core.Commands ;
2025-04-24 10:40:22 +02:00
using BeWo.ServiceProxy ;
2025-04-14 10:15:45 +02:00
using BS.Shared ;
2025-06-24 13:21:07 +02:00
using BS.Shared.Core ;
2025-03-19 16:30:27 +01:00
using BS.Shared.DataContracts ;
2025-04-02 16:01:21 +02:00
using BS.Shared.DataContracts.Feature.AI ;
2025-03-19 16:30:27 +01:00
using BS.Shared.Extensions ;
using ChatController.Utilities.Extensions ;
using DevExpress.Mvvm ;
2025-04-24 10:40:22 +02:00
using DevExpress.Xpf.Editors ;
2025-03-19 16:30:27 +01:00
using DevExpress.XtraPrinting.Native ;
using System ;
using System.Collections.Generic ;
using System.Collections.ObjectModel ;
2025-04-03 16:47:50 +02:00
using System.Diagnostics ;
2025-03-19 16:30:27 +01:00
using System.Linq ;
2025-03-28 10:05:29 +01:00
using System.Runtime.Remoting.Contexts ;
2025-03-19 16:30:27 +01:00
using System.Text ;
using System.Threading.Tasks ;
2025-04-24 16:02:13 +02:00
using System.Windows ;
2025-06-20 13:43:06 +02:00
using System.Windows.Data ;
2025-04-24 16:02:13 +02:00
using System.Windows.Input ;
2025-04-02 16:01:21 +02:00
using System.Windows.Markup ;
2025-03-19 16:30:27 +01:00
using System.Windows.Threading ;
namespace BeWo.ViewModel.ListViewModel
{
public class AiConversationListVM : AbstractDCListMapperVM < AiConversationDC , AiConversationVM >
{
2025-04-24 10:40:22 +02:00
private bool _IsSettingsOpen ;
private bool _IsCloneOpen ;
2025-05-07 10:49:29 +02:00
private bool _IsSending ;
2025-04-24 10:40:22 +02:00
2025-03-28 10:05:29 +01:00
private string _MessageInput ;
private string _ContextInput ;
2025-03-19 16:30:27 +01:00
private AiModelDC _SelectedModel ;
2025-04-08 16:57:55 +02:00
private AiConfigVM _Config ;
2025-03-19 16:30:27 +01:00
2025-04-24 10:50:31 +02:00
public AiConversationListVM ( ) : this ( null )
2025-03-19 16:30:27 +01:00
{
2025-04-03 16:47:50 +02:00
if ( BeWoApp . IsInDesignMode )
{
InitDesigner ( ) ;
}
2025-03-19 16:30:27 +01:00
}
2025-04-03 16:47:50 +02:00
2025-03-19 16:30:27 +01:00
public AiConversationListVM ( List < AiConversationDC > pDCs ) : base ( pDCs )
{
2025-06-27 13:19:36 +02:00
Models = new BS . Shared . Core . ObservableSortCollection < AiModelDC > ( ) ;
2025-03-28 10:05:29 +01:00
2025-06-11 12:51:32 +02:00
bool sendCanExecute ( ) = > SelectedVM is object & & ! string . IsNullOrWhiteSpace ( MessageInput ) & & ! IsSending ;
SendNewMessageCommand = new DelegateCommand ( SendNewMessage , sendCanExecute ) ;
2025-05-13 11:10:24 +02:00
OpenNewConversationCommand = new DelegateCommand ( OpenNewConversation , ( ) = > BeWoApp . HasLoggedOnUserRight ( UserRightType . AiModuleChatAdd ) ) ;
2025-06-11 12:51:32 +02:00
bool startconvCanExecute ( ) = > ! string . IsNullOrWhiteSpace ( MessageInput ) & & ! IsSending ;
StartConversationWithMessageCommand = new DelegateCommand ( StartConversationWithMessage , startconvCanExecute ) ;
2025-04-08 16:57:55 +02:00
ReloadConfigCommand = new DelegateCommand ( ReloadConfig ) ;
ReloadConversationsCommand = new DelegateCommand ( ReloadConversations ) ;
ReloadModelsCommand = new DelegateCommand ( ReloadModels ) ;
2025-04-24 10:40:22 +02:00
2025-06-11 12:51:32 +02:00
bool openCanExecute ( ) = > ( BeWoApp . AppSettings ? . ModuleAiSettingsEnabled ? ? true ) & & BeWoApp . HasLoggedOnUserRight ( UserRightType . AiModuleViewSetting ) ;
OpenSettingCommand = new DelegateCommand ( OpenSetting , openCanExecute , false ) ;
2025-05-06 10:32:44 +02:00
OpenCloneCommand = new DelegateCommand ( OpenClone , ( ) = > BeWoApp . HasLoggedOnUserRight ( UserRightType . AiModuleChatClone ) & & SelectedVM is object ) ;
2025-04-24 16:02:13 +02:00
CloneCommand = new DelegateCommand ( Clone ) ;
AskDeleteCommand = new DelegateCommand ( AskDelete , ( ) = > BeWoApp . HasLoggedOnUserRight ( UserRightType . AiModuleChatDelete ) & & SelectedVM is object ) ;
2025-05-13 11:10:24 +02:00
SelectedVMChanged + = ( s , e ) = > FirePropertyChanged ( nameof ( IsNewConversationVisible ) ) ;
2025-03-19 16:30:27 +01:00
}
2025-05-07 10:54:38 +02:00
public event EventHandler SendNewMessageSuccess ;
2025-03-28 10:05:29 +01:00
public DelegateCommand SendNewMessageCommand { get ; set ; }
2025-05-13 11:10:24 +02:00
public DelegateCommand OpenNewConversationCommand { get ; set ; }
public DelegateCommand StartConversationWithMessageCommand { get ; set ; }
2025-06-11 12:51:32 +02:00
//public DelegateCommand RequestNewConversationCommand { get; set; }
//public DelegateCommand TestCommand { get; set; }
2025-04-24 16:02:13 +02:00
public DelegateCommand AskDeleteCommand { get ; set ; }
2025-04-08 16:57:55 +02:00
public DelegateCommand ReloadConfigCommand { get ; set ; }
public DelegateCommand ReloadConversationsCommand { get ; set ; }
public DelegateCommand ReloadModelsCommand { get ; set ; }
2025-03-28 10:05:29 +01:00
2025-04-24 10:40:22 +02:00
public DelegateCommand OpenSettingCommand { get ; set ; }
public DelegateCommand OpenCloneCommand { get ; set ; }
2025-04-24 16:02:13 +02:00
public DelegateCommand CloneCommand { get ; set ; }
2025-04-24 10:40:22 +02:00
2025-03-19 16:30:27 +01:00
public ObservableCollection < AiModelDC > Models { get ; set ; }
2025-04-08 16:57:55 +02:00
public AiModelDC SelectedModel
{
get { return _SelectedModel ; }
2025-03-19 16:30:27 +01:00
set
{
if ( _SelectedModel = = value )
return ;
_SelectedModel = value ;
FirePropertyChanged ( nameof ( SelectedModel ) ) ;
}
}
2025-04-08 16:57:55 +02:00
public AiConfigVM Config
{
get { return _Config ; }
set
{
if ( Config = = value )
return ;
_Config = value ;
FirePropertyChanged ( nameof ( Config ) ) ;
}
}
2025-04-02 16:01:21 +02:00
2025-03-28 10:05:29 +01:00
public string MessageInput
{
get { return _MessageInput ; }
set
{
if ( MessageInput = = value )
return ;
_MessageInput = value ;
FirePropertyChanged ( nameof ( MessageInput ) ) ;
}
}
public string ContextInput
{
get { return _ContextInput ; }
set
{
if ( ContextInput = = value )
return ;
_ContextInput = value ;
FirePropertyChanged ( nameof ( ContextInput ) ) ;
}
}
2025-04-24 10:40:22 +02:00
public bool IsSettingsOpen
{
get = > _IsSettingsOpen ;
set
{
_IsSettingsOpen = value ;
FirePropertyChanged ( nameof ( IsSettingsOpen ) ) ;
}
}
public bool IsCloneOpen
{
get = > _IsCloneOpen ;
set
{
_IsCloneOpen = value ;
FirePropertyChanged ( nameof ( IsCloneOpen ) ) ;
}
}
2025-05-07 10:49:29 +02:00
public bool IsSending
{
get = > _IsSending ;
set
{
_IsSending = value ;
FirePropertyChanged ( nameof ( IsSending ) ) ;
}
}
2025-05-13 11:10:24 +02:00
public bool IsNewConversationVisible = > SelectedVM is null ;
2025-04-24 10:40:22 +02:00
2025-04-24 10:50:31 +02:00
public int UIContext { get ; set ; }
2025-05-05 13:08:09 +02:00
public long? ReferenceObjectOid { get ; set ; }
2025-04-14 10:15:45 +02:00
public Dictionary < TableID , long [ ] > ContextBeWoObjects { get ; set ; }
2025-04-02 16:01:21 +02:00
2025-05-13 11:10:24 +02:00
private void StartConversationWithMessage ( )
2025-04-02 16:01:21 +02:00
{
2025-05-13 11:10:24 +02:00
StartSending ( ) ;
try
{
var message = MessageInput ;
var conv = new AiConversationDC ( ) ;
conv . Created = DateTime . Now ;
conv . Updated = DateTime . Now ;
conv . UIContext = UIContext ;
conv . ContextBeWoObjects = ContextBeWoObjects ;
conv . Messages = new List < AiConversationMessageDC > ( )
{
new AiConversationMessageDC ( )
{
Message = message ,
Role = AiConversationMessageRole . User
}
} ;
2025-04-14 10:15:45 +02:00
2025-05-13 11:10:24 +02:00
var vm = InsertConverstion ( conv ) ;
2025-04-14 10:15:45 +02:00
2025-05-13 11:10:24 +02:00
ServiceFacade . DoAiEnhancedServiceAsnyc (
x = > x . CreateAiConversationWithMessage ( conv , Config . SelectedModel . Oid . Value , message ) ,
dc = > UpdateConverstion ( vm , dc ) ,
e = > EndSending ( ) ) ;
}
catch ( Exception ex )
{
EndSending ( ) ;
}
}
private void OpenNewConversation ( )
{
SelectedVM = null ;
2025-04-02 16:01:21 +02:00
}
2025-04-24 16:02:13 +02:00
private void SendNewMessage ( )
2025-03-28 10:05:29 +01:00
{
2025-05-13 11:10:24 +02:00
StartSending ( ) ;
2025-03-28 10:05:29 +01:00
2025-05-07 10:49:29 +02:00
try
{
var conv = SelectedVM ;
2025-03-28 10:05:29 +01:00
2025-05-07 10:49:29 +02:00
var msg_dc = new AiConversationMessageDC ( ) ;
2025-03-28 10:05:29 +01:00
2025-05-07 10:49:29 +02:00
msg_dc . Message = MessageInput ;
2025-06-20 12:16:01 +02:00
msg_dc . Role = AiConversationMessageRole . User ;
2025-05-07 10:49:29 +02:00
msg_dc . Created = DateTime . Now ;
2025-04-02 16:01:21 +02:00
2025-05-07 10:49:29 +02:00
var msg_vm = new AiConversationMessageVM ( msg_dc ) ;
2025-03-28 10:05:29 +01:00
2025-05-07 10:49:29 +02:00
conv . Messages . VMList . Add ( msg_vm ) ;
2025-03-28 10:05:29 +01:00
2025-05-07 10:49:29 +02:00
ServiceFacade . DoAiEnhancedServiceAsnyc (
x = > x . SendNewMessage ( conv . DataContract . Oid . Value , MessageInput ) ,
( messages ) = >
{
if ( messages . Count ! = 2 )
throw new InvalidOperationException ( "message count: " + messages . Count ) ;
2025-03-28 10:05:29 +01:00
2025-05-07 10:49:29 +02:00
msg_vm . DataContract = messages [ 0 ] ;
2025-04-24 15:19:59 +02:00
2025-05-07 10:49:29 +02:00
conv . Messages . VMList . Add ( new AiConversationMessageVM ( messages [ 1 ] ) ) ;
MessageInput = string . Empty ;
2025-05-13 11:10:24 +02:00
EndSending ( ) ;
2025-05-07 10:54:38 +02:00
SendNewMessageSuccess ? . Invoke ( this , EventArgs . Empty ) ;
2025-05-07 10:49:29 +02:00
} ,
( exception ) = >
{
conv . Messages . VMList . Remove ( msg_vm ) ;
2025-05-13 11:10:24 +02:00
EndSending ( ) ;
2025-05-07 10:49:29 +02:00
}
) ;
}
catch ( Exception ex ) {
2025-05-13 11:10:24 +02:00
EndSending ( ) ;
2025-04-24 14:56:11 +02:00
}
2025-05-13 11:10:24 +02:00
}
private void StartSending ( )
{
if ( IsSending )
throw new InvalidOperationException ( "Sendet bereits" ) ;
IsSending = true ;
}
private void EndSending ( )
{
if ( ! IsSending )
throw new InvalidOperationException ( "Sendet nicht" ) ;
2025-05-07 10:49:29 +02:00
2025-05-13 11:10:24 +02:00
IsSending = false ;
2025-03-28 10:05:29 +01:00
}
2025-04-24 16:02:13 +02:00
private void Test ( )
2025-03-28 10:05:29 +01:00
{
2025-04-02 16:01:21 +02:00
throw new NotImplementedException ( ) ;
2025-03-28 10:05:29 +01:00
2025-04-02 16:01:21 +02:00
//var limit = 5;
2025-03-28 10:05:29 +01:00
2025-04-02 16:01:21 +02:00
//var models = ServiceFacade.DoOperationsEnhancedServiceSnyc(x => x.GetAiModels());
//Models.MakeEqualTo(models);
2025-03-28 10:05:29 +01:00
2025-04-02 16:01:21 +02:00
//VMList.Clear();
//foreach (var vm in Models)
//{
// var dc = new AiConversationDC();
2025-03-28 10:05:29 +01:00
2025-04-02 16:01:21 +02:00
// dc.Created = DateTime.Now;
// dc.Displayname = "Example";
// dc.Modell = vm.ToString();
2025-03-28 10:05:29 +01:00
2025-04-02 16:01:21 +02:00
// var pvm = new AiConversationVM(dc);
2025-03-28 10:05:29 +01:00
2025-04-02 16:01:21 +02:00
// VMList.Add(pvm);
//}
2025-03-28 10:05:29 +01:00
2025-04-02 16:01:21 +02:00
//var msg = "Wie alt ist Frau Müller?";
//var context = "Frau Müller wurde am 1.1.1950 geboren. Aktuelle haben wir folgende Universalzeit: " + DateTime.Now.ToUniversalTime();
2025-03-28 10:05:29 +01:00
2025-04-02 16:01:21 +02:00
//for (var i = 0; i < limit; i++)
//{
// foreach (var vm in VMList)
// {
// ServiceFacade.DoOperationsEnhancedServiceAsnyc(x => x.SendNewMessage(vm.CommitToDataContract(), context, msg), (message) =>
// {
// vm.Messages.VMList.Add(new AiConversationMessageVM(message));
// });
// }
//}
2025-03-28 10:05:29 +01:00
}
2025-04-22 14:05:51 +02:00
2025-05-13 11:10:24 +02:00
private AiConversationVM InsertConverstion ( AiConversationDC dc )
2025-04-22 14:05:51 +02:00
{
var vm = new AiConversationVM ( dc ) ;
VMList . Insert ( 0 , vm ) ;
SelectedVM = vm ;
2025-05-13 11:10:24 +02:00
return vm ;
}
private void UpdateConverstion ( AiConversationVM vm , AiConversationDC dc )
{
vm . UpdateByDataContract ( dc ) ;
MessageInput = string . Empty ;
EndSending ( ) ;
SendNewMessageSuccess ? . Invoke ( this , EventArgs . Empty ) ;
2025-04-22 14:05:51 +02:00
}
2025-03-28 10:05:29 +01:00
2025-04-08 16:57:55 +02:00
private void ReloadConfig ( )
{
2025-04-14 13:04:13 +02:00
ServiceFacade . DoAiEnhancedServiceAsnyc ( x = > x . GetAiConfig ( ) , ( x ) = >
2025-04-08 16:57:55 +02:00
{
if ( Config is null )
Config = new AiConfigVM ( x ) ;
else
Config . Update ( x ) ;
} ) ;
}
public void UpdateConfig ( )
{
if ( ! Config . IsDirty )
return ;
2025-04-14 13:04:13 +02:00
ServiceFacade . DoAiEnhancedServiceAsnyc ( x = > x . UpdateAiConfig ( Config . CommitToDataContract ( ) ) , ( x ) = >
2025-04-08 16:57:55 +02:00
{
Config . Update ( x ) ;
} ) ;
}
private void ReloadModels ( )
{
2025-04-14 13:04:13 +02:00
ServiceFacade . DoAiEnhancedServiceAsnyc ( x = > x . GetAiModels ( ) , ( x ) = >
2025-04-08 16:57:55 +02:00
{
Models . MakeEqualTo ( x ) ;
if ( Config . SelectedModel is null & & Models . Any ( ) )
Config . SelectedModel = Models . First ( ) ;
} ) ;
}
private void ReloadConversations ( )
{
var ui_context = UIContext ;
2025-05-05 13:08:09 +02:00
var reference = ReferenceObjectOid ;
2025-04-08 16:57:55 +02:00
2025-05-05 13:08:09 +02:00
ServiceFacade . DoAiEnhancedServiceAsnyc ( x = > x . GetAiConversations ( ui_context , reference ) , ( x ) = >
2025-04-08 16:57:55 +02:00
{
x . Reverse ( ) ;
var vms = new AiConversationListVM ( x ) ;
VMList . MakeEqualTo ( vms . VMList ) ;
} ) ;
}
2025-04-24 10:40:22 +02:00
private void OpenSetting ( )
{
ServiceFacade . DoAiEnhancedServiceAsnyc ( x = > x . GetAiModels ( ) , ( x ) = >
{
Models . MakeEqualTo ( x ) ;
IsSettingsOpen = true ;
} ) ;
}
private void OpenClone ( )
{
foreach ( var message in SelectedVM . Messages . VMList )
{
message . IsChecked = true ;
}
IsCloneOpen = true ;
}
2025-04-24 16:02:13 +02:00
private void Clone ( )
{
var conv = SelectedVM ;
AiConversationMessageVM last = null ;
foreach ( var msg in conv . Messages . VMList )
{
if ( ! msg . IsChecked )
break ;
last = msg ;
}
var conv_oid = conv . DataContract . Oid . Value ;
var msg_oid = last ? . DataContract . Oid ;
ServiceFacade . DoAiEnhancedServiceAsnyc ( x = > x . CloneAiConversation ( conv_oid , msg_oid ) , dc = >
{
InsertConverstion ( dc ) ;
CloseClone ( ) ;
} ) ;
}
2025-04-24 10:50:31 +02:00
private void CloseClone ( )
{
IsCloneOpen = false ;
}
2025-04-24 10:40:22 +02:00
2025-04-24 16:02:13 +02:00
public void AskDelete ( )
{
var selected = SelectedVM ;
var oid = selected . DataContract . Oid . Value ;
var msg = $"Wollen Sie die ausgewählte Konversation ({oid}) löschen?" ;
if ( MessageBox . Show ( msg , "Konversation löschen" , MessageBoxButton . YesNo , MessageBoxImage . Warning ) = =
MessageBoxResult . Yes )
{
ServiceFacade . DoAiEnhancedServiceAsnyc ( x = > x . DeleteAiConversation ( oid ) , ( ) = > {
VMList . Remove ( selected ) ;
CommandManager . InvalidateRequerySuggested ( ) ;
//SelectedVM = VMList.FirstOrDefault();
} ) ;
}
}
2025-04-08 16:57:55 +02:00
#region Designer
2025-04-03 16:47:50 +02:00
private void InitDesigner ( )
{
2025-04-08 12:58:12 +02:00
var model = new AiModelDC ( )
{
2025-04-09 15:54:28 +02:00
ModelName = "N llama3.2"
2025-04-08 12:58:12 +02:00
} ;
2025-04-03 16:47:50 +02:00
var message_dc = new AiConversationMessageDC ( )
{
Created = DateTime . Now ,
2025-04-09 15:54:28 +02:00
Message = "Nu bist eine intelligente Einheit mit ganz ganz vielen Eingaben: value1, value2, value3, value4\r\nTest" ,
2025-04-03 16:47:50 +02:00
Role = BS . Shared . AiConversationMessageRole . System
} ;
var message_dc2 = new AiConversationMessageDC ( )
{
Created = DateTime . Now ,
2025-04-09 15:54:28 +02:00
Message = "N. Dies ist eine Design Frage: Du sollst ganz viele Sachen machen. Dabei sollst du auf ganz viele Sachen achten: Zum Beispiel:\r\nSache 1\r\nSchritt 2" ,
2025-04-03 16:47:50 +02:00
Role = BS . Shared . AiConversationMessageRole . User
} ;
var message_dc3 = new AiConversationMessageDC ( )
{
Created = DateTime . Now ,
2025-04-09 15:54:28 +02:00
Message = "N. Deine Antwort. Dies ist eine Design Antwort. Du hast ganz viele Sachen angefragt. Dabei soll ich auf ganz viele Sachen achten. Wie Test, test, tEst und tesT.\r\nTest\r\nTest\r\nTest" ,
2025-04-08 12:58:12 +02:00
Role = BS . Shared . AiConversationMessageRole . Assistent ,
ModelName = model . ModelName ,
Duration = 10 ,
2025-04-03 16:47:50 +02:00
} ;
var messages_dc = new List < AiConversationMessageDC > ( )
{
message_dc ,
message_dc2 ,
2025-04-08 12:58:12 +02:00
message_dc3 ,
message_dc2 ,
message_dc3 ,
message_dc2 ,
message_dc3 ,
message_dc2 ,
message_dc3 ,
2025-04-03 16:47:50 +02:00
} ;
2025-04-24 10:50:31 +02:00
2025-04-03 16:47:50 +02:00
var conversation_dc = new AiConversationDC ( )
{
Created = DateTime . Now ,
2025-04-08 10:22:22 +02:00
Displayname = "Displayname Megamegalange Deluxe Op 3000" ,
2025-04-03 16:47:50 +02:00
Messages = messages_dc ,
Modell = model ,
UIContext = 19 ,
Updated = DateTime . Now ,
} ;
var conversation_vm = new AiConversationVM ( conversation_dc ) ;
VMList . Add ( conversation_vm ) ;
2025-04-08 10:22:22 +02:00
InitDummyConversations ( 10 ) ;
2025-05-13 11:10:24 +02:00
//SelectedVM = conversation_vm;
2025-04-03 16:47:50 +02:00
}
2025-04-08 10:22:22 +02:00
private void InitDummyConversations ( int count )
{
var model = new AiModelDC ( )
{
ModelName = "llama3.2"
} ;
for ( int i = 0 ; i < count ; i + + )
{
var conversation_dc2 = new AiConversationDC ( )
{
Created = DateTime . Now ,
Displayname = "Dummy Num " + i . ToString ( ) ,
Modell = model ,
UIContext = 19 ,
Updated = DateTime . Now ,
} ;
var conversation_vm2 = new AiConversationVM ( conversation_dc2 ) ;
VMList . Add ( conversation_vm2 ) ;
}
}
2025-04-08 16:57:55 +02:00
#endregion
2025-03-19 16:30:27 +01:00
}
}