SyedZaid-Bin-Haris commited on
Commit
80598b3
·
verified ·
1 Parent(s): 9001795

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +344 -64
app.py CHANGED
@@ -123,6 +123,53 @@ def main():
123
  except Exception as e:
124
  return None, f"Error retrieving outline data: {str(e)}"
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  # Helper function to extract outline from potentially nested structure
127
  def extract_outline_from_data(data):
128
  """Extract outline data from potentially nested structures"""
@@ -142,6 +189,26 @@ def main():
142
 
143
  # Return the original if we can't determine the structure
144
  return data
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
 
146
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange")) as demo:
147
  # Header
@@ -173,9 +240,34 @@ def main():
173
  with gr.Row():
174
  load_button = gr.Button("Load Outline")
175
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  # Synthesis status display
177
  with gr.Row(visible=False) as status_panel:
178
- gr.Markdown("## Current Outline Status")
179
 
180
  with gr.Column():
181
  status_query = gr.Textbox(label="Query")
@@ -191,7 +283,7 @@ def main():
191
  # Step Status Card
192
  steps_container = gr.Row(visible=False)
193
  with steps_container:
194
- gr.Markdown("## Outline Status")
195
 
196
  with gr.Group():
197
  gr.Markdown("### Outline Generator")
@@ -200,8 +292,17 @@ def main():
200
  outline_retry = gr.Button("Retry", size="sm", variant="primary")
201
  outline_view = gr.Button("View Results", size="sm")
202
  outline_download = gr.Button("Download", size="sm")
 
 
 
 
 
 
 
 
 
203
 
204
- # Result Preview
205
  with gr.Row(visible=False) as result_panel:
206
  gr.Markdown("## Outline Preview")
207
  with gr.Column():
@@ -223,6 +324,28 @@ def main():
223
  refresh_results = gr.Button("Refresh Results")
224
  download_results = gr.Button("Download Results")
225
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  # Log panel
227
  with gr.Row(visible=False) as log_panel:
228
  gr.Markdown("## Process Log")
@@ -236,7 +359,7 @@ def main():
236
  # Function for generating a new outline
237
  def generate_new_outline(query):
238
  if not query.strip():
239
- return "Please enter a query first", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), ""
240
 
241
  # Generate a timestamp-based ID (in real implementation, this would match your AWS naming pattern)
242
  timestamp = str(int(time.time()))
@@ -256,13 +379,31 @@ def main():
256
  datetime.now().strftime("%Y-%m-%d %H:%M"),
257
  datetime.now().strftime("%Y-%m-%d %H:%M"),
258
  0.00,
259
- "🟡 **In Progress**..."
 
260
  )
261
 
262
- # Function for loading existing outline - FIX: Return all required values even in error case
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  def load_existing(existing_id):
264
  if not existing_id.strip():
265
- # Return all 10 required outputs even in error case
266
  return (
267
  gr.update(visible=False), # status_panel
268
  gr.update(visible=False), # steps_container
@@ -273,25 +414,29 @@ def main():
273
  "", # status_created
274
  "", # status_updated
275
  0.0, # status_cost
276
- "❌ **Error**" # outline_status
 
277
  )
278
 
279
  # Now we actually fetch the data from AWS S3
280
- outline_data, message = fetch_outline_data(existing_id)
 
 
281
 
282
  if not outline_data:
283
- # Return all 10 required outputs even in error case
284
  return (
285
  gr.update(visible=False), # status_panel
286
  gr.update(visible=False), # steps_container
287
  gr.update(visible=False), # log_panel
288
- f"Error: {message}", # log_output
289
  "", # status_query
290
  existing_id, # status_id
291
  "", # status_created
292
  "", # status_updated
293
  0.0, # status_cost
294
- "❌ **Error**" # outline_status
 
295
  )
296
 
297
  # Extract the actual outline
@@ -300,7 +445,7 @@ def main():
300
  # Extract query from ID (assuming ID format: timestamp_formatted_query)
301
  parts = existing_id.split('_', 1)
302
  if len(parts) < 2:
303
- # Return all 10 required outputs even in error case
304
  return (
305
  gr.update(visible=False), # status_panel
306
  gr.update(visible=False), # steps_container
@@ -311,7 +456,8 @@ def main():
311
  "", # status_created
312
  "", # status_updated
313
  0.0, # status_cost
314
- "❌ **Error**" # outline_status
 
315
  )
316
 
317
  # Reconstruct the original query
@@ -323,6 +469,14 @@ def main():
323
  # Determine actual status based on outline data
324
  outline_status_text = "✅ **Completed**" # Default to completed if we found data
325
 
 
 
 
 
 
 
 
 
326
  # Get creation time from timestamp in ID
327
  try:
328
  creation_time = datetime.fromtimestamp(int(parts[0])).strftime("%Y-%m-%d %H:%M")
@@ -339,50 +493,35 @@ def main():
339
  gr.update(visible=True),
340
  gr.update(visible=True),
341
  gr.update(visible=True),
342
- f"[{log_timestamp}] Loaded outline with ID: {existing_id}\n[{log_timestamp}] {message}\n",
343
  original_query,
344
  existing_id,
345
  creation_time,
346
  datetime.now().strftime("%Y-%m-%d %H:%M"), # Last updated is now
347
  cost,
348
- outline_status_text
 
349
  )
350
 
351
- # Connect the handlers
352
- create_button.click(
353
- fn=generate_new_outline,
354
- inputs=[query_input],
355
- outputs=[
356
- synthesis_id,
357
- status_panel,
358
- steps_container,
359
- log_panel,
360
- log_output,
361
- status_query,
362
- status_id,
363
- status_created,
364
- status_updated,
365
- status_cost,
366
- outline_status
367
- ]
368
- )
369
-
370
- load_button.click(
371
- fn=load_existing,
372
- inputs=[existing_id_input],
373
- outputs=[
374
- status_panel,
375
- steps_container,
376
- log_panel,
377
- log_output,
378
- status_query,
379
- status_id,
380
- status_created,
381
- status_updated,
382
- status_cost,
383
- outline_status
384
- ]
385
- )
386
 
387
  # Function for retrying outline generation
388
  def retry_outline(outline_id):
@@ -394,6 +533,16 @@ def main():
394
  f"[{log_timestamp}] Retrying outline generation for ID: {outline_id}\n[{log_timestamp}] Connecting to AWS...\n"
395
  )
396
 
 
 
 
 
 
 
 
 
 
 
397
  # Function to view outline results
398
  def view_outline_results(outline_id):
399
  # Fetch real data from AWS
@@ -458,6 +607,117 @@ def main():
458
  "raw_data": str(outline_data)[:1000]
459
  }
460
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
461
  # Connect outline action buttons
462
  outline_retry.click(
463
  fn=retry_outline,
@@ -468,35 +728,55 @@ def main():
468
  outline_view.click(
469
  fn=view_outline_results,
470
  inputs=[status_id],
471
- outputs=[result_panel, result_json] # Now returning both visibility update and data
472
  )
473
 
474
- # Function for actual download (in production)
475
- def download_outline(outline_id):
476
- # For now, just log that we would download
477
- log_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
478
- return f"[{log_timestamp}] Downloading outline with ID: {outline_id}...\n"
479
-
480
  outline_download.click(
481
- fn=download_outline,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
482
  inputs=[status_id],
483
  outputs=[log_output]
484
  )
485
 
486
- # Connect refresh button to view function
487
  refresh_results.click(
488
  fn=view_outline_results,
489
  inputs=[status_id],
490
- outputs=[result_panel, result_json] # Updated to match the view function outputs
491
  )
492
 
493
- # Connect download results button
494
  download_results.click(
495
- fn=download_outline,
496
  inputs=[status_id],
497
  outputs=[log_output]
498
  )
499
-
 
 
 
 
 
 
 
500
  return demo
501
 
502
  if __name__ == "__main__":
 
123
  except Exception as e:
124
  return None, f"Error retrieving outline data: {str(e)}"
125
 
126
+ # Function to fetch research data from AWS
127
+ def fetch_research_data(outline_id, bucket_name="dediro-backup"):
128
+ s3_client, message = init_aws_client()
129
+ if not s3_client:
130
+ return None, message
131
+
132
+ try:
133
+ # Construct the S3 key with the correct path for Research Agent
134
+ s3_key = f"Research-Agent/agent_steps/{outline_id}_results.json"
135
+
136
+ # Debug info
137
+ log_message = f"Looking for research file at: {bucket_name}/{s3_key}"
138
+ print(log_message)
139
+
140
+ # Try to get the object from S3
141
+ try:
142
+ response = s3_client.get_object(Bucket=bucket_name, Key=s3_key)
143
+ research_data = json.loads(response['Body'].read().decode('utf-8'))
144
+ return research_data, f"Successfully retrieved research data for ID: {outline_id}"
145
+ except s3_client.exceptions.NoSuchKey:
146
+ # If exact key not found, try to list objects with similar prefix
147
+ prefix = f"Research-Agent/agent_steps/{outline_id}"
148
+ response = s3_client.list_objects_v2(
149
+ Bucket=bucket_name,
150
+ Prefix=prefix
151
+ )
152
+
153
+ if 'Contents' in response:
154
+ # Find the first research JSON file
155
+ research_files = [obj['Key'] for obj in response['Contents']
156
+ if '_results.json' in obj['Key']]
157
+
158
+ if research_files:
159
+ # Get the first matching research file
160
+ research_key = research_files[0]
161
+ print(f"Found alternative file: {research_key}")
162
+ response = s3_client.get_object(Bucket=bucket_name, Key=research_key)
163
+ research_data = json.loads(response['Body'].read().decode('utf-8'))
164
+ return research_data, f"Found similar research results: {research_key}"
165
+
166
+ return None, f"No research data found for ID: {outline_id}"
167
+
168
+ except NoCredentialsError:
169
+ return None, "AWS credentials not available"
170
+ except Exception as e:
171
+ return None, f"Error retrieving research data: {str(e)}"
172
+
173
  # Helper function to extract outline from potentially nested structure
174
  def extract_outline_from_data(data):
175
  """Extract outline data from potentially nested structures"""
 
189
 
190
  # Return the original if we can't determine the structure
191
  return data
192
+
193
+ # Helper function to extract research results from potentially nested structure
194
+ def extract_research_from_data(data):
195
+ """Extract research data from potentially nested structures"""
196
+ if not data:
197
+ return None
198
+
199
+ # Try different possible paths to the research data
200
+ if isinstance(data, dict):
201
+ if "results" in data:
202
+ return data["results"]
203
+ elif "data" in data and "results" in data["data"]:
204
+ return data["data"]["results"]
205
+
206
+ # Check if this looks like research results directly
207
+ if "theme" in data or "articles" in data:
208
+ return data
209
+
210
+ # Return the original if we can't determine the structure
211
+ return data
212
 
213
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange")) as demo:
214
  # Header
 
240
  with gr.Row():
241
  load_button = gr.Button("Load Outline")
242
 
243
+ # New: Research section
244
+ with gr.Row():
245
+ with gr.Column(scale=2):
246
+ # Research Agent section
247
+ gr.Markdown("## Generate Research")
248
+ research_query_input = gr.Textbox(
249
+ label="Enter Outline ID for Research:",
250
+ placeholder="Enter the Outline ID to generate research for...",
251
+ lines=1
252
+ )
253
+
254
+ with gr.Row():
255
+ generate_research_button = gr.Button("Generate Research", variant="primary")
256
+
257
+ with gr.Column(scale=2):
258
+ # Continue existing research section
259
+ gr.Markdown("## Continue Existing Research")
260
+ existing_research_id_input = gr.Textbox(
261
+ label="Enter Existing Research ID:",
262
+ placeholder="Enter ID to view existing research..."
263
+ )
264
+
265
+ with gr.Row():
266
+ load_research_button = gr.Button("Load Research")
267
+
268
  # Synthesis status display
269
  with gr.Row(visible=False) as status_panel:
270
+ gr.Markdown("## Current Project Status")
271
 
272
  with gr.Column():
273
  status_query = gr.Textbox(label="Query")
 
283
  # Step Status Card
284
  steps_container = gr.Row(visible=False)
285
  with steps_container:
286
+ gr.Markdown("## Process Status")
287
 
288
  with gr.Group():
289
  gr.Markdown("### Outline Generator")
 
292
  outline_retry = gr.Button("Retry", size="sm", variant="primary")
293
  outline_view = gr.Button("View Results", size="sm")
294
  outline_download = gr.Button("Download", size="sm")
295
+
296
+ # Add Research Agent status section
297
+ with gr.Group():
298
+ gr.Markdown("### Research Agent")
299
+ research_status = gr.Markdown("⏳ **Waiting**...")
300
+ with gr.Row():
301
+ research_retry = gr.Button("Retry", size="sm", variant="primary")
302
+ research_view = gr.Button("View Results", size="sm")
303
+ research_download = gr.Button("Download", size="sm")
304
 
305
+ # Result Preview for Outline
306
  with gr.Row(visible=False) as result_panel:
307
  gr.Markdown("## Outline Preview")
308
  with gr.Column():
 
324
  refresh_results = gr.Button("Refresh Results")
325
  download_results = gr.Button("Download Results")
326
 
327
+ # Result Preview for Research
328
+ with gr.Row(visible=False) as research_panel:
329
+ gr.Markdown("## Research Results")
330
+ with gr.Column():
331
+ # Add a text area to display any research errors or messages
332
+ research_message = gr.Textbox(
333
+ label="Status",
334
+ value="",
335
+ visible=False,
336
+ lines=2
337
+ )
338
+ # JSON component for the research data
339
+ research_json = gr.JSON(
340
+ label="Research Results",
341
+ value={}
342
+ )
343
+
344
+ # Add buttons for refresh and download
345
+ with gr.Row():
346
+ refresh_research = gr.Button("Refresh Research")
347
+ download_research_btn = gr.Button("Download Research")
348
+
349
  # Log panel
350
  with gr.Row(visible=False) as log_panel:
351
  gr.Markdown("## Process Log")
 
359
  # Function for generating a new outline
360
  def generate_new_outline(query):
361
  if not query.strip():
362
+ return "Please enter a query first", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), "", "", "", "", "", 0.00, "", ""
363
 
364
  # Generate a timestamp-based ID (in real implementation, this would match your AWS naming pattern)
365
  timestamp = str(int(time.time()))
 
379
  datetime.now().strftime("%Y-%m-%d %H:%M"),
380
  datetime.now().strftime("%Y-%m-%d %H:%M"),
381
  0.00,
382
+ "🟡 **In Progress**...",
383
+ "⏳ **Waiting**..." # Research status starts as waiting
384
  )
385
 
386
+ # Function for generating research
387
+ def generate_research(outline_id):
388
+ if not outline_id.strip():
389
+ return gr.update(visible=True), f"Please enter a valid outline ID", gr.update(visible=False)
390
+
391
+ # First check if the outline exists
392
+ outline_data, outline_message = fetch_outline_data(outline_id)
393
+
394
+ if not outline_data:
395
+ return gr.update(visible=True), f"Error: {outline_message}", gr.update(visible=False)
396
+
397
+ # Update UI
398
+ log_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
399
+ log_message = f"[{log_timestamp}] Starting research generation for outline ID: {outline_id}\n[{log_timestamp}] This would trigger the ResearchAgent in a real implementation...\n"
400
+
401
+ return gr.update(visible=True), log_message, gr.update(visible=True)
402
+
403
+ # Function for loading existing outline
404
  def load_existing(existing_id):
405
  if not existing_id.strip():
406
+ # Return all required outputs even in error case
407
  return (
408
  gr.update(visible=False), # status_panel
409
  gr.update(visible=False), # steps_container
 
414
  "", # status_created
415
  "", # status_updated
416
  0.0, # status_cost
417
+ "❌ **Error**", # outline_status
418
+ "❌ **Error**" # research_status (new)
419
  )
420
 
421
  # Now we actually fetch the data from AWS S3
422
+ outline_data, outline_message = fetch_outline_data(existing_id)
423
+ # Also check if research data exists
424
+ research_data, research_message = fetch_research_data(existing_id)
425
 
426
  if not outline_data:
427
+ # Return all required outputs even in error case
428
  return (
429
  gr.update(visible=False), # status_panel
430
  gr.update(visible=False), # steps_container
431
  gr.update(visible=False), # log_panel
432
+ f"Error: {outline_message}", # log_output
433
  "", # status_query
434
  existing_id, # status_id
435
  "", # status_created
436
  "", # status_updated
437
  0.0, # status_cost
438
+ "❌ **Error**", # outline_status
439
+ "❌ **Not Started**" # research_status
440
  )
441
 
442
  # Extract the actual outline
 
445
  # Extract query from ID (assuming ID format: timestamp_formatted_query)
446
  parts = existing_id.split('_', 1)
447
  if len(parts) < 2:
448
+ # Return all required outputs even in error case
449
  return (
450
  gr.update(visible=False), # status_panel
451
  gr.update(visible=False), # steps_container
 
456
  "", # status_created
457
  "", # status_updated
458
  0.0, # status_cost
459
+ "❌ **Error**", # outline_status
460
+ "❌ **Error**" # research_status
461
  )
462
 
463
  # Reconstruct the original query
 
469
  # Determine actual status based on outline data
470
  outline_status_text = "✅ **Completed**" # Default to completed if we found data
471
 
472
+ # Determine research status
473
+ if research_data:
474
+ research_status_text = "✅ **Completed**"
475
+ log_message = f"[{log_timestamp}] Loaded outline with ID: {existing_id}\n[{log_timestamp}] {outline_message}\n[{log_timestamp}] Research data found: {research_message}\n"
476
+ else:
477
+ research_status_text = "⏳ **Not Started**"
478
+ log_message = f"[{log_timestamp}] Loaded outline with ID: {existing_id}\n[{log_timestamp}] {outline_message}\n[{log_timestamp}] No research data found yet.\n"
479
+
480
  # Get creation time from timestamp in ID
481
  try:
482
  creation_time = datetime.fromtimestamp(int(parts[0])).strftime("%Y-%m-%d %H:%M")
 
493
  gr.update(visible=True),
494
  gr.update(visible=True),
495
  gr.update(visible=True),
496
+ log_message,
497
  original_query,
498
  existing_id,
499
  creation_time,
500
  datetime.now().strftime("%Y-%m-%d %H:%M"), # Last updated is now
501
  cost,
502
+ outline_status_text,
503
+ research_status_text
504
  )
505
 
506
+ # Function for loading existing research
507
+ def load_existing_research(existing_id):
508
+ if not existing_id.strip():
509
+ return gr.update(visible=False), "Please enter a valid research ID", gr.update(visible=True)
510
+
511
+ # Fetch research data from AWS
512
+ research_data, message = fetch_research_data(existing_id)
513
+
514
+ if not research_data:
515
+ return gr.update(visible=False), f"Error: {message}", gr.update(visible=True)
516
+
517
+ # Extract the actual research results
518
+ actual_research = extract_research_from_data(research_data)
519
+
520
+ # Update UI components
521
+ log_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
522
+ log_message = f"[{log_timestamp}] Loaded research with ID: {existing_id}\n[{log_timestamp}] {message}\n"
523
+
524
+ return gr.update(visible=True), actual_research, log_message
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
 
526
  # Function for retrying outline generation
527
  def retry_outline(outline_id):
 
533
  f"[{log_timestamp}] Retrying outline generation for ID: {outline_id}\n[{log_timestamp}] Connecting to AWS...\n"
534
  )
535
 
536
+ # Function for retrying research generation
537
+ def retry_research(outline_id):
538
+ # This would call your ResearchAgent with force_rerun=True
539
+ # For now, just update the UI
540
+ log_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
541
+ return (
542
+ "🟡 **Retrying**...",
543
+ f"[{log_timestamp}] Retrying research generation for ID: {outline_id}\n[{log_timestamp}] Connecting to AWS...\n"
544
+ )
545
+
546
  # Function to view outline results
547
  def view_outline_results(outline_id):
548
  # Fetch real data from AWS
 
607
  "raw_data": str(outline_data)[:1000]
608
  }
609
 
610
+ # Function to view research results
611
+ def view_research_results(outline_id):
612
+ # Fetch real data from AWS
613
+ research_data, message = fetch_research_data(outline_id)
614
+
615
+ if not research_data:
616
+ # Return a message if data not found
617
+ return gr.update(visible=True), gr.update(visible=True), {"error": message}
618
+
619
+ # Print the raw data for debugging
620
+ print(f"Raw research data type: {type(research_data)}")
621
+
622
+ # Step by step extraction with verbose logging
623
+ try:
624
+ # Extract the actual research results
625
+ actual_research = extract_research_from_data(research_data)
626
+
627
+ # Ensure we're working with a non-empty structure
628
+ if not actual_research:
629
+ print(f"Warning: Extracted research is not valid: {actual_research}")
630
+ # If it's not, pass the original data
631
+ actual_research = {"warning": "Could not extract proper research structure", "data": str(research_data)[:1000]}
632
+
633
+ # Make the research panel visible and return the data for the JSON component
634
+ return gr.update(visible=True), gr.update(visible=False), actual_research
635
+
636
+ except Exception as e:
637
+ # If there's an error processing the data, log it and return the raw data
638
+ error_msg = f"Error processing research data: {str(e)}"
639
+ print(error_msg)
640
+ traceback_info = __import__('traceback').format_exc()
641
+ print(f"Traceback: {traceback_info}")
642
+
643
+ # Return both the error and the raw data for debugging
644
+ return gr.update(visible=True), gr.update(visible=True), {
645
+ "error": error_msg,
646
+ "raw_data": str(research_data)[:1000]
647
+ }
648
+
649
+ # Function for downloading outline data
650
+ def download_outline_file(outline_id):
651
+ # For now, just log that we would download
652
+ log_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
653
+ return f"[{log_timestamp}] Downloading outline with ID: {outline_id}...\n"
654
+
655
+ # Function for downloading research data
656
+ def download_research_file(outline_id):
657
+ # For now, just log that we would download
658
+ log_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
659
+ return f"[{log_timestamp}] Downloading research with ID: {outline_id}...\n"
660
+
661
+ # Connect the handlers
662
+ create_button.click(
663
+ fn=generate_new_outline,
664
+ inputs=[query_input],
665
+ outputs=[
666
+ synthesis_id,
667
+ status_panel,
668
+ steps_container,
669
+ log_panel,
670
+ log_output,
671
+ status_query,
672
+ status_id,
673
+ status_created,
674
+ status_updated,
675
+ status_cost,
676
+ outline_status,
677
+ research_status
678
+ ]
679
+ )
680
+
681
+ load_button.click(
682
+ fn=load_existing,
683
+ inputs=[existing_id_input],
684
+ outputs=[
685
+ status_panel,
686
+ steps_container,
687
+ log_panel,
688
+ log_output,
689
+ status_query,
690
+ status_id,
691
+ status_created,
692
+ status_updated,
693
+ status_cost,
694
+ outline_status,
695
+ research_status
696
+ ]
697
+ )
698
+
699
+ # Connect research generation button
700
+ generate_research_button.click(
701
+ fn=generate_research,
702
+ inputs=[research_query_input],
703
+ outputs=[
704
+ log_panel,
705
+ log_output,
706
+ steps_container
707
+ ]
708
+ )
709
+
710
+ # Connect load research button
711
+ load_research_button.click(
712
+ fn=load_existing_research,
713
+ inputs=[existing_research_id_input],
714
+ outputs=[
715
+ research_panel,
716
+ research_json,
717
+ log_output
718
+ ]
719
+ )
720
+
721
  # Connect outline action buttons
722
  outline_retry.click(
723
  fn=retry_outline,
 
728
  outline_view.click(
729
  fn=view_outline_results,
730
  inputs=[status_id],
731
+ outputs=[result_panel, result_json]
732
  )
733
 
 
 
 
 
 
 
734
  outline_download.click(
735
+ fn=download_outline_file,
736
+ inputs=[status_id],
737
+ outputs=[log_output]
738
+ )
739
+
740
+ # Connect research action buttons
741
+ research_retry.click(
742
+ fn=retry_research,
743
+ inputs=[status_id],
744
+ outputs=[research_status, log_output]
745
+ )
746
+
747
+ research_view.click(
748
+ fn=view_research_results,
749
+ inputs=[status_id],
750
+ outputs=[research_panel, research_message, research_json]
751
+ )
752
+
753
+ research_download.click(
754
+ fn=download_research_file,
755
  inputs=[status_id],
756
  outputs=[log_output]
757
  )
758
 
759
+ # Connect refresh button to view function for outline
760
  refresh_results.click(
761
  fn=view_outline_results,
762
  inputs=[status_id],
763
+ outputs=[result_panel, result_json]
764
  )
765
 
766
+ # Connect download results button for outline
767
  download_results.click(
768
+ fn=download_outline_file,
769
  inputs=[status_id],
770
  outputs=[log_output]
771
  )
772
+
773
+ # Connect refresh button to view function for research
774
+ refresh_research.click(
775
+ fn=view_research_results,
776
+ inputs=[status_id],
777
+ outputs=[research_panel, research_message, research_json]
778
+ )
779
+
780
  return demo
781
 
782
  if __name__ == "__main__":