amd-gaia 0.14.1__py3-none-any.whl → 0.14.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -445,7 +445,7 @@ class Orchestrator:
445
445
  )
446
446
 
447
447
  try:
448
- response = self.llm_client.send(prompt, timeout=1200, no_history=True)
448
+ response = self.llm_client.send(prompt, timeout=1200)
449
449
  data = self._parse_checkpoint_response(response)
450
450
  return CheckpointAssessment(
451
451
  status=data.get("status", "needs_fix"),
@@ -472,7 +472,9 @@ class Orchestrator:
472
472
  validation_history: List[Any],
473
473
  ) -> str:
474
474
  """Build the prompt for the checkpoint reviewer."""
475
- validation_summary = self._format_validation_history(validation_history)
475
+ validation_summary = self._format_validation_history(
476
+ validation_history, getattr(execution_result, "validation_logs", None)
477
+ )
476
478
 
477
479
  outstanding = (
478
480
  "\n".join(f"- {item}" for item in context.fix_feedback)
@@ -530,52 +532,70 @@ class Orchestrator:
530
532
  logger.exception("Failed to summarize conversation history: %s", exc)
531
533
  return None
532
534
 
533
- def _format_validation_history(self, validation_history: List[Any]) -> str:
534
- """Format validation logs for the checkpoint prompt."""
535
+ def _format_validation_history(
536
+ self, validation_history: List[Any], latest_plan_logs: Optional[List[Any]]
537
+ ) -> str:
538
+ """Format validation logs, splitting latest plan from historical ones."""
539
+
535
540
  if not validation_history:
536
541
  return "No validation or test commands have been executed yet."
537
542
 
538
- lines: List[str] = []
539
- recent = validation_history[-5:]
540
- for entry in recent:
541
- if hasattr(entry, "to_dict"):
542
- entry_data = entry.to_dict()
543
- elif isinstance(entry, dict):
544
- entry_data = entry
545
- else:
546
- entry_data = {}
543
+ latest_logs = latest_plan_logs or []
544
+ latest_count = len(latest_logs)
545
+ historical_logs = (
546
+ validation_history[:-latest_count] if latest_count else validation_history
547
+ )
547
548
 
548
- template = getattr(entry, "template", None) or entry_data.get("template")
549
- description = getattr(entry, "description", None) or entry_data.get(
550
- "description", ""
551
- )
552
- success = getattr(entry, "success", None)
553
- if success is None:
554
- success = entry_data.get("success", True)
555
- status = "PASS" if success else "FAIL"
556
- error = getattr(entry, "error", None) or entry_data.get("error")
557
- output = getattr(entry, "output", None) or entry_data.get("output", {})
558
-
559
- lines.append(f"- [{status}] {template}: {description}")
560
- if error:
561
- lines.append(f" Error: {error}")
562
-
563
- snippet = ""
564
- if isinstance(output, dict):
565
- for key in ("stdout", "stderr", "message", "log", "details"):
566
- if output.get(key):
567
- snippet = str(output[key])
568
- break
569
- if not snippet and output:
570
- snippet = json.dumps(output)[:400]
571
- elif output:
572
- snippet = str(output)[:400]
573
-
574
- snippet = snippet.strip()
575
- if snippet:
576
- lines.append(f" Output: {snippet[:400]}")
577
-
578
- return "\n".join(lines)
549
+ def normalize(entry: Any) -> Dict[str, Any]:
550
+ if hasattr(entry, "to_dict"):
551
+ return entry.to_dict()
552
+ if isinstance(entry, dict):
553
+ return entry
554
+ return {}
555
+
556
+ def render(entries: List[Any], limit: Optional[int] = None) -> List[str]:
557
+ if not entries:
558
+ return ["None"]
559
+
560
+ selected = entries if limit is None else entries[-limit:]
561
+ lines: List[str] = []
562
+ for entry in selected:
563
+ data = normalize(entry)
564
+ template = data.get("template", "unknown")
565
+ description = data.get("description", "")
566
+ success = data.get("success", True)
567
+ status = "PASS" if success else "FAIL"
568
+ error = data.get("error")
569
+ output = data.get("output", {})
570
+
571
+ lines.append(f"- [{status}] {template}: {description}")
572
+ if error:
573
+ lines.append(f" Error: {error}")
574
+
575
+ snippet = ""
576
+ if isinstance(output, dict):
577
+ for key in ("stdout", "stderr", "message", "log", "details"):
578
+ if output.get(key):
579
+ snippet = str(output[key])
580
+ break
581
+ if not snippet and output:
582
+ snippet = json.dumps(output)[:400]
583
+ elif output:
584
+ snippet = str(output)[:400]
585
+
586
+ snippet = snippet.strip()
587
+ if snippet:
588
+ lines.append(f" Output: {snippet[:400]}")
589
+ return lines
590
+
591
+ sections: List[str] = []
592
+ sections.append("### Latest Plan Results")
593
+ sections.extend(render(list(latest_logs)))
594
+ sections.append("")
595
+ sections.append("### Previous Plan History")
596
+ sections.extend(render(list(historical_logs), limit=5))
597
+
598
+ return "\n".join(sections).strip()
579
599
 
580
600
  def _parse_checkpoint_response(self, response: Any) -> Dict[str, Any]:
581
601
  """Parse JSON output from the checkpoint reviewer."""
@@ -72,7 +72,7 @@ ERROR_PATTERNS: List[ErrorPattern] = [
72
72
  pattern=r"ModuleNotFoundError:\s+No module named '([^']+)'",
73
73
  category=ErrorCategory.DEPENDENCY,
74
74
  action=RecoveryAction.FIX_AND_RETRY,
75
- fix_command="pip install {module}",
75
+ fix_command="uv pip install {module}",
76
76
  max_retries=2,
77
77
  ),
78
78
  # TypeScript compilation - escalate to LLM
@@ -257,9 +257,14 @@ TEMPLATE_CATALOG: Dict[str, TemplateDefinition] = {
257
257
  ),
258
258
  "variant": ParameterSpec(
259
259
  type=ParameterType.STRING,
260
- description="Component variant: list|form|new|detail|actions",
260
+ description="Component variant: list|form|new|detail|actions|artifact-timer",
261
261
  example="list",
262
262
  ),
263
+ "component_name": ParameterSpec(
264
+ type=ParameterType.STRING,
265
+ description="Optional explicit component name (e.g., CountdownTimer)",
266
+ required=False,
267
+ ),
263
268
  "with_checkboxes": ParameterSpec(
264
269
  type=ParameterType.BOOLEAN,
265
270
  description="Add checkbox UI for boolean fields (e.g., todo completion)",
@@ -275,6 +280,7 @@ TEMPLATE_CATALOG: Dict[str, TemplateDefinition] = {
275
280
  "Use 'form' for reusable create/edit form component",
276
281
  "Use 'new' for /resource/new page",
277
282
  "Use 'detail' for /resource/[id] EDIT page with pre-populated form",
283
+ "Use 'artifact-timer' when the user requests a countdown; supply component_name (e.g., CountdownTimer) so pages can import the client-side timer widget",
278
284
  "Add with_checkboxes=true for todo apps",
279
285
  ],
280
286
  ),
@@ -394,6 +394,8 @@ def _map_type_to_zod(field_type: str) -> str:
394
394
 
395
395
  SERVER_COMPONENT_LIST = """import {{ prisma }} from "@/lib/prisma";
396
396
  import Link from "next/link";
397
+ // EXTRA COMPONENT NOTE: Import any previously generated components/helpers as needed.
398
+ // import {{ AdditionalComponent }} from "@/components/AdditionalComponent";
397
399
 
398
400
  async function get{Resource}s() {{
399
401
  const {resource_plural} = await prisma.{resource}.findMany({{
@@ -409,16 +411,25 @@ export default async function {Resource}sPage() {{
409
411
  return (
410
412
  <div className="min-h-screen">
411
413
  <div className="container mx-auto px-4 py-12 max-w-4xl">
412
- {{/* Header */}}
413
- <div className="mb-10">
414
- <h1 className="text-4xl font-bold bg-gradient-to-r from-indigo-400 via-purple-400 to-pink-400 bg-clip-text text-transparent mb-2">
415
- {Resource}s
416
- </h1>
417
- <p className="text-slate-400">
418
- {{{resource_plural}.length === 0
419
- ? "No items yet. Create your first one!"
420
- : `${{({resource_plural} as any[]).filter(t => !(t as any).completed).length}} pending items`}}
421
- </p>
414
+ {{/* Header + Custom Components */}}
415
+ <div className="mb-10 flex flex-col gap-6 md:flex-row md:items-center md:justify-between">
416
+ <div>
417
+ <h1 className="text-4xl font-bold bg-gradient-to-r from-indigo-400 via-purple-400 to-pink-400 bg-clip-text text-transparent mb-2">
418
+ {Resource}s
419
+ </h1>
420
+ <p className="text-slate-400">
421
+ {{{resource_plural}.length === 0
422
+ ? "No items yet. Create your first one!"
423
+ : `${{({resource_plural} as any[]).filter(t => !(t as any).completed).length}} pending items`}}
424
+ </p>
425
+ </div>
426
+
427
+ {{/* EXTRA COMPONENT NOTE:
428
+ Check the plan for other generated components (timer, stats badge, etc.)
429
+ and render them here via their imports. Example:
430
+ <AdditionalComponent targetTimestamp={{...}} />
431
+ Remove this placeholder when no extra component is needed. */}}
432
+ {{/* <AdditionalComponent className="w-full md:w-60" /> */}}
422
433
  </div>
423
434
 
424
435
  {{/* Add Button */}}
@@ -458,13 +469,21 @@ export default async function {Resource}sPage() {{
458
469
  ) : (
459
470
  <div className="space-y-3">
460
471
  {{{resource_plural}.map((item) => (
461
- <Link
462
- key={{item.id}}
463
- href={{`/{resource}s/${{item.id}}`}}
464
- className="block p-5 rounded-xl bg-slate-800/30 border border-slate-700/30 hover:bg-slate-800/50 hover:border-indigo-500/30 transition-all duration-300"
465
- >
466
- {field_display}
467
- </Link>
472
+ <Link
473
+ key={{item.id}}
474
+ href={{`/{resource}s/${{item.id}}`}}
475
+ className="block p-5 rounded-xl bg-slate-800/30 border border-slate-700/30 hover:bg-slate-800/50 hover:border-indigo-500/30 transition-all duration-300"
476
+ >
477
+ <div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
478
+ <div className="flex-1">{field_display}</div>
479
+ {{/* EXTRA COMPONENT NOTE:
480
+ Check the plan for per-item components that were generated (countdown,
481
+ status badge, etc.) and include them here. Example:
482
+ <AdditionalComponent targetTimestamp={{item.missionTime}} />
483
+ Remove this placeholder if no extra component is needed. */}}
484
+ {{/* <AdditionalComponent {...item} className="w-full md:w-56" /> */}}
485
+ </div>
486
+ </Link>
468
487
  ))}}
469
488
  </div>
470
489
  )}}
@@ -604,6 +623,98 @@ export function {Resource}Form({{ initialData, mode = "create" }}: {Resource}For
604
623
  );
605
624
  }}"""
606
625
 
626
+ CLIENT_COMPONENT_TIMER = """"use client";
627
+
628
+ import {{ useEffect, useMemo, useState }} from "react";
629
+
630
+ interface {{ComponentName}}Props {{
631
+ targetTimestamp?: string; // ISO 8601 string that marks when the countdown ends
632
+ durationSeconds?: number; // Fallback duration (seconds) when no timestamp is provided
633
+ className?: string;
634
+ }}
635
+
636
+ const MS_IN_SECOND = 1000;
637
+ const MS_IN_MINUTE = 60 * MS_IN_SECOND;
638
+ const MS_IN_HOUR = 60 * MS_IN_MINUTE;
639
+ const MS_IN_DAY = 24 * MS_IN_HOUR;
640
+
641
+ export function {{ComponentName}}({{
642
+ targetTimestamp,
643
+ durationSeconds = 0,
644
+ className = "",
645
+ }}: {{ComponentName}}Props) {{
646
+ const deadlineMs = useMemo(() => {{
647
+ if (targetTimestamp) {{
648
+ const parsed = Date.parse(targetTimestamp);
649
+ return Number.isNaN(parsed) ? null : parsed;
650
+ }}
651
+ if (durationSeconds > 0) {{
652
+ return Date.now() + durationSeconds * MS_IN_SECOND;
653
+ }}
654
+ return null;
655
+ }}, [targetTimestamp, durationSeconds]);
656
+
657
+ const [timeLeftMs, setTimeLeftMs] = useState(() => {{
658
+ if (!deadlineMs) return 0;
659
+ return Math.max(deadlineMs - Date.now(), 0);
660
+ }});
661
+
662
+ useEffect(() => {{
663
+ if (!deadlineMs) {{
664
+ setTimeLeftMs(0);
665
+ return;
666
+ }}
667
+
668
+ const update = () => {{
669
+ setTimeLeftMs(Math.max(deadlineMs - Date.now(), 0));
670
+ }};
671
+
672
+ update();
673
+
674
+ const intervalId = window.setInterval(() => {{
675
+ update();
676
+ if (deadlineMs <= Date.now()) {{
677
+ window.clearInterval(intervalId);
678
+ }}
679
+ }}, 1000);
680
+
681
+ return () => window.clearInterval(intervalId);
682
+ }}, [deadlineMs]);
683
+
684
+ const isExpired = timeLeftMs <= 0;
685
+
686
+ // TIMER_NOTE: derive whichever granularity the feature demands (days, hours,
687
+ // minutes, seconds, milliseconds, etc.). Remove unused helpers so the final
688
+ // output matches the spec exactly.
689
+ const days = Math.floor(timeLeftMs / MS_IN_DAY);
690
+ const hours = Math.floor((timeLeftMs % MS_IN_DAY) / MS_IN_HOUR);
691
+ const minutes = Math.floor((timeLeftMs % MS_IN_HOUR) / MS_IN_MINUTE);
692
+ const seconds = Math.floor((timeLeftMs % MS_IN_MINUTE) / MS_IN_SECOND);
693
+
694
+ return (
695
+ <section
696
+ className={{`glass-card p-6 space-y-4 ${{className}}`.trim()}}
697
+ data-countdown-target={{targetTimestamp || ""}}
698
+ >
699
+ {{/* TIMER_NOTE: swap this placeholder layout for the requested display.
700
+ Emit only the units the user cares about (e.g., just minutes/seconds,
701
+ or a full days→hours→minutes breakdown). */}}
702
+ <div className="font-mono text-4xl text-slate-100">
703
+ {{seconds}}s
704
+ </div>
705
+
706
+ {{isExpired && (
707
+ <p className="text-sm text-slate-400">
708
+ {{/* TIMER_NOTE: replace this placeholder with the exact completion
709
+ copy or follow-up action the prompt describes. */}}
710
+ Countdown complete.
711
+ </p>
712
+ )}}
713
+ </section>
714
+ );
715
+ }}"""
716
+
717
+
607
718
  CLIENT_COMPONENT_NEW_PAGE = """"use client";
608
719
 
609
720
  import {{ {Resource}Form }} from "@/components/{Resource}Form";
@@ -148,7 +148,7 @@ class CodeFormattingMixin:
148
148
  except ImportError:
149
149
  return {
150
150
  "status": "error",
151
- "error": "black is not installed. Install with: pip install black",
151
+ "error": "black is not installed. Install with: uv pip install black",
152
152
  }
153
153
  except Exception as e:
154
154
  return {"status": "error", "error": str(e)}
@@ -568,7 +568,7 @@ if __name__ == "__main__":
568
568
  except ImportError:
569
569
  return {
570
570
  "status": "error",
571
- "error": "pylint is not installed. Install with: pip install pylint",
571
+ "error": "pylint is not installed. Install with: uv pip install pylint",
572
572
  }
573
573
  except Exception as e:
574
574
  return {"status": "error", "error": str(e)}
@@ -29,6 +29,7 @@ from gaia.agents.code.prompts.code_patterns import (
29
29
  APP_GLOBALS_CSS,
30
30
  APP_LAYOUT,
31
31
  CLIENT_COMPONENT_FORM,
32
+ CLIENT_COMPONENT_TIMER,
32
33
  COMPONENT_TEST_ACTIONS,
33
34
  COMPONENT_TEST_FORM,
34
35
  LANDING_PAGE_WITH_LINKS,
@@ -504,7 +505,7 @@ class WebToolsMixin:
504
505
  # These variants always generate client components with "use client"
505
506
  # This prevents the stub fallback when variant="form" but component_type
506
507
  # defaults to "server"
507
- if variant in ["form", "new", "detail", "actions"]:
508
+ if variant in ["form", "new", "detail", "actions", "artifact-timer"]:
508
509
  component_type = "client"
509
510
 
510
511
  # Phase 1 Fix (Issue #885): Read from Prisma schema instead of
@@ -630,6 +631,20 @@ class WebToolsMixin:
630
631
  }
631
632
  content = generate_detail_page(clean_resource_name, fields)
632
633
 
634
+ elif variant == "artifact-timer":
635
+ timer_component = component_name or (
636
+ f"{clean_resource_name.capitalize()}Timer"
637
+ if clean_resource_name
638
+ else "CountdownTimer"
639
+ )
640
+ timer_component = re.sub(r"[^0-9A-Za-z_]", "", timer_component)
641
+ if not timer_component:
642
+ timer_component = "CountdownTimer"
643
+ component_name = timer_component
644
+ content = CLIENT_COMPONENT_TIMER.format(
645
+ ComponentName=timer_component,
646
+ )
647
+
633
648
  elif variant == "actions" and clean_resource_name:
634
649
  # Generate actions component with delete functionality
635
650
  content = generate_actions_component(clean_resource_name)
@@ -36,7 +36,7 @@ class PDFFormatter:
36
36
  def __init__(self):
37
37
  if not HAS_REPORTLAB:
38
38
  raise ImportError(
39
- "PDF output requires reportlab. Install with: pip install reportlab"
39
+ "PDF output requires reportlab. Install with: uv pip install reportlab"
40
40
  )
41
41
 
42
42
  self.styles = getSampleStyleSheet()
@@ -123,7 +123,7 @@ class AudioClient:
123
123
 
124
124
  except ImportError:
125
125
  self.log.error(
126
- "WhisperAsr not found. Please install voice support with: pip install .[talk]"
126
+ 'WhisperAsr not found. Please install voice support with: uv pip install ".[talk]"'
127
127
  )
128
128
  raise
129
129
  except Exception as e:
@@ -306,7 +306,7 @@ class AudioClient:
306
306
  self.log.debug("TTS initialized successfully")
307
307
  except Exception as e:
308
308
  raise RuntimeError(
309
- f"Failed to initialize TTS:\n{e}\nInstall talk dependencies with: pip install .[talk]\nYou can also use --no-tts option to disable TTS"
309
+ f'Failed to initialize TTS:\n{e}\nInstall talk dependencies with: uv pip install ".[talk]"\nYou can also use --no-tts option to disable TTS'
310
310
  )
311
311
 
312
312
  async def speak_text(self, text: str) -> None:
gaia/audio/kokoro_tts.py CHANGED
@@ -43,9 +43,9 @@ class KokoroTTS:
43
43
  error_msg = (
44
44
  f"\n❌ Error: Missing required talk dependencies: {', '.join(missing)}\n\n"
45
45
  f"Please install the talk dependencies:\n"
46
- f" pip install -e .[talk]\n\n"
46
+ f' uv pip install -e ".[talk]"\n\n'
47
47
  f"Or install packages directly:\n"
48
- f" pip install {' '.join(missing)}\n"
48
+ f" uv pip install {' '.join(missing)}\n"
49
49
  )
50
50
  raise ImportError(error_msg)
51
51
 
gaia/audio/whisper_asr.py CHANGED
@@ -56,9 +56,9 @@ class WhisperAsr(AudioRecorder):
56
56
  error_msg = (
57
57
  f"\n❌ Error: Missing required talk dependencies: {', '.join(missing)}\n\n"
58
58
  f"Please install the talk dependencies:\n"
59
- f" pip install -e .[talk]\n\n"
59
+ f' uv pip install -e ".[talk]"\n\n'
60
60
  f"Or install packages directly:\n"
61
- f" pip install {' '.join(missing)}\n"
61
+ f" uv pip install {' '.join(missing)}\n"
62
62
  )
63
63
  raise ImportError(error_msg)
64
64
 
gaia/chat/sdk.py CHANGED
@@ -687,7 +687,7 @@ class ChatSDK:
687
687
  from gaia.rag.sdk import RAGSDK, RAGConfig
688
688
  except ImportError:
689
689
  raise ImportError(
690
- 'RAG dependencies not installed. Install with: pip install ".[rag]"'
690
+ 'RAG dependencies not installed. Install with: uv pip install -e ".[rag]"'
691
691
  )
692
692
 
693
693
  # Create RAG config matching chat config
gaia/cli.py CHANGED
@@ -2109,7 +2109,7 @@ Examples:
2109
2109
  print("The evaluation dependencies are not installed.")
2110
2110
  print("")
2111
2111
  print("To fix this, install the evaluation dependencies:")
2112
- print(" pip install -e .[eval]")
2112
+ print(' uv pip install -e ".[eval]"')
2113
2113
  print("")
2114
2114
  print("This will install required packages including:")
2115
2115
  print(" - anthropic (for Claude AI)")
@@ -2464,7 +2464,7 @@ Examples:
2464
2464
 
2465
2465
  if not HAS_REPORTLAB:
2466
2466
  print(
2467
- "❌ Error: PDF output requires reportlab. Install with: pip install reportlab"
2467
+ "❌ Error: PDF output requires reportlab. Install with: uv pip install reportlab"
2468
2468
  )
2469
2469
  if args.format == "both":
2470
2470
  print(
@@ -2542,7 +2542,7 @@ Examples:
2542
2542
  pdf_formatter = PDFFormatter()
2543
2543
  else:
2544
2544
  print(
2545
- "⚠️ Warning: PDF output requires reportlab. Install with: pip install reportlab"
2545
+ "⚠️ Warning: PDF output requires reportlab. Install with: uv pip install reportlab"
2546
2546
  )
2547
2547
  if args.format == "pdf":
2548
2548
  print("❌ Cannot generate PDF files without reportlab.")
@@ -2660,7 +2660,7 @@ Let me know your answer!
2660
2660
  log.debug("ASR initialized successfully")
2661
2661
  except ImportError:
2662
2662
  log.error(
2663
- "WhisperAsr not found. Please install voice support with: pip install -e .[talk]"
2663
+ 'WhisperAsr not found. Please install voice support with: uv pip install -e ".[talk]"'
2664
2664
  )
2665
2665
  raise
2666
2666
  except Exception as e:
@@ -2746,7 +2746,7 @@ Let me know your answer!
2746
2746
  "❌ Error: YouTube transcript functionality requires additional dependencies."
2747
2747
  )
2748
2748
  print(
2749
- "Please install: pip install llama-index-readers-youtube-transcript"
2749
+ "Please install: uv pip install llama-index-readers-youtube-transcript"
2750
2750
  )
2751
2751
  print(f"Import error: {e}")
2752
2752
  sys.exit(1)
@@ -3150,7 +3150,7 @@ Let me know your answer!
3150
3150
  print("The evaluation dependencies are not installed.")
3151
3151
  print("")
3152
3152
  print("To fix this, install the evaluation dependencies:")
3153
- print(" pip install -e .[eval]")
3153
+ print(' uv pip install -e ".[eval]"')
3154
3154
  print("")
3155
3155
  print("This will install required packages including:")
3156
3156
  print(" - anthropic (for Claude AI)")
@@ -3323,7 +3323,7 @@ Let me know your answer!
3323
3323
  print("The evaluation dependencies are not installed.")
3324
3324
  print("")
3325
3325
  print("To fix this, install the evaluation dependencies:")
3326
- print(" pip install -e .[eval]")
3326
+ print(' uv pip install -e ".[eval]"')
3327
3327
  print("")
3328
3328
  print("This will install required packages including:")
3329
3329
  print(" - anthropic (for Claude AI)")
@@ -3363,7 +3363,7 @@ Let me know your answer!
3363
3363
  print("The evaluation dependencies are not installed.")
3364
3364
  print("")
3365
3365
  print("To fix this, install the evaluation dependencies:")
3366
- print(" pip install -e .[eval]")
3366
+ print(' uv pip install -e ".[eval]"')
3367
3367
  print("")
3368
3368
  print("This will install required packages including:")
3369
3369
  print(" - anthropic (for Claude AI)")
@@ -3727,7 +3727,7 @@ Let me know your answer!
3727
3727
  print("The evaluation dependencies are not installed.")
3728
3728
  print("")
3729
3729
  print("To fix this, install the evaluation dependencies:")
3730
- print(" pip install -e .[eval]")
3730
+ print(' uv pip install -e ".[eval]"')
3731
3731
  print("")
3732
3732
  print("This will install required packages including:")
3733
3733
  print(" - anthropic (for Claude AI)")
@@ -3802,7 +3802,7 @@ Let me know your answer!
3802
3802
  print("The evaluation dependencies are not installed.")
3803
3803
  print("")
3804
3804
  print("To fix this, install the evaluation dependencies:")
3805
- print(" pip install -e .[eval]")
3805
+ print(' uv pip install -e ".[eval]"')
3806
3806
  print("")
3807
3807
  print("This will install required packages including:")
3808
3808
  print(" - anthropic (for Claude AI)")
@@ -3878,7 +3878,7 @@ Let me know your answer!
3878
3878
  print("The evaluation dependencies are not installed.")
3879
3879
  print("")
3880
3880
  print("To fix this, install the evaluation dependencies:")
3881
- print(" pip install -e .[eval]")
3881
+ print(' uv pip install -e ".[eval]"')
3882
3882
  print("")
3883
3883
  print("This will install required packages including:")
3884
3884
  print(" - anthropic (for Claude AI)")
@@ -4495,7 +4495,7 @@ def handle_jira_command(args):
4495
4495
  except ImportError as e:
4496
4496
  log.error(f"Failed to import Jira app: {e}")
4497
4497
  print("❌ Error: Jira app components are not available")
4498
- print("Make sure GAIA is installed properly: pip install -e .")
4498
+ print("Make sure GAIA is installed properly: uv pip install -e .")
4499
4499
  sys.exit(1)
4500
4500
  except Exception as e:
4501
4501
  log.error(f"Error running Jira app: {e}")
@@ -4546,7 +4546,7 @@ def handle_docker_command(args):
4546
4546
  except ImportError as e:
4547
4547
  log.error(f"Failed to import Docker app: {e}")
4548
4548
  print("❌ Error: Docker app components are not available")
4549
- print("Make sure GAIA is installed properly: pip install -e .")
4549
+ print("Make sure GAIA is installed properly: uv pip install -e .")
4550
4550
  sys.exit(1)
4551
4551
  except Exception as e:
4552
4552
  log.error(f"Error running Docker app: {e}")
@@ -4624,7 +4624,7 @@ def handle_api_command(args):
4624
4624
  except ImportError as e:
4625
4625
  log.error(f"Failed to import API server: {e}")
4626
4626
  print("❌ Error: API server components are not available")
4627
- print("Make sure uvicorn is installed: pip install uvicorn")
4627
+ print("Make sure uvicorn is installed: uv pip install uvicorn")
4628
4628
  sys.exit(1)
4629
4629
  except KeyboardInterrupt:
4630
4630
  print("\n✅ API server stopped")
@@ -4866,7 +4866,7 @@ def handle_blender_command(args):
4866
4866
  # Check if Blender components are available
4867
4867
  if not BLENDER_AVAILABLE:
4868
4868
  print("❌ Error: Blender agent components are not available")
4869
- print("Install blender dependencies with: pip install -e .[blender]")
4869
+ print('Install blender dependencies with: uv pip install -e ".[blender]"')
4870
4870
  sys.exit(1)
4871
4871
 
4872
4872
  # Initialize Lemonade with blender agent profile (32768 context)
@@ -5063,7 +5063,7 @@ def handle_mcp_start(args):
5063
5063
  print("❌ Error: MCP dependencies not installed.")
5064
5064
  print("")
5065
5065
  print("To fix this, install the MCP dependencies:")
5066
- print(" pip install -e .[mcp]")
5066
+ print(' uv pip install -e ".[mcp]"')
5067
5067
  return
5068
5068
 
5069
5069
  # Import and start the HTTP-native MCP bridge
@@ -155,7 +155,7 @@ class BatchExperimentRunner:
155
155
  if PdfReader is None:
156
156
  raise ImportError(
157
157
  "PDF reading library not found. Please install pypdf:\n"
158
- " pip install pypdf"
158
+ " uv pip install pypdf"
159
159
  )
160
160
 
161
161
  try:
gaia/eval/claude.py CHANGED
@@ -41,9 +41,9 @@ class ClaudeClient:
41
41
  error_msg = (
42
42
  "\n❌ Error: Missing required package 'anthropic'\n\n"
43
43
  "Please install the eval dependencies:\n"
44
- " pip install -e .[eval]\n\n"
44
+ ' uv pip install -e ".[eval]"\n\n'
45
45
  "Or install anthropic directly:\n"
46
- " pip install anthropic\n"
46
+ " uv pip install anthropic\n"
47
47
  )
48
48
  raise ImportError(error_msg)
49
49
 
@@ -51,9 +51,9 @@ class ClaudeClient:
51
51
  error_msg = (
52
52
  "\n❌ Error: Missing required package 'bs4' (BeautifulSoup4)\n\n"
53
53
  "Please install the eval dependencies:\n"
54
- " pip install -e .[eval]\n\n"
54
+ ' uv pip install -e ".[eval]"\n\n'
55
55
  "Or install beautifulsoup4 directly:\n"
56
- " pip install beautifulsoup4\n"
56
+ " uv pip install beautifulsoup4\n"
57
57
  )
58
58
  raise ImportError(error_msg)
59
59
 
gaia/llm/llm_client.py CHANGED
@@ -142,7 +142,7 @@ class LLMClient:
142
142
  logger.debug(f"Using Claude API with model={self.default_model}")
143
143
  elif use_claude and not CLAUDE_AVAILABLE:
144
144
  raise ValueError(
145
- "Claude support requested but anthropic library not available. Install with: pip install anthropic"
145
+ "Claude support requested but anthropic library not available. Install with: uv pip install anthropic"
146
146
  )
147
147
  elif use_openai:
148
148
  # Use OpenAI API