1- using BotSharp . Abstraction . Chart ;
21using BotSharp . Abstraction . Files . Constants ;
32using BotSharp . Abstraction . Files . Enums ;
4- using BotSharp . Abstraction . Files . Utilities ;
53using BotSharp . Abstraction . MessageHub . Models ;
64using BotSharp . Abstraction . MessageHub . Services ;
75using BotSharp . Abstraction . Options ;
86using BotSharp . Abstraction . Routing ;
97using BotSharp . Abstraction . Users . Dtos ;
108using BotSharp . Core . Infrastructures ;
11- using BotSharp . Core . Users . Services ;
12- using System . Diagnostics ;
13- using static BotSharp . Abstraction . Diagnostics . ModelDiagnostics ;
149
1510namespace BotSharp . OpenAPI . Controllers ;
1611
1712[ Authorize ]
1813[ ApiController ]
19- public class ConversationController : ControllerBase
14+ public partial class ConversationController : ControllerBase
2015{
2116 private readonly IServiceProvider _services ;
2217 private readonly IUserIdentity _user ;
2318 private readonly JsonSerializerOptions _jsonOptions ;
2419
25- public ConversationController ( IServiceProvider services ,
20+ public ConversationController (
21+ IServiceProvider services ,
2622 IUserIdentity user ,
2723 BotSharpOptions options )
2824 {
@@ -46,12 +42,8 @@ public async Task<ConversationViewModel> NewConversation([FromRoute] string agen
4642 } ;
4743 conv = await service . NewConversation ( conv ) ;
4844 service . SetConversationId ( conv . Id , config . States ) ;
49- using ( var trace = new ActivitySource ( "BotSharp" ) . StartActivity ( "NewUserSession" , ActivityKind . Internal ) )
50- {
51- trace ? . SetTag ( "user_id" , _user . FullName ) ;
52- trace ? . SetTag ( "conversation_id" , conv . Id ) ;
53- return ConversationViewModel . FromSession ( conv ) ;
54- }
45+
46+ return ConversationViewModel . FromSession ( conv ) ;
5547 }
5648
5749 [ HttpGet ( "/conversations" ) ]
@@ -371,34 +363,25 @@ public async Task<ChatResponseModel> SendMessage(
371363 conv . SetConversationId ( conversationId , input . States ) ;
372364 SetStates ( conv , input ) ;
373365
374- using ( var trace = new ActivitySource ( "BotSharp" ) . StartActivity ( "UserSession" , ActivityKind . Internal ) )
375- {
376- trace ? . SetTag ( "user.id" , _user . FullName ) ;
377- trace ? . SetTag ( "session.id" , conversationId ) ;
378- trace ? . SetTag ( "input" , inputMsg . Content ) ;
379- trace ? . SetTag ( ModelDiagnosticsTags . AgentId , agentId ) ;
380-
381- var response = new ChatResponseModel ( ) ;
382- await conv . SendMessage ( agentId , inputMsg ,
383- replyMessage : input . Postback ,
384- async msg =>
385- {
386- response . Text = ! string . IsNullOrEmpty ( msg . SecondaryContent ) ? msg . SecondaryContent : msg . Content ;
387- response . Function = msg . FunctionName ;
388- response . MessageLabel = msg . MessageLabel ;
389- response . RichContent = msg . SecondaryRichContent ?? msg . RichContent ;
390- response . Instruction = msg . Instruction ;
391- response . Data = msg . Data ;
392- } ) ;
366+ var response = new ChatResponseModel ( ) ;
367+ await conv . SendMessage ( agentId , inputMsg ,
368+ replyMessage : input . Postback ,
369+ async msg =>
370+ {
371+ response . Text = ! string . IsNullOrEmpty ( msg . SecondaryContent ) ? msg . SecondaryContent : msg . Content ;
372+ response . Function = msg . FunctionName ;
373+ response . MessageLabel = msg . MessageLabel ;
374+ response . RichContent = msg . SecondaryRichContent ?? msg . RichContent ;
375+ response . Instruction = msg . Instruction ;
376+ response . Data = msg . Data ;
377+ } ) ;
393378
394- var state = _services . GetRequiredService < IConversationStateService > ( ) ;
395- response . States = state . GetStates ( ) ;
396- response . MessageId = inputMsg . MessageId ;
397- response . ConversationId = conversationId ;
379+ var state = _services . GetRequiredService < IConversationStateService > ( ) ;
380+ response . States = state . GetStates ( ) ;
381+ response . MessageId = inputMsg . MessageId ;
382+ response . ConversationId = conversationId ;
398383
399- trace ? . SetTag ( "output" , response . Data ) ;
400- return response ;
401- }
384+ return response ;
402385 }
403386
404387
@@ -449,7 +432,7 @@ await conv.SendMessage(agentId, inputMsg,
449432 response . Instruction = msg . Instruction ;
450433 response . Data = msg . Data ;
451434 response . States = state . GetStates ( ) ;
452-
435+
453436 await OnChunkReceived ( Response , response ) ;
454437 } ) ;
455438
@@ -475,183 +458,6 @@ private async Task OnReceiveToolCallIndication(string conversationId, RoleDialog
475458 }
476459 #endregion
477460
478- #region Files and attachments
479- [ HttpGet ( "/conversation/{conversationId}/attachments" ) ]
480- public List < MessageFileViewModel > ListAttachments ( [ FromRoute ] string conversationId )
481- {
482- var fileStorage = _services . GetRequiredService < IFileStorageService > ( ) ;
483- var dir = fileStorage . GetDirectory ( conversationId ) ;
484-
485- // List files in the directory
486- var files = Directory . Exists ( dir )
487- ? Directory . GetFiles ( dir ) . Select ( f => new MessageFileViewModel
488- {
489- FileName = Path . GetFileName ( f ) ,
490- FileExtension = Path . GetExtension ( f ) . TrimStart ( '.' ) . ToLower ( ) ,
491- ContentType = FileUtility . GetFileContentType ( f ) ,
492- FileDownloadUrl = $ "/conversation/{ conversationId } /attachments/file/{ Path . GetFileName ( f ) } ",
493- } ) . ToList ( )
494- : new List < MessageFileViewModel > ( ) ;
495-
496- return files ;
497- }
498-
499- [ AllowAnonymous ]
500- [ HttpGet ( "/conversation/{conversationId}/attachments/file/{fileName}" ) ]
501- public IActionResult GetAttachment ( [ FromRoute ] string conversationId , [ FromRoute ] string fileName )
502- {
503- var fileStorage = _services . GetRequiredService < IFileStorageService > ( ) ;
504- var dir = fileStorage . GetDirectory ( conversationId ) ;
505- var filePath = Path . Combine ( dir , fileName ) ;
506- if ( ! System . IO . File . Exists ( filePath ) )
507- {
508- return NotFound ( ) ;
509- }
510- return BuildFileResult ( filePath ) ;
511- }
512-
513- [ HttpPost ( "/conversation/{conversationId}/attachments" ) ]
514- public IActionResult UploadAttachments ( [ FromRoute ] string conversationId , IFormFile [ ] files )
515- {
516- if ( files != null && files . Length > 0 )
517- {
518- var fileStorage = _services . GetRequiredService < IFileStorageService > ( ) ;
519- var dir = fileStorage . GetDirectory ( conversationId ) ;
520- foreach ( var file in files )
521- {
522- // Save the file, process it, etc.
523- var fileName = ContentDispositionHeaderValue . Parse ( file . ContentDisposition ) . FileName . Trim ( '"' ) ;
524- var filePath = Path . Combine ( dir , fileName ) ;
525-
526- fileStorage . SaveFileStreamToPath ( filePath , file . OpenReadStream ( ) ) ;
527- }
528-
529- return Ok ( new { message = "File uploaded successfully." } ) ;
530- }
531-
532- return BadRequest ( new { message = "Invalid file." } ) ;
533- }
534-
535- [ HttpPost ( "/agent/{agentId}/conversation/{conversationId}/upload" ) ]
536- public async Task < IActionResult > UploadConversationMessageFiles ( [ FromRoute ] string agentId , [ FromRoute ] string conversationId , [ FromBody ] InputMessageFiles input )
537- {
538- var convService = _services . GetRequiredService < IConversationService > ( ) ;
539- convService . SetConversationId ( conversationId , input . States ) ;
540- var conv = await convService . GetConversationRecordOrCreateNew ( agentId ) ;
541- var fileStorage = _services . GetRequiredService < IFileStorageService > ( ) ;
542- var messageId = Guid . NewGuid ( ) . ToString ( ) ;
543- var isSaved = fileStorage . SaveMessageFiles ( conv . Id , messageId , FileSource . User , input . Files ) ;
544- return Ok ( new { messageId = isSaved ? messageId : string . Empty } ) ;
545- }
546-
547- [ HttpGet ( "/conversation/{conversationId}/files/{messageId}/{source}" ) ]
548- public IEnumerable < MessageFileViewModel > GetConversationMessageFiles ( [ FromRoute ] string conversationId , [ FromRoute ] string messageId , [ FromRoute ] string source )
549- {
550- var fileStorage = _services . GetRequiredService < IFileStorageService > ( ) ;
551- var files = fileStorage . GetMessageFiles ( conversationId , [ messageId ] , options : new ( ) { Sources = [ source ] } ) ;
552- return files ? . Select ( x => MessageFileViewModel . Transform ( x ) ) ? . ToList ( ) ?? [ ] ;
553- }
554-
555- [ HttpGet ( "/conversation/{conversationId}/message/{messageId}/{source}/file/{index}/{fileName}" ) ]
556- public IActionResult GetMessageFile ( [ FromRoute ] string conversationId , [ FromRoute ] string messageId , [ FromRoute ] string source , [ FromRoute ] string index , [ FromRoute ] string fileName )
557- {
558- var fileStorage = _services . GetRequiredService < IFileStorageService > ( ) ;
559- var file = fileStorage . GetMessageFile ( conversationId , messageId , source , index , fileName ) ;
560- if ( string . IsNullOrEmpty ( file ) )
561- {
562- return NotFound ( ) ;
563- }
564- return BuildFileResult ( file ) ;
565- }
566-
567- [ HttpGet ( "/conversation/{conversationId}/message/{messageId}/{source}/file/{index}/{fileName}/download" ) ]
568- public IActionResult DownloadMessageFile ( [ FromRoute ] string conversationId , [ FromRoute ] string messageId , [ FromRoute ] string source , [ FromRoute ] string index , [ FromRoute ] string fileName )
569- {
570- var fileStorage = _services . GetRequiredService < IFileStorageService > ( ) ;
571- var file = fileStorage . GetMessageFile ( conversationId , messageId , source , index , fileName ) ;
572- if ( string . IsNullOrEmpty ( file ) )
573- {
574- return NotFound ( ) ;
575- }
576-
577- var fName = file . Split ( Path . DirectorySeparatorChar ) . Last ( ) ;
578- var contentType = FileUtility . GetFileContentType ( fName ) ;
579- var stream = System . IO . File . Open ( file , FileMode . Open , FileAccess . Read , FileShare . Read ) ;
580- var bytes = new byte [ stream . Length ] ;
581- stream . Read ( bytes , 0 , ( int ) stream . Length ) ;
582- stream . Position = 0 ;
583-
584- return new FileStreamResult ( stream , contentType ) { FileDownloadName = fName } ;
585- }
586- #endregion
587-
588- #region Chart
589- [ AllowAnonymous ]
590- [ HttpGet ( "/conversation/{conversationId}/message/{messageId}/user/chart/data" ) ]
591- public async Task < ConversationChartDataResponse ? > GetConversationChartData (
592- [ FromRoute ] string conversationId ,
593- [ FromRoute ] string messageId ,
594- [ FromQuery ] ConversationChartDataRequest request )
595- {
596- var chart = _services . GetServices < IBotSharpChartService > ( ) . FirstOrDefault ( x => x . Provider == request ? . ChartProvider ) ;
597- if ( chart == null ) return null ;
598-
599- var result = await chart . GetConversationChartData ( conversationId , messageId , request ) ;
600- return ConversationChartDataResponse . From ( result ) ;
601- }
602-
603- [ HttpPost ( "/conversation/{conversationId}/message/{messageId}/user/chart/code" ) ]
604- public async Task < ConversationChartCodeResponse ? > GetConversationChartCode (
605- [ FromRoute ] string conversationId ,
606- [ FromRoute ] string messageId ,
607- [ FromBody ] ConversationChartCodeRequest request )
608- {
609- var chart = _services . GetServices < IBotSharpChartService > ( ) . FirstOrDefault ( x => x . Provider == request ? . ChartProvider ) ;
610- if ( chart == null ) return null ;
611-
612- var result = await chart . GetConversationChartCode ( conversationId , messageId , request ) ;
613- return ConversationChartCodeResponse . From ( result ) ;
614- }
615- #endregion
616-
617- #region Dashboard
618- [ HttpPut ( "/agent/{agentId}/conversation/{conversationId}/dashboard" ) ]
619- public async Task < bool > PinConversationToDashboard ( [ FromRoute ] string agentId , [ FromRoute ] string conversationId )
620- {
621- var userService = _services . GetRequiredService < IUserService > ( ) ;
622- var pinned = await userService . AddDashboardConversation ( conversationId ) ;
623- return pinned ;
624- }
625-
626- [ HttpDelete ( "/agent/{agentId}/conversation/{conversationId}/dashboard" ) ]
627- public async Task < bool > UnpinConversationFromDashboard ( [ FromRoute ] string agentId , [ FromRoute ] string conversationId )
628- {
629- var userService = _services . GetRequiredService < IUserService > ( ) ;
630- var unpinned = await userService . RemoveDashboardConversation ( conversationId ) ;
631- return unpinned ;
632- }
633- #endregion
634-
635- #region Search state keys
636- [ HttpGet ( "/conversation/state/keys" ) ]
637- public async Task < List < string > > GetConversationStateKeys ( [ FromQuery ] ConversationStateKeysFilter request )
638- {
639- var convService = _services . GetRequiredService < IConversationService > ( ) ;
640- var keys = await convService . GetConversationStateSearhKeys ( request ) ;
641- return keys ;
642- }
643- #endregion
644-
645- #region Migrate Latest States
646- [ HttpPost ( "/conversation/latest-state/migrate" ) ]
647- public async Task < bool > MigrateConversationLatestStates ( [ FromBody ] MigrateLatestStateRequest request )
648- {
649- var convService = _services . GetRequiredService < IConversationService > ( ) ;
650- var res = await convService . MigrateLatestStates ( request . BatchSize , request . ErrorLimit ) ;
651- return res ;
652- }
653- #endregion
654-
655461 #region Private methods
656462 private void SetStates ( IConversationService conv , NewMessageModel input )
657463 {
0 commit comments