GuglielmoTor commited on
Commit
d575454
·
verified ·
1 Parent(s): d3914e5

Create agentic_handlers.py

Browse files
Files changed (1) hide show
  1. services/agentic_handlers.py +278 -0
services/agentic_handlers.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # handlers/agentic_handlers.py
2
+ import gradio as gr
3
+ import logging
4
+ from collections import defaultdict
5
+
6
+ # Attempt to import agentic pipeline functions and UI formatters
7
+ try:
8
+ from run_agentic_pipeline import run_full_analytics_orchestration
9
+ from ui.insights_ui_generator import (
10
+ format_report_to_markdown,
11
+ extract_key_results_for_selection,
12
+ format_single_okr_for_display
13
+ )
14
+ AGENTIC_MODULES_LOADED = True
15
+ except ImportError as e:
16
+ logging.error(f"Could not import agentic pipeline modules for AgenticHandlers: {e}.")
17
+ AGENTIC_MODULES_LOADED = False
18
+ # Define placeholder functions if modules are not loaded to avoid NameErrors during class definition
19
+ async def run_full_analytics_orchestration(*args, **kwargs): return None
20
+ def format_report_to_markdown(report_string): return "Agentic modules not loaded. Report unavailable."
21
+ def extract_key_results_for_selection(okrs_dict): return []
22
+ def format_single_okr_for_display(okr_data, **kwargs): return "Agentic modules not loaded. OKR display unavailable."
23
+
24
+
25
+ class AgenticHandlers:
26
+ def __init__(self, agentic_report_components, agentic_okrs_components,
27
+ token_state_ref, orchestration_raw_results_st_ref,
28
+ key_results_for_selection_st_ref, selected_key_result_ids_st_ref):
29
+
30
+ self.report_components = agentic_report_components
31
+ self.okrs_components = agentic_okrs_components
32
+
33
+ # References to global states
34
+ self.token_state = token_state_ref
35
+ self.orchestration_raw_results_st = orchestration_raw_results_st_ref
36
+ self.key_results_for_selection_st = key_results_for_selection_st_ref
37
+ self.selected_key_result_ids_st = selected_key_result_ids_st_ref # Though this is updated by CBG, might be read
38
+
39
+ self.agentic_modules_really_loaded = AGENTIC_MODULES_LOADED # Store the flag
40
+ logging.info(f"AgenticHandlers initialized. Modules loaded: {self.agentic_modules_really_loaded}")
41
+
42
+ async def run_agentic_pipeline_autonomously_on_update(self, current_token_state_val):
43
+ """
44
+ This function is intended to be triggered by changes in token_state
45
+ (e.g., after initial load or after sync).
46
+ It yields updates for the agentic report and OKR tabs.
47
+ """
48
+ logging.info(f"Agentic pipeline auto-trigger. Token: {'Set' if current_token_state_val.get('token') else 'Not Set'}")
49
+
50
+ # Initial "waiting" status updates
51
+ initial_report_status = "Pipeline AI: In attesa dei dati necessari..."
52
+ initial_okr_choices = []
53
+ initial_okr_value = []
54
+ initial_okr_interactive = False
55
+ initial_okr_details = "Pipeline AI: In attesa dei dati necessari..."
56
+ initial_orchestration_results = self.orchestration_raw_results_st.value # Preserve if re-running
57
+ initial_selected_krs = self.selected_key_result_ids_st.value
58
+ initial_krs_for_selection = self.key_results_for_selection_st.value
59
+
60
+ # Check if components exist (in case tabs were conditionally not fully rendered)
61
+ report_status_md_update = gr.update(value=initial_report_status) if self.report_components.get("agentic_pipeline_status_md") else gr.update()
62
+ report_display_md_update = gr.update() # No change to report display yet
63
+
64
+ okrs_cbg_update = gr.update(choices=initial_okr_choices, value=initial_okr_value, interactive=initial_okr_interactive) if self.okrs_components.get("key_results_cbg") else gr.update()
65
+ okrs_detail_md_update = gr.update(value=initial_okr_details) if self.okrs_components.get("okr_detail_display_md") else gr.update()
66
+
67
+ if not current_token_state_val or not current_token_state_val.get("token"):
68
+ logging.info("Agentic pipeline: Token not available in token_state. Skipping actual run.")
69
+ yield (
70
+ report_status_md_update, # For agentic_pipeline_status_md
71
+ report_display_md_update, # For agentic_report_display_md (no change yet)
72
+ okrs_cbg_update, # For key_results_cbg
73
+ okrs_detail_md_update, # For okr_detail_display_md
74
+ initial_orchestration_results, # For orchestration_raw_results_st
75
+ initial_selected_krs, # For selected_key_result_ids_st
76
+ initial_krs_for_selection # For key_results_for_selection_st
77
+ )
78
+ return
79
+
80
+ # Update status to "in progress"
81
+ in_progress_status = "Analisi AI (Sempre) in corso..."
82
+ if self.report_components.get("agentic_pipeline_status_md"):
83
+ report_status_md_update = gr.update(value=in_progress_status)
84
+ if self.okrs_components.get("okr_detail_display_md"): # Also update OKR detail placeholder
85
+ okrs_detail_md_update = gr.update(value="Dettagli OKR (Sempre) in corso di generazione...")
86
+
87
+ yield (
88
+ report_status_md_update, report_display_md_update, okrs_cbg_update, okrs_detail_md_update,
89
+ initial_orchestration_results, initial_selected_krs, initial_krs_for_selection
90
+ )
91
+
92
+ if not self.agentic_modules_really_loaded:
93
+ logging.warning("Agentic modules not loaded. Skipping autonomous pipeline actual run.")
94
+ error_status = "Moduli AI non caricati. Operazione non disponibile."
95
+ if self.report_components.get("agentic_pipeline_status_md"):
96
+ report_status_md_update = gr.update(value=error_status)
97
+ if self.report_components.get("agentic_report_display_md"):
98
+ report_display_md_update = gr.update(value=error_status) # Update report display too
99
+ if self.okrs_components.get("okr_detail_display_md"):
100
+ okrs_detail_md_update = gr.update(value=error_status) # Update OKR detail too
101
+
102
+ yield (
103
+ report_status_md_update, report_display_md_update, okrs_cbg_update, okrs_detail_md_update,
104
+ None, [], [] # Reset states
105
+ )
106
+ return
107
+
108
+ try:
109
+ # Always use "Sempre" filter for the autonomous agentic pipeline
110
+ date_filter_val_agentic = "Sempre"
111
+ custom_start_val_agentic = None
112
+ custom_end_val_agentic = None
113
+
114
+ logging.info("Agentic pipeline: Calling run_full_analytics_orchestration...")
115
+ orchestration_output = await run_full_analytics_orchestration(
116
+ current_token_state_val,
117
+ date_filter_val_agentic,
118
+ custom_start_val_agentic,
119
+ custom_end_val_agentic
120
+ )
121
+
122
+ final_status_text = "Pipeline AI (Sempre) completata."
123
+ logging.info(f"Autonomous agentic pipeline finished. Output keys: {orchestration_output.keys() if orchestration_output else 'None'}")
124
+
125
+ orchestration_results_update_val = None
126
+ selected_krs_update_val = []
127
+ krs_for_selection_update_val = []
128
+
129
+ if orchestration_output:
130
+ orchestration_results_update_val = orchestration_output # Store the raw output
131
+
132
+ report_str = orchestration_output.get('comprehensive_analysis_report', "Nessun report testuale fornito.")
133
+ if self.report_components.get("agentic_report_display_md"):
134
+ report_display_md_update = gr.update(value=format_report_to_markdown(report_str))
135
+
136
+ actionable_okrs = orchestration_output.get('actionable_okrs_and_tasks')
137
+ krs_for_ui_selection_list = extract_key_results_for_selection(actionable_okrs)
138
+ krs_for_selection_update_val = krs_for_ui_selection_list # Store for CBG change handler
139
+
140
+ kr_choices_for_cbg = [(kr['kr_description'], kr['unique_kr_id']) for kr in krs_for_ui_selection_list]
141
+ if self.okrs_components.get("key_results_cbg"):
142
+ okrs_cbg_update = gr.update(choices=kr_choices_for_cbg, value=[], interactive=True)
143
+
144
+ # Display all OKRs initially (before any KR selection)
145
+ all_okrs_md_parts = []
146
+ if actionable_okrs and isinstance(actionable_okrs.get("okrs"), list):
147
+ for okr_idx, okr_item in enumerate(actionable_okrs["okrs"]):
148
+ all_okrs_md_parts.append(format_single_okr_for_display(okr_item, accepted_kr_indices=None, okr_main_index=okr_idx))
149
+
150
+ if not all_okrs_md_parts:
151
+ if self.okrs_components.get("okr_detail_display_md"):
152
+ okrs_detail_md_update = gr.update(value="Nessun OKR generato o trovato (Sempre).")
153
+ else:
154
+ if self.okrs_components.get("okr_detail_display_md"):
155
+ okrs_detail_md_update = gr.update(value="\n\n---\n\n".join(all_okrs_md_parts))
156
+
157
+ selected_krs_update_val = [] # Reset selection
158
+ else: # No output from pipeline
159
+ final_status_text = "Pipeline AI (Sempre): Nessun risultato prodotto."
160
+ if self.report_components.get("agentic_report_display_md"):
161
+ report_display_md_update = gr.update(value="Nessun report generato dalla pipeline AI (Sempre).")
162
+ if self.okrs_components.get("key_results_cbg"):
163
+ okrs_cbg_update = gr.update(choices=[], value=[], interactive=False)
164
+ if self.okrs_components.get("okr_detail_display_md"):
165
+ okrs_detail_md_update = gr.update(value="Nessun OKR generato o errore nella pipeline AI (Sempre).")
166
+
167
+ if self.report_components.get("agentic_pipeline_status_md"):
168
+ report_status_md_update = gr.update(value=final_status_text)
169
+
170
+ yield (
171
+ report_status_md_update, report_display_md_update, okrs_cbg_update, okrs_detail_md_update,
172
+ orchestration_results_update_val, selected_krs_update_val, krs_for_selection_update_val
173
+ )
174
+
175
+ except Exception as e:
176
+ logging.error(f"Error during autonomous agentic pipeline execution: {e}", exc_info=True)
177
+ error_status_text = f"Errore pipeline AI (Sempre): {str(e)}"
178
+ if self.report_components.get("agentic_pipeline_status_md"):
179
+ report_status_md_update = gr.update(value=error_status_text)
180
+ if self.report_components.get("agentic_report_display_md"):
181
+ report_display_md_update = gr.update(value=f"Errore generazione report AI (Sempre): {str(e)}")
182
+ if self.okrs_components.get("key_results_cbg"):
183
+ okrs_cbg_update = gr.update(choices=[], value=[], interactive=False)
184
+ if self.okrs_components.get("okr_detail_display_md"):
185
+ okrs_detail_md_update = gr.update(value=f"Errore generazione OKR AI (Sempre): {str(e)}")
186
+
187
+ yield (
188
+ report_status_md_update, report_display_md_update, okrs_cbg_update, okrs_detail_md_update,
189
+ None, [], [] # Reset states on error
190
+ )
191
+
192
+ def update_okr_display_on_kr_selection(self, selected_kr_unique_ids: list,
193
+ raw_orchestration_results: dict,
194
+ all_krs_for_selection_list: list):
195
+ """
196
+ Updates the OKR detail display when Key Results are selected in the CheckboxGroup.
197
+ """
198
+ if not self.agentic_modules_really_loaded:
199
+ return gr.update(value="Moduli AI non caricati. Impossibile visualizzare i dettagli OKR.")
200
+ if not raw_orchestration_results:
201
+ return gr.update(value="Nessun dato dalla pipeline AI o moduli non caricati.")
202
+
203
+ actionable_okrs_dict = raw_orchestration_results.get("actionable_okrs_and_tasks")
204
+ if not actionable_okrs_dict or not isinstance(actionable_okrs_dict.get("okrs"), list):
205
+ return gr.update(value="Nessun OKR trovato nei risultati della pipeline.")
206
+
207
+ okrs_list = actionable_okrs_dict["okrs"]
208
+ if not okrs_list: # Should be caught by above, but defensive
209
+ return gr.update(value="Nessun OKR generato.")
210
+
211
+ # Create a mapping from unique_kr_id to its (okr_index, kr_index_within_okr)
212
+ kr_id_to_indices = {}
213
+ if all_krs_for_selection_list: # This list comes from extract_key_results_for_selection
214
+ for kr_info in all_krs_for_selection_list:
215
+ kr_id_to_indices[kr_info['unique_kr_id']] = (kr_info['okr_index'], kr_info['kr_index'])
216
+
217
+ # Group selected KR indices by their parent OKR index
218
+ selected_krs_by_okr_idx = defaultdict(list)
219
+ if selected_kr_unique_ids: # This is the list of unique_kr_ids from the checkboxgroup
220
+ for kr_unique_id in selected_kr_unique_ids:
221
+ if kr_unique_id in kr_id_to_indices:
222
+ okr_idx, kr_idx_in_okr = kr_id_to_indices[kr_unique_id]
223
+ selected_krs_by_okr_idx[okr_idx].append(kr_idx_in_okr)
224
+
225
+ output_md_parts = []
226
+ for okr_idx, okr_data in enumerate(okrs_list):
227
+ # If specific KRs are selected, only show OKRs that have at least one selected KR,
228
+ # and then format that OKR to only show its selected KRs.
229
+ # If no KRs are selected, show all OKRs with all their KRs.
230
+
231
+ accepted_indices_for_this_okr = selected_krs_by_okr_idx.get(okr_idx) # This will be a list of KR indices or None
232
+
233
+ if selected_kr_unique_ids: # If there's any selection active
234
+ if accepted_indices_for_this_okr is not None: # Only format/display if this OKR has selected KRs
235
+ formatted_okr_md = format_single_okr_for_display(
236
+ okr_data,
237
+ accepted_kr_indices=accepted_indices_for_this_okr,
238
+ okr_main_index=okr_idx
239
+ )
240
+ output_md_parts.append(formatted_okr_md)
241
+ else: # No KRs selected, display all OKRs fully
242
+ formatted_okr_md = format_single_okr_for_display(
243
+ okr_data,
244
+ accepted_kr_indices=None, # None means show all KRs for this OKR
245
+ okr_main_index=okr_idx
246
+ )
247
+ output_md_parts.append(formatted_okr_md)
248
+
249
+ if not output_md_parts and selected_kr_unique_ids:
250
+ final_md = "Nessun OKR corrisponde alla selezione corrente o i KR selezionati non hanno task dettagliati."
251
+ elif not output_md_parts and not selected_kr_unique_ids: # Should mean okrs_list was empty
252
+ final_md = "Nessun OKR generato."
253
+ else:
254
+ final_md = "\n\n---\n\n".join(output_md_parts)
255
+
256
+ return gr.update(value=final_md)
257
+
258
+ def setup_event_handlers(self):
259
+ """Sets up event handlers for the agentic OKRs tab."""
260
+ if not self.agentic_modules_really_loaded:
261
+ logging.warning("Agentic modules not loaded. Skipping agentic event handler setup.")
262
+ return
263
+
264
+ if self.okrs_components.get("key_results_cbg"):
265
+ self.okrs_components['key_results_cbg'].change(
266
+ fn=self.update_okr_display_on_kr_selection,
267
+ inputs=[
268
+ self.okrs_components['key_results_cbg'], # Current value of checkbox group
269
+ self.orchestration_raw_results_st, # State
270
+ self.key_results_for_selection_st # State
271
+ ],
272
+ outputs=[self.okrs_components['okr_detail_display_md']],
273
+ api_name="update_okr_display_on_kr_selection"
274
+ )
275
+ logging.info("Agentic OKR selection handler setup complete.")
276
+ else:
277
+ logging.warning("key_results_cbg component not found for agentic OKR handler setup.")
278
+