1616"""
1717
1818import logging
19+ import os
1920from datetime import datetime
2021from time import perf_counter
2122from typing import Optional , Union
2223from uuid import UUID , uuid4
2324
25+ from sqlalchemy import func
2426from sqlmodel import Session , select , desc
2527
2628from csv_data import get_csv_ticket_service
@@ -221,12 +223,14 @@ async def generate_draft(self, create_req: KBADraftCreate) -> KBADraft:
221223 extra = {"draft_id" : str (draft .id ), "ticket_id" : str (create_req .ticket_id )}
222224 )
223225 except Exception as e :
224- # Log error but continue - search questions are optional
225226 logger .warning (
226227 f"Failed to generate search questions: { str (e )} " ,
227228 extra = {"draft_id" : str (draft .id ), "error" : str (e )}
228229 )
229230 draft .search_questions = []
231+ draft .generation_warnings .append (
232+ f"Search questions generation failed: { str (e )} "
233+ )
230234
231235 # 7. Save to database
232236 draft_table = self ._draft_to_table (draft )
@@ -557,8 +561,9 @@ def list_drafts(self, filters: KBADraftFilter) -> KBADraftListResponse:
557561 if filters .incident_id :
558562 statement = statement .where (KBADraftTable .incident_id == filters .incident_id )
559563
560- # Count total
561- total = len (self .session .exec (statement ).all ())
564+ # Count total using SQL COUNT(*)
565+ count_statement = select (func .count ()).select_from (statement .subquery ())
566+ total = self .session .exec (count_statement ).one ()
562567
563568 # Apply pagination
564569 statement = statement .offset (filters .offset ).limit (filters .limit )
@@ -981,23 +986,31 @@ def _get_adapter_config(self, target_system: str) -> dict:
981986 "create_categories" : True
982987 },
983988 "sharepoint" : {
984- "site_url" : "https://example.sharepoint.com/sites/KB" ,
985- "client_id" : "..." , # TODO: Load from env
986- "client_secret" : "..." # TODO: Load from env
989+ "site_url" : os . environ . get ( "KB_SHAREPOINT_SITE_URL" , "" ) ,
990+ "client_id" : os . environ . get ( "KB_SHAREPOINT_CLIENT_ID" , "" ),
991+ "client_secret" : os . environ . get ( "KB_SHAREPOINT_CLIENT_SECRET" , "" ),
987992 },
988993 "itsm" : {
989- "instance_url" : "https://example.service-now.com" ,
990- "username" : "..." , # TODO: Load from env
991- "password" : "..." # TODO: Load from env
994+ "instance_url" : os . environ . get ( "KB_ITSM_INSTANCE_URL" , "" ) ,
995+ "username" : os . environ . get ( "KB_ITSM_USERNAME" , "" ),
996+ "password" : os . environ . get ( "KB_ITSM_PASSWORD" , "" ),
992997 },
993998 "confluence" : {
994- "base_url" : "https://example.atlassian.net" ,
995- "username" : "..." , # TODO: Load from env
996- "api_token" : "..." # TODO: Load from env
999+ "base_url" : os . environ . get ( "KB_CONFLUENCE_BASE_URL" , "" ) ,
1000+ "username" : os . environ . get ( "KB_CONFLUENCE_USERNAME" , "" ),
1001+ "api_token" : os . environ . get ( "KB_CONFLUENCE_API_TOKEN" , "" ),
9971002 }
9981003 }
9991004
1000- return configs .get (target_system , {})
1005+ config = configs .get (target_system , {})
1006+ if target_system != "file" and config :
1007+ missing = [k for k , v in config .items () if not v ]
1008+ if missing :
1009+ raise NotImplementedError (
1010+ f"Adapter '{ target_system } ' requires environment variables: "
1011+ f"{ ', ' .join (f'KB_{ target_system .upper ()} _{ k .upper ()} ' for k in missing )} "
1012+ )
1013+ return config
10011014
10021015 def _draft_to_table (self , draft : KBADraft ) -> KBADraftTable :
10031016 """Convert KBADraft to KBADraftTable for persistence"""
@@ -1024,6 +1037,7 @@ def _draft_to_table(self, draft: KBADraft) -> KBADraftTable:
10241037 tags = draft .tags ,
10251038 related_tickets = draft .related_tickets ,
10261039 search_questions = draft .search_questions if draft .search_questions is not None else [],
1040+ generation_warnings = draft .generation_warnings if draft .generation_warnings is not None else [],
10271041 guidelines_used = draft .guidelines_used ,
10281042 status = draft .status .value ,
10291043 created_at = draft .created_at ,
@@ -1055,6 +1069,7 @@ def _table_to_draft(self, table: KBADraftTable) -> KBADraft:
10551069 tags = table .tags ,
10561070 related_tickets = table .related_tickets ,
10571071 search_questions = table .search_questions if hasattr (table , 'search_questions' ) and table .search_questions is not None else [],
1072+ generation_warnings = table .generation_warnings if hasattr (table , 'generation_warnings' ) and table .generation_warnings is not None else [],
10581073 guidelines_used = table .guidelines_used ,
10591074 status = KBADraftStatus (table .status ),
10601075 created_at = table .created_at ,
0 commit comments