GuglielmoTor commited on
Commit
6b39ad4
·
verified ·
1 Parent(s): b55c420

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +59 -128
app.py CHANGED
@@ -49,9 +49,9 @@ except ImportError as e:
49
  AGENTIC_MODULES_LOADED = False
50
  # Placeholder functions to prevent app from crashing if imports fail
51
  def load_and_display_agentic_results(*args, **kwargs):
52
- return "Modules not loaded.", gr.update(), "Modules not loaded.", "Modules not loaded.", None, [], [], "Error"
53
  def fetch_and_reconstruct_data_from_bubble(*args, **kwargs):
54
- return None
55
  def format_report_for_display(report_data):
56
  return "Agentic modules not loaded. Report display unavailable."
57
  def extract_key_results_for_selection(okr_data):
@@ -84,7 +84,6 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
84
  "bubble_mentions_df": pd.DataFrame(), "bubble_follower_stats_df": pd.DataFrame(),
85
  "bubble_agentic_analysis_data": pd.DataFrame(), # To store agentic results from Bubble
86
  "url_user_token_temp_storage": None,
87
- # Config values remain useful for display components
88
  "config_date_col_posts": "published_at", "config_date_col_mentions": "date",
89
  "config_date_col_followers": "date", "config_media_type_col": "media_type",
90
  "config_eb_labels_col": "li_eb_label"
@@ -96,29 +95,27 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
96
  plot_data_for_chatbot_st = gr.State({})
97
 
98
  # States for agentic results display
99
- orchestration_raw_results_st = gr.State(None) # Stores reconstructed report/OKR dict from Bubble
100
- key_results_for_selection_st = gr.State([]) # Stores list of dicts for KR selection
101
- selected_key_result_ids_st = gr.State([]) # Stores unique_kr_ids selected by the user
 
 
 
 
102
 
103
  # --- UI LAYOUT ---
104
  gr.Markdown("# 🚀 LinkedIn Organization Dashboard")
105
- # Hidden components to receive URL parameters
106
  url_user_token_display = gr.Textbox(label="User Token (Hidden)", interactive=False, visible=False)
107
  org_urn_display = gr.Textbox(label="Org URN (Hidden)", interactive=False, visible=False)
108
- # General status display
109
  status_box = gr.Textbox(label="Status", interactive=False, value="Initializing...")
110
 
111
- # Load URL parameters on page load
112
  app.load(fn=get_url_user_token, inputs=None, outputs=[url_user_token_display, org_urn_display], api_name="get_url_params", show_progress=False)
113
 
114
- # UPDATED: Simplified initial data loading sequence
115
  def initial_data_load_sequence(url_token, org_urn_val, current_state):
116
- # This function now only loads data from Bubble and updates the main dashboard display
117
  status_msg, new_state = load_data_from_bubble(url_token, org_urn_val, current_state)
118
  dashboard_content = display_main_dashboard(new_state)
119
  return status_msg, new_state, dashboard_content
120
 
121
- # Instantiate the AnalyticsTab module (no changes needed here)
122
  analytics_icons = {'bomb': BOMB_ICON, 'explore': EXPLORE_ICON, 'formula': FORMULA_ICON, 'active': ACTIVE_ICON}
123
  analytics_tab_instance = AnalyticsTab(
124
  token_state=token_state,
@@ -135,23 +132,14 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
135
  fn_generate_llm_response=generate_llm_response
136
  )
137
 
138
- # --- MODIFIED: Comprehensive handler for report selection and OKR display ---
139
- def update_report_and_okr_display(selected_report_id: str, current_token_state: dict):
140
- """
141
- Finds the selected report in the state, formats its text for display,
142
- and crucially, fetches and reconstructs its associated OKRs and Tasks from Bubble.
143
- Returns a full set of UI updates for all agentic components.
144
- """
145
- # Define a default/error return tuple that matches the output components
146
  error_return_tuple = (
147
  gr.update(value="*Please select a report to view its details.*"),
148
  gr.update(choices=[], value=[], interactive=False),
149
  gr.update(value="*Please select a report to see OKRs.*"),
150
- None,
151
- [],
152
- []
153
  )
154
-
155
  if not selected_report_id:
156
  return error_return_tuple
157
 
@@ -165,49 +153,33 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
165
  return error_return_tuple
166
 
167
  selected_report_series = selected_report_series_df.iloc[0]
168
-
169
- # 1. Format the main report text
170
  report_markdown = format_report_for_display(selected_report_series)
171
 
172
- # 2. Fetch and reconstruct the full OKR data for the selected report
173
- reconstructed_data = fetch_and_reconstruct_data_from_bubble(selected_report_series)
174
 
175
- # 3. Prepare UI updates for the OKR section based on the reconstructed data
176
  if reconstructed_data:
177
  raw_results_state = reconstructed_data
178
  actionable_okrs_dict = reconstructed_data.get("actionable_okrs", {})
179
-
180
  all_krs_state = extract_key_results_for_selection(actionable_okrs_dict)
181
  if all_krs_state:
182
  kr_choices = [(kr['kr_description'], kr['unique_kr_id']) for kr in all_krs_state]
183
  key_results_cbg_update = gr.update(choices=kr_choices, value=[], interactive=True)
184
-
185
- # Format all OKRs for initial display
186
  okrs_list = actionable_okrs_dict.get("okrs", [])
187
- output_md_parts = [
188
- format_single_okr_for_display(okr_data, okr_main_index=okr_idx)
189
- for okr_idx, okr_data in enumerate(okrs_list)
190
- ]
191
- okr_details_md = "\n\n---\n\n".join(output_md_parts) if output_md_parts else "No OKRs are defined in this report."
192
  else:
193
  key_results_cbg_update = gr.update(choices=[], value=[], interactive=False)
194
- okr_details_md = "No Key Results were found for this report."
195
  all_krs_state = []
196
  else:
197
- # Handle case where reconstruction fails
198
  key_results_cbg_update = gr.update(choices=[], value=[], interactive=False)
199
- okr_details_md = "Error: Could not fetch or reconstruct OKR data for this report."
200
- raw_results_state = None
201
- all_krs_state = []
202
 
203
- # 4. Return the complete set of updates for the UI
204
  return (
205
- report_markdown,
206
- key_results_cbg_update,
207
- okr_details_md,
208
- raw_results_state,
209
- [], # Reset selected key results on new report selection
210
- all_krs_state
211
  )
212
 
213
  with gr.Tabs() as tabs:
@@ -215,71 +187,52 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
215
  gr.Markdown("I dati visualizzati in questo pannello sono caricati direttamente da Bubble.io.")
216
  dashboard_display_html = gr.HTML("<p style='text-align:center;'>Caricamento dashboard...</p>")
217
 
218
- # Use the AnalyticsTab module to create Tab 2
219
  analytics_tab_instance.create_tab_ui()
220
 
221
- # Tab 3: Agentic Analysis Report - MODIFIED
222
  with gr.TabItem("3️⃣ Agentic Analysis Report", id="tab_agentic_report", visible=AGENTIC_MODULES_LOADED):
223
  gr.Markdown("## 🤖 Comprehensive Analysis Report (from Bubble.io)")
224
  agentic_pipeline_status_md = gr.Markdown("Status: Loading report data...", visible=True)
225
- gr.Markdown("Questo report è stato pre-generato da un agente AI e caricato da Bubble.io. Seleziona un report dalla libreria per visualizzarlo.")
226
-
227
  with gr.Row():
228
- report_selector_dd = gr.Dropdown(
229
- label="Report Library",
230
- choices=[],
231
- interactive=True,
232
- info="Select a previously generated report to view its details."
233
- )
234
-
235
  agentic_report_display_md = gr.Markdown("Please select a report from the library to view it.")
236
-
237
  if not AGENTIC_MODULES_LOADED:
238
- gr.Markdown("🔴 **Error:** Agentic pipeline display modules could not be loaded. This tab is disabled.")
239
 
240
- # Tab 4: Agentic OKRs & Tasks
241
  with gr.TabItem("4️⃣ Agentic OKRs & Tasks", id="tab_agentic_okrs", visible=AGENTIC_MODULES_LOADED):
242
  gr.Markdown("## 🎯 AI Generated OKRs and Actionable Tasks (from Bubble.io)")
243
- gr.Markdown("Basato sull'analisi AI pre-generata, l'agente ha proposto i seguenti OKR. Seleziona i Key Results per dettagli.")
244
  if not AGENTIC_MODULES_LOADED:
245
- gr.Markdown("🔴 **Error:** Agentic pipeline display modules could not be loaded. This tab is disabled.")
246
  with gr.Row():
247
  with gr.Column(scale=1):
248
  gr.Markdown("### Suggested Key Results")
249
  key_results_cbg = gr.CheckboxGroup(label="Select Key Results", choices=[], value=[], interactive=True)
250
  with gr.Column(scale=3):
251
- gr.Markdown("### Detailed OKRs and Tasks for Selected Key Results")
252
- okr_detail_display_md = gr.Markdown("I dettagli OKR appariranno qui dopo il caricamento dei dati.")
253
-
254
- # This handler logic for the CheckboxGroup remains the same, as it operates on loaded data.
255
- def update_okr_display_on_selection(selected_kr_unique_ids: list, raw_orchestration_results: dict, all_krs_for_selection: list):
256
- if not raw_orchestration_results or not AGENTIC_MODULES_LOADED:
257
- return gr.update(value="Nessun dato di analisi caricato o moduli non disponibili.")
258
- actionable_okrs_dict = raw_orchestration_results.get("actionable_okrs")
259
- if not actionable_okrs_dict or not isinstance(actionable_okrs_dict.get("okrs"), list):
260
- return gr.update(value="Nessun OKR trovato nei dati di analisi caricati.")
261
-
262
- okrs_list = actionable_okrs_dict["okrs"]
263
- if not all_krs_for_selection or not isinstance(all_krs_for_selection, list):
264
- return gr.update(value="Errore interno: formato dati KR non valido.")
265
-
266
- kr_id_to_indices = {kr_info['unique_kr_id']: (kr_info['okr_index'], kr_info['kr_index']) for kr_info in all_krs_for_selection}
267
  selected_krs_by_okr_idx = defaultdict(list)
268
- if selected_kr_unique_ids:
269
- for kr_unique_id in selected_kr_unique_ids:
270
- if kr_unique_id in kr_id_to_indices:
271
- okr_idx, kr_idx = kr_id_to_indices[kr_unique_id]
272
  selected_krs_by_okr_idx[okr_idx].append(kr_idx)
273
-
274
- output_md_parts = []
275
- for okr_idx, okr_data in enumerate(okrs_list):
276
- if not selected_kr_unique_ids: # Show all if nothing is selected
277
- output_md_parts.append(format_single_okr_for_display(okr_data, accepted_kr_indices=None, okr_main_index=okr_idx))
278
- elif okr_idx in selected_krs_by_okr_idx: # Show only OKRs that have a selected KR
279
  accepted_indices = selected_krs_by_okr_idx.get(okr_idx)
280
- output_md_parts.append(format_single_okr_for_display(okr_data, accepted_kr_indices=accepted_indices, okr_main_index=okr_idx))
281
-
282
- final_md = "\n\n---\n\n".join(output_md_parts) if output_md_parts else "Nessun OKR corrisponde alla selezione corrente."
283
  return gr.update(value=final_md)
284
 
285
  if AGENTIC_MODULES_LOADED:
@@ -289,39 +242,25 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
289
  outputs=[okr_detail_display_md]
290
  )
291
 
292
- # --- MODIFIED: Event binding for the report selector dropdown ---
293
- # This now updates all agentic components, not just the report text.
294
  if AGENTIC_MODULES_LOADED:
295
- # Define the list of outputs that the handler function will update
296
  report_selection_outputs = [
297
- agentic_report_display_md,
298
- key_results_cbg,
299
- okr_detail_display_md,
300
- orchestration_raw_results_st,
301
- selected_key_result_ids_st,
302
- key_results_for_selection_st
303
  ]
304
  report_selector_dd.change(
305
  fn=update_report_and_okr_display,
306
- inputs=[report_selector_dd, token_state],
307
  outputs=report_selection_outputs,
308
  show_progress="minimal"
309
  )
310
 
311
- # --- EVENT HANDLING (SIMPLIFIED) ---
312
- # The output list for the initial agentic load
313
  agentic_display_outputs = [
314
- agentic_report_display_md,
315
- report_selector_dd,
316
- key_results_cbg,
317
- okr_detail_display_md,
318
- orchestration_raw_results_st,
319
- selected_key_result_ids_st,
320
- key_results_for_selection_st,
321
- agentic_pipeline_status_md
322
  ]
323
 
324
- # This is the main event chain that runs when the app loads
325
  initial_load_event = org_urn_display.change(
326
  fn=initial_data_load_sequence,
327
  inputs=[url_user_token_display, org_urn_display, token_state],
@@ -329,35 +268,27 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"),
329
  show_progress="full"
330
  )
331
 
332
- # After initial data is loaded, refresh the analytics graphs
333
  initial_load_event.then(
334
  fn=analytics_tab_instance._refresh_analytics_graphs_ui,
335
- inputs=[
336
- token_state,
337
- analytics_tab_instance.date_filter_selector,
338
- analytics_tab_instance.custom_start_date_picker,
339
- analytics_tab_instance.custom_end_date_picker,
340
- chat_histories_st
341
- ],
342
  outputs=analytics_tab_instance.graph_refresh_outputs_list,
343
  show_progress="full"
344
- # Then, load and display the pre-computed agentic results, including reconstructed OKRs
345
  ).then(
346
  fn=load_and_display_agentic_results,
347
- inputs=[token_state], # Inputs simplified as the function now gets everything from state
348
  outputs=agentic_display_outputs,
349
  show_progress="minimal"
350
  )
351
 
352
  if __name__ == "__main__":
353
- # Environment variable checks remain important
354
  if not os.environ.get(LINKEDIN_CLIENT_ID_ENV_VAR):
355
  logging.warning(f"WARNING: '{LINKEDIN_CLIENT_ID_ENV_VAR}' is not set.")
356
  if not all(os.environ.get(var) for var in [BUBBLE_APP_NAME_ENV_VAR, BUBBLE_API_KEY_PRIVATE_ENV_VAR, BUBBLE_API_ENDPOINT_ENV_VAR]):
357
  logging.warning("WARNING: One or more Bubble environment variables are not set.")
358
  if not AGENTIC_MODULES_LOADED:
359
- logging.warning("CRITICAL: Agentic pipeline display modules failed to load. Tabs 3 and 4 will be non-functional.")
360
  if not os.environ.get("GEMINI_API_KEY"):
361
- logging.warning("WARNING: 'GEMINI_API_KEY' is not set. This may be needed for chatbot features.")
362
 
363
  app.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)), debug=True)
 
49
  AGENTIC_MODULES_LOADED = False
50
  # Placeholder functions to prevent app from crashing if imports fail
51
  def load_and_display_agentic_results(*args, **kwargs):
52
+ return "Modules not loaded.", gr.update(), "Modules not loaded.", "Modules not loaded.", None, [], [], "Error", {}
53
  def fetch_and_reconstruct_data_from_bubble(*args, **kwargs):
54
+ return None, {}
55
  def format_report_for_display(report_data):
56
  return "Agentic modules not loaded. Report display unavailable."
57
  def extract_key_results_for_selection(okr_data):
 
84
  "bubble_mentions_df": pd.DataFrame(), "bubble_follower_stats_df": pd.DataFrame(),
85
  "bubble_agentic_analysis_data": pd.DataFrame(), # To store agentic results from Bubble
86
  "url_user_token_temp_storage": None,
 
87
  "config_date_col_posts": "published_at", "config_date_col_mentions": "date",
88
  "config_date_col_followers": "date", "config_media_type_col": "media_type",
89
  "config_eb_labels_col": "li_eb_label"
 
95
  plot_data_for_chatbot_st = gr.State({})
96
 
97
  # States for agentic results display
98
+ orchestration_raw_results_st = gr.State(None)
99
+ key_results_for_selection_st = gr.State([])
100
+ selected_key_result_ids_st = gr.State([])
101
+
102
+ # --- NEW: Session-specific cache for reconstructed OKR data ---
103
+ reconstruction_cache_st = gr.State({})
104
+
105
 
106
  # --- UI LAYOUT ---
107
  gr.Markdown("# 🚀 LinkedIn Organization Dashboard")
 
108
  url_user_token_display = gr.Textbox(label="User Token (Hidden)", interactive=False, visible=False)
109
  org_urn_display = gr.Textbox(label="Org URN (Hidden)", interactive=False, visible=False)
 
110
  status_box = gr.Textbox(label="Status", interactive=False, value="Initializing...")
111
 
 
112
  app.load(fn=get_url_user_token, inputs=None, outputs=[url_user_token_display, org_urn_display], api_name="get_url_params", show_progress=False)
113
 
 
114
  def initial_data_load_sequence(url_token, org_urn_val, current_state):
 
115
  status_msg, new_state = load_data_from_bubble(url_token, org_urn_val, current_state)
116
  dashboard_content = display_main_dashboard(new_state)
117
  return status_msg, new_state, dashboard_content
118
 
 
119
  analytics_icons = {'bomb': BOMB_ICON, 'explore': EXPLORE_ICON, 'formula': FORMULA_ICON, 'active': ACTIVE_ICON}
120
  analytics_tab_instance = AnalyticsTab(
121
  token_state=token_state,
 
132
  fn_generate_llm_response=generate_llm_response
133
  )
134
 
135
+ # --- MODIFIED: Handler now uses the session cache ---
136
+ def update_report_and_okr_display(selected_report_id: str, current_token_state: dict, session_cache: dict):
 
 
 
 
 
 
137
  error_return_tuple = (
138
  gr.update(value="*Please select a report to view its details.*"),
139
  gr.update(choices=[], value=[], interactive=False),
140
  gr.update(value="*Please select a report to see OKRs.*"),
141
+ None, [], [], session_cache # Pass cache back unchanged
 
 
142
  )
 
143
  if not selected_report_id:
144
  return error_return_tuple
145
 
 
153
  return error_return_tuple
154
 
155
  selected_report_series = selected_report_series_df.iloc[0]
 
 
156
  report_markdown = format_report_for_display(selected_report_series)
157
 
158
+ # Use the session cache
159
+ reconstructed_data, updated_cache = fetch_and_reconstruct_data_from_bubble(selected_report_series, session_cache)
160
 
 
161
  if reconstructed_data:
162
  raw_results_state = reconstructed_data
163
  actionable_okrs_dict = reconstructed_data.get("actionable_okrs", {})
 
164
  all_krs_state = extract_key_results_for_selection(actionable_okrs_dict)
165
  if all_krs_state:
166
  kr_choices = [(kr['kr_description'], kr['unique_kr_id']) for kr in all_krs_state]
167
  key_results_cbg_update = gr.update(choices=kr_choices, value=[], interactive=True)
 
 
168
  okrs_list = actionable_okrs_dict.get("okrs", [])
169
+ output_md_parts = [format_single_okr_for_display(okr, okr_main_index=i) for i, okr in enumerate(okrs_list)]
170
+ okr_details_md = "\n\n---\n\n".join(output_md_parts) if output_md_parts else "No OKRs defined."
 
 
 
171
  else:
172
  key_results_cbg_update = gr.update(choices=[], value=[], interactive=False)
173
+ okr_details_md = "No Key Results found for this report."
174
  all_krs_state = []
175
  else:
 
176
  key_results_cbg_update = gr.update(choices=[], value=[], interactive=False)
177
+ okr_details_md = "Error: Could not fetch or reconstruct OKR data."
178
+ raw_results_state, all_krs_state = None, []
 
179
 
 
180
  return (
181
+ report_markdown, key_results_cbg_update, okr_details_md,
182
+ raw_results_state, [], all_krs_state, updated_cache
 
 
 
 
183
  )
184
 
185
  with gr.Tabs() as tabs:
 
187
  gr.Markdown("I dati visualizzati in questo pannello sono caricati direttamente da Bubble.io.")
188
  dashboard_display_html = gr.HTML("<p style='text-align:center;'>Caricamento dashboard...</p>")
189
 
 
190
  analytics_tab_instance.create_tab_ui()
191
 
 
192
  with gr.TabItem("3️⃣ Agentic Analysis Report", id="tab_agentic_report", visible=AGENTIC_MODULES_LOADED):
193
  gr.Markdown("## 🤖 Comprehensive Analysis Report (from Bubble.io)")
194
  agentic_pipeline_status_md = gr.Markdown("Status: Loading report data...", visible=True)
195
+ gr.Markdown("Questo report è stato pre-generato. Seleziona un report dalla libreria per visualizzarlo.")
 
196
  with gr.Row():
197
+ report_selector_dd = gr.Dropdown(label="Report Library", choices=[], interactive=True, info="Select a report.")
 
 
 
 
 
 
198
  agentic_report_display_md = gr.Markdown("Please select a report from the library to view it.")
 
199
  if not AGENTIC_MODULES_LOADED:
200
+ gr.Markdown("🔴 **Error:** Agentic modules could not be loaded.")
201
 
 
202
  with gr.TabItem("4️⃣ Agentic OKRs & Tasks", id="tab_agentic_okrs", visible=AGENTIC_MODULES_LOADED):
203
  gr.Markdown("## 🎯 AI Generated OKRs and Actionable Tasks (from Bubble.io)")
204
+ gr.Markdown("Basato sull'analisi AI, l'agente ha proposto i seguenti OKR. Seleziona i Key Results per dettagli.")
205
  if not AGENTIC_MODULES_LOADED:
206
+ gr.Markdown("🔴 **Error:** Agentic modules could not be loaded.")
207
  with gr.Row():
208
  with gr.Column(scale=1):
209
  gr.Markdown("### Suggested Key Results")
210
  key_results_cbg = gr.CheckboxGroup(label="Select Key Results", choices=[], value=[], interactive=True)
211
  with gr.Column(scale=3):
212
+ gr.Markdown("### Detailed OKRs and Tasks")
213
+ okr_detail_display_md = gr.Markdown("I dettagli OKR appariranno qui.")
214
+
215
+ def update_okr_display_on_selection(selected_kr_ids: list, raw_results: dict, all_krs: list):
216
+ if not raw_results or not AGENTIC_MODULES_LOADED:
217
+ return gr.update(value="Nessun dato di analisi caricato.")
218
+ actionable_okrs = raw_results.get("actionable_okrs")
219
+ if not actionable_okrs or not isinstance(actionable_okrs.get("okrs"), list):
220
+ return gr.update(value="Nessun OKR trovato.")
221
+ okrs_list, kr_id_map = actionable_okrs["okrs"], {kr['unique_kr_id']: (kr['okr_index'], kr['kr_index']) for kr in all_krs}
 
 
 
 
 
 
222
  selected_krs_by_okr_idx = defaultdict(list)
223
+ if selected_kr_ids:
224
+ for kr_id in selected_kr_ids:
225
+ if kr_id in kr_id_map:
226
+ okr_idx, kr_idx = kr_id_map[kr_id]
227
  selected_krs_by_okr_idx[okr_idx].append(kr_idx)
228
+ output_parts = []
229
+ for okr_idx, okr in enumerate(okrs_list):
230
+ if not selected_kr_ids:
231
+ output_parts.append(format_single_okr_for_display(okr, okr_main_index=okr_idx))
232
+ elif okr_idx in selected_krs_by_okr_idx:
 
233
  accepted_indices = selected_krs_by_okr_idx.get(okr_idx)
234
+ output_parts.append(format_single_okr_for_display(okr, accepted_kr_indices=accepted_indices, okr_main_index=okr_idx))
235
+ final_md = "\n\n---\n\n".join(output_parts) if output_parts else "Nessun OKR corrisponde alla selezione."
 
236
  return gr.update(value=final_md)
237
 
238
  if AGENTIC_MODULES_LOADED:
 
242
  outputs=[okr_detail_display_md]
243
  )
244
 
 
 
245
  if AGENTIC_MODULES_LOADED:
 
246
  report_selection_outputs = [
247
+ agentic_report_display_md, key_results_cbg, okr_detail_display_md,
248
+ orchestration_raw_results_st, selected_key_result_ids_st,
249
+ key_results_for_selection_st, reconstruction_cache_st # Pass cache state back
 
 
 
250
  ]
251
  report_selector_dd.change(
252
  fn=update_report_and_okr_display,
253
+ inputs=[report_selector_dd, token_state, reconstruction_cache_st], # Pass cache state in
254
  outputs=report_selection_outputs,
255
  show_progress="minimal"
256
  )
257
 
 
 
258
  agentic_display_outputs = [
259
+ agentic_report_display_md, report_selector_dd, key_results_cbg,
260
+ okr_detail_display_md, orchestration_raw_results_st, selected_key_result_ids_st,
261
+ key_results_for_selection_st, agentic_pipeline_status_md, reconstruction_cache_st # Pass cache state back
 
 
 
 
 
262
  ]
263
 
 
264
  initial_load_event = org_urn_display.change(
265
  fn=initial_data_load_sequence,
266
  inputs=[url_user_token_display, org_urn_display, token_state],
 
268
  show_progress="full"
269
  )
270
 
 
271
  initial_load_event.then(
272
  fn=analytics_tab_instance._refresh_analytics_graphs_ui,
273
+ inputs=[token_state, analytics_tab_instance.date_filter_selector, analytics_tab_instance.custom_start_date_picker,
274
+ analytics_tab_instance.custom_end_date_picker, chat_histories_st],
 
 
 
 
 
275
  outputs=analytics_tab_instance.graph_refresh_outputs_list,
276
  show_progress="full"
 
277
  ).then(
278
  fn=load_and_display_agentic_results,
279
+ inputs=[token_state, reconstruction_cache_st], # Pass cache state in
280
  outputs=agentic_display_outputs,
281
  show_progress="minimal"
282
  )
283
 
284
  if __name__ == "__main__":
 
285
  if not os.environ.get(LINKEDIN_CLIENT_ID_ENV_VAR):
286
  logging.warning(f"WARNING: '{LINKEDIN_CLIENT_ID_ENV_VAR}' is not set.")
287
  if not all(os.environ.get(var) for var in [BUBBLE_APP_NAME_ENV_VAR, BUBBLE_API_KEY_PRIVATE_ENV_VAR, BUBBLE_API_ENDPOINT_ENV_VAR]):
288
  logging.warning("WARNING: One or more Bubble environment variables are not set.")
289
  if not AGENTIC_MODULES_LOADED:
290
+ logging.warning("CRITICAL: Agentic modules failed to load.")
291
  if not os.environ.get("GEMINI_API_KEY"):
292
+ logging.warning("WARNING: 'GEMINI_API_KEY' is not set.")
293
 
294
  app.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)), debug=True)