3
3
4
4
import requests
5
5
import structlog
6
- from fastapi import APIRouter , Depends , HTTPException , Response
6
+ from fastapi import APIRouter , Depends , HTTPException , Query , Response
7
7
from fastapi .responses import StreamingResponse
8
8
from fastapi .routing import APIRoute
9
9
from pydantic import BaseModel , ValidationError
10
10
11
+ from codegate .config import API_DEFAULT_PAGE_SIZE , API_MAX_PAGE_SIZE
11
12
import codegate .muxing .models as mux_models
12
13
from codegate import __version__
13
14
from codegate .api import v1_models , v1_processing
14
15
from codegate .db .connection import AlreadyExistsError , DbReader
15
- from codegate .db .models import AlertSeverity , Persona , WorkspaceWithModel
16
+ from codegate .db .models import AlertSeverity , AlertTriggerType , Persona , WorkspaceWithModel
16
17
from codegate .muxing .persona import (
17
18
PersonaDoesNotExistError ,
18
19
PersonaManager ,
@@ -443,11 +444,11 @@ async def get_workspace_alerts_summary(workspace_name: str) -> v1_models.AlertSu
443
444
raise HTTPException (status_code = 500 , detail = "Internal server error" )
444
445
445
446
try :
446
- summary = await dbreader .get_alerts_summary_by_workspace ( ws .id )
447
+ summary = await dbreader .get_alerts_summary ( workspace_id = ws .id )
447
448
return v1_models .AlertSummary (
448
- malicious_packages = summary [ "codegate_context_retriever_count" ] ,
449
- pii = summary [ "codegate_pii_count" ] ,
450
- secrets = summary [ "codegate_secrets_count" ] ,
449
+ malicious_packages = summary . total_packages_count ,
450
+ pii = summary . total_pii_count ,
451
+ secrets = summary . total_secrets_count ,
451
452
)
452
453
except Exception :
453
454
logger .exception ("Error while getting alerts summary" )
@@ -459,7 +460,13 @@ async def get_workspace_alerts_summary(workspace_name: str) -> v1_models.AlertSu
459
460
tags = ["Workspaces" ],
460
461
generate_unique_id_function = uniq_name ,
461
462
)
462
- async def get_workspace_messages (workspace_name : str ) -> List [v1_models .Conversation ]:
463
+ async def get_workspace_messages (
464
+ workspace_name : str ,
465
+ page : int = Query (1 , ge = 1 ),
466
+ page_size : int = Query (API_DEFAULT_PAGE_SIZE , ge = 1 , le = API_MAX_PAGE_SIZE ),
467
+ filter_by_ids : Optional [List [str ]] = Query (None ),
468
+ filter_by_alert_trigger_types : Optional [List [AlertTriggerType ]] = Query (None ),
469
+ ) -> v1_models .PaginatedMessagesResponse :
463
470
"""Get messages for a workspace."""
464
471
try :
465
472
ws = await wscrud .get_workspace_by_name (workspace_name )
@@ -469,20 +476,89 @@ async def get_workspace_messages(workspace_name: str) -> List[v1_models.Conversa
469
476
logger .exception ("Error while getting workspace" )
470
477
raise HTTPException (status_code = 500 , detail = "Internal server error" )
471
478
472
- try :
473
- prompts_with_output_alerts_usage = (
474
- await dbreader .get_prompts_with_output_alerts_usage_by_workspace_id (
475
- ws .id , AlertSeverity .CRITICAL .value
476
- )
479
+ offset = (page - 1 ) * page_size
480
+
481
+ prompts = await dbreader .get_prompts (
482
+ ws .id ,
483
+ offset ,
484
+ page_size ,
485
+ filter_by_ids ,
486
+ list ([AlertSeverity .CRITICAL .value ]), # TODO: Configurable severity
487
+ filter_by_alert_trigger_types ,
488
+ )
489
+ # Fetch total message count
490
+ total_count = await dbreader .get_total_messages_count_by_workspace_id (
491
+ ws .id , AlertSeverity .CRITICAL .value
492
+ )
493
+
494
+ # iterate for all prompts to compose the conversation summary
495
+ conversation_summaries : List [v1_models .ConversationSummary ] = []
496
+ for prompt in prompts :
497
+ if not prompt .request :
498
+ logger .warning (f"Skipping prompt { prompt .id } . Empty request field" )
499
+ continue
500
+
501
+ messages , _ = await v1_processing .parse_request (prompt .request )
502
+ if not messages or len (messages ) == 0 :
503
+ logger .warning (f"Skipping prompt { prompt .id } . No messages found" )
504
+ continue
505
+
506
+ # message is just the first entry in the request
507
+ message_obj = v1_models .ChatMessage (
508
+ message = messages [0 ], timestamp = prompt .timestamp , message_id = prompt .id
477
509
)
478
- conversations , _ = await v1_processing .parse_messages_in_conversations (
479
- prompts_with_output_alerts_usage
510
+
511
+ # count total alerts for the prompt
512
+ total_alerts_row = await dbreader .get_alerts_summary (prompt_id = prompt .id )
513
+
514
+ # get token usage for the prompt
515
+ prompts_outputs = await dbreader .get_prompts_with_output (prompt_id = prompt .id )
516
+ ws_token_usage = await v1_processing .parse_workspace_token_usage (prompts_outputs )
517
+
518
+ conversation_summary = v1_models .ConversationSummary (
519
+ chat_id = prompt .id ,
520
+ prompt = message_obj ,
521
+ provider = prompt .provider ,
522
+ type = prompt .type ,
523
+ conversation_timestamp = prompt .timestamp ,
524
+ total_alerts = total_alerts_row .total_alerts ,
525
+ token_usage_agg = ws_token_usage ,
480
526
)
481
- return conversations
527
+
528
+ conversation_summaries .append (conversation_summary )
529
+
530
+ return v1_models .PaginatedMessagesResponse (
531
+ data = conversation_summaries ,
532
+ limit = page_size ,
533
+ offset = (page - 1 ) * page_size ,
534
+ total = total_count ,
535
+ )
536
+
537
+
538
+ @v1 .get (
539
+ "/workspaces/{workspace_name}/messages/{prompt_id}" ,
540
+ tags = ["Workspaces" ],
541
+ generate_unique_id_function = uniq_name ,
542
+ )
543
+ async def get_messages_by_prompt_id (
544
+ workspace_name : str ,
545
+ prompt_id : str ,
546
+ ) -> List [v1_models .Conversation ]:
547
+ """Get messages for a workspace."""
548
+ try :
549
+ ws = await wscrud .get_workspace_by_name (workspace_name )
550
+ except crud .WorkspaceDoesNotExistError :
551
+ raise HTTPException (status_code = 404 , detail = "Workspace does not exist" )
482
552
except Exception :
483
- logger .exception ("Error while getting messages " )
553
+ logger .exception ("Error while getting workspace " )
484
554
raise HTTPException (status_code = 500 , detail = "Internal server error" )
485
555
556
+ prompts_outputs = await dbreader .get_prompts_with_output (
557
+ workspace_id = ws .id , prompt_id = prompt_id
558
+ )
559
+ conversations , _ = await v1_processing .parse_messages_in_conversations (prompts_outputs )
560
+ return conversations
561
+
486
562
487
563
@v1 .get (
488
564
"/workspaces/{workspace_name}/custom-instructions" ,
@@ -665,7 +741,7 @@ async def get_workspace_token_usage(workspace_name: str) -> v1_models.TokenUsage
665
741
raise HTTPException (status_code = 500 , detail = "Internal server error" )
666
742
667
743
try :
668
- prompts_outputs = await dbreader .get_prompts_with_output (ws .id )
744
+ prompts_outputs = await dbreader .get_prompts_with_output (worskpace_id = ws .id )
669
745
ws_token_usage = await v1_processing .parse_workspace_token_usage (prompts_outputs )
670
746
return ws_token_usage
671
747
except Exception :
0 commit comments