bedrock-agentcore-starter-toolkit 0.1.8__py3-none-any.whl → 0.1.10__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.

Potentially problematic release.


This version of bedrock-agentcore-starter-toolkit might be problematic. Click here for more details.

@@ -14,6 +14,7 @@ from rich.syntax import Syntax
14
14
 
15
15
  from ...operations.runtime import (
16
16
  configure_bedrock_agentcore,
17
+ destroy_bedrock_agentcore,
17
18
  get_status,
18
19
  invoke_bedrock_agentcore,
19
20
  launch_bedrock_agentcore,
@@ -27,6 +28,22 @@ from .configuration_manager import ConfigurationManager
27
28
  logger = logging.getLogger(__name__)
28
29
 
29
30
 
31
+ def _show_configuration_not_found_panel():
32
+ """Show standardized configuration not found panel."""
33
+ console.print(
34
+ Panel(
35
+ "⚠️ [yellow]Configuration Not Found[/yellow]\n\n"
36
+ "No agent configuration found in this directory.\n\n"
37
+ "[bold]Get Started:[/bold]\n"
38
+ " [cyan]agentcore configure --entrypoint your_agent.py[/cyan]\n"
39
+ " [cyan]agentcore launch[/cyan]\n"
40
+ ' [cyan]agentcore invoke \'{"prompt": "Hello"}\'[/cyan]',
41
+ title="⚠️ Setup Required",
42
+ border_style="bright_blue",
43
+ )
44
+ )
45
+
46
+
30
47
  def _validate_requirements_file(file_path: str) -> str:
31
48
  """Validate requirements file and return the path."""
32
49
  from ...utils.runtime.entrypoint import validate_requirements_file
@@ -237,17 +254,23 @@ def configure(
237
254
 
238
255
  console.print(
239
256
  Panel(
240
- f"[green]Configuration Summary[/green]\n\n"
241
- f"Name: {agent_name}\n"
242
- f"Runtime: {result.runtime}\n"
243
- f"Region: {result.region}\n"
244
- f"Account: {result.account_id}\n"
245
- f"Execution Role: {result.execution_role}\n"
246
- f"ECR: {'Auto-create' if result.auto_create_ecr else result.ecr_repository or 'N/A'}\n"
247
- f"Authorization: {auth_info}\n\n"
248
- f"Configuration saved to: {result.config_path}",
249
- title="Bedrock AgentCore Configured",
250
- border_style="green",
257
+ f"[green]Configuration Complete[/green]\n\n"
258
+ f"[bold]Agent Details:[/bold]\n"
259
+ f"Agent Name: [cyan]{agent_name}[/cyan]\n"
260
+ f"Runtime: [cyan]{result.runtime}[/cyan]\n"
261
+ f"Region: [cyan]{result.region}[/cyan]\n"
262
+ f"Account: [dim]{result.account_id}[/dim]\n\n"
263
+ f"[bold]Configuration:[/bold]\n"
264
+ f"Execution Role: [dim]{result.execution_role}[/dim]\n"
265
+ f"ECR Repository: [dim]"
266
+ f"{'Auto-create' if result.auto_create_ecr else result.ecr_repository or 'N/A'}"
267
+ f"[/dim]\n"
268
+ f"Authorization: [dim]{auth_info}[/dim]\n\n"
269
+ f"📄 Config saved to: [dim]{result.config_path}[/dim]\n\n"
270
+ f"[bold]Next Steps:[/bold]\n"
271
+ f" [cyan]agentcore launch[/cyan]",
272
+ title="Configuration Success",
273
+ border_style="bright_blue",
251
274
  )
252
275
  )
253
276
 
@@ -397,22 +420,19 @@ def launch(
397
420
  console.print("\n[yellow]Stopped[/yellow]")
398
421
 
399
422
  elif result.mode == "codebuild":
400
- _print_success(f"CodeBuild completed: [cyan]{result.codebuild_id}[/cyan]")
401
- _print_success(f"ARM64 image pushed to ECR: [cyan]{result.ecr_uri}:latest[/cyan]")
402
-
403
423
  # Show deployment success panel
404
424
  agent_name = result.tag.split(":")[0].replace("bedrock_agentcore-", "")
405
425
  deploy_panel = (
406
- f"[green]CodeBuild ARM64 Deployment Successful![/green]\n\n"
407
- f"Agent Name: {agent_name}\n"
408
- f"CodeBuild ID: [cyan]{result.codebuild_id}[/cyan]\n"
426
+ f"[green]CodeBuild Deployment Successful![/green]\n\n"
427
+ f"[bold]Agent Details:[/bold]\n"
428
+ f"Agent Name: [cyan]{agent_name}[/cyan]\n"
409
429
  f"Agent ARN: [cyan]{result.agent_arn}[/cyan]\n"
410
- f"ECR URI: [cyan]{result.ecr_uri}:latest[/cyan]\n\n"
411
- f"ARM64 container deployed to Bedrock AgentCore.\n\n"
412
- f"You can now check the status of your Bedrock AgentCore endpoint with:\n"
413
- f"[cyan]agentcore status[/cyan]\n\n"
414
- f"You can now invoke your Bedrock AgentCore endpoint with:\n"
415
- f'[cyan]agentcore invoke \'{{"prompt": "Hello"}}\'[/cyan]'
430
+ f"ECR URI: [cyan]{result.ecr_uri}:latest[/cyan]\n"
431
+ f"CodeBuild ID: [dim]{result.codebuild_id}[/dim]\n\n"
432
+ f"🚀 ARM64 container deployed to Bedrock AgentCore\n\n"
433
+ f"[bold]Next Steps:[/bold]\n"
434
+ f" [cyan]agentcore status[/cyan]\n"
435
+ f' [cyan]agentcore invoke \'{{"prompt": "Hello"}}\'[/cyan]'
416
436
  )
417
437
 
418
438
  # Add log information if we have agent_id
@@ -422,7 +442,7 @@ def launch(
422
442
  runtime_logs, otel_logs = get_agent_log_paths(result.agent_id)
423
443
  follow_cmd, since_cmd = get_aws_tail_commands(runtime_logs)
424
444
  deploy_panel += (
425
- f"\n\n📋 [cyan]Agent logs available at:[/cyan]\n"
445
+ f"\n\n📋 [cyan]CloudWatch Logs:[/cyan]\n"
426
446
  f" {runtime_logs}\n"
427
447
  f" {otel_logs}\n\n"
428
448
  f"💡 [dim]Tail logs with:[/dim]\n"
@@ -433,44 +453,42 @@ def launch(
433
453
  console.print(
434
454
  Panel(
435
455
  deploy_panel,
436
- title="CodeBuild Deployment Complete",
437
- border_style="green",
456
+ title="Deployment Success",
457
+ border_style="bright_blue",
438
458
  )
439
459
  )
440
460
 
441
461
  else: # cloud mode (either CodeBuild default or local-build)
442
- _print_success(f"Image pushed to ECR: [cyan]{result.ecr_uri}:latest[/cyan]")
443
-
444
- # Show deployment success panel
445
462
  agent_name = result.tag.split(":")[0].replace("bedrock_agentcore-", "")
446
463
 
447
- # Determine deployment type for panel title
448
464
  if local_build:
449
- title = "Local Build Deployment Complete"
450
- deployment_type = "Local Docker Build Deployment Successful!"
465
+ title = "Local Build Success"
466
+ deployment_type = "✅ [green]Local Build Deployment Successful![/green]"
467
+ icon = "🔧"
451
468
  else:
452
- title = "CodeBuild Deployment Complete"
453
- deployment_type = "CodeBuild Deployment Successful!"
469
+ title = "Deployment Success"
470
+ deployment_type = " [green]Deployment Successful![/green]"
471
+ icon = "🚀"
454
472
 
455
473
  deploy_panel = (
456
- f"[green]{deployment_type}[/green]\n\n"
457
- f"Agent Name: {agent_name}\n"
474
+ f"{deployment_type}\n\n"
475
+ f"[bold]Agent Details:[/bold]\n"
476
+ f"Agent Name: [cyan]{agent_name}[/cyan]\n"
458
477
  f"Agent ARN: [cyan]{result.agent_arn}[/cyan]\n"
459
478
  f"ECR URI: [cyan]{result.ecr_uri}[/cyan]\n\n"
460
- f"You can now check the status of your Bedrock AgentCore endpoint with:\n"
461
- f"[cyan]agentcore status[/cyan]\n\n"
462
- f"You can now invoke your Bedrock AgentCore endpoint with:\n"
463
- f'[cyan]agentcore invoke \'{{"prompt": "Hello"}}\'[/cyan]'
479
+ f"{icon} Container deployed to Bedrock AgentCore\n\n"
480
+ f"[bold]Next Steps:[/bold]\n"
481
+ f" [cyan]agentcore status[/cyan]\n"
482
+ f' [cyan]agentcore invoke \'{{"prompt": "Hello"}}\'[/cyan]'
464
483
  )
465
484
 
466
- # Add log information if we have agent_id
467
485
  if result.agent_id:
468
486
  from ...utils.runtime.logs import get_agent_log_paths, get_aws_tail_commands
469
487
 
470
488
  runtime_logs, otel_logs = get_agent_log_paths(result.agent_id)
471
489
  follow_cmd, since_cmd = get_aws_tail_commands(runtime_logs)
472
490
  deploy_panel += (
473
- f"\n\n📋 [cyan]Agent logs available at:[/cyan]\n"
491
+ f"\n\n📋 [cyan]CloudWatch Logs:[/cyan]\n"
474
492
  f" {runtime_logs}\n"
475
493
  f" {otel_logs}\n\n"
476
494
  f"💡 [dim]Tail logs with:[/dim]\n"
@@ -482,7 +500,7 @@ def launch(
482
500
  Panel(
483
501
  deploy_panel,
484
502
  title=title,
485
- border_style="green",
503
+ border_style="bright_blue",
486
504
  )
487
505
  )
488
506
 
@@ -498,6 +516,54 @@ def launch(
498
516
  raise
499
517
 
500
518
 
519
+ def _show_invoke_info_panel(agent_name: str, invoke_result=None, config=None):
520
+ """Show consistent panel with invoke information (session, request_id, arn, logs)."""
521
+ info_lines = []
522
+ # Session ID
523
+ if invoke_result and invoke_result.session_id:
524
+ info_lines.append(f"Session: [cyan]{invoke_result.session_id}[/cyan]")
525
+ # Request ID
526
+ if invoke_result and isinstance(invoke_result.response, dict):
527
+ request_id = invoke_result.response.get("ResponseMetadata", {}).get("RequestId")
528
+ if request_id:
529
+ info_lines.append(f"Request ID: [cyan]{request_id}[/cyan]")
530
+ # Agent ARN
531
+ if invoke_result and invoke_result.agent_arn:
532
+ info_lines.append(f"ARN: [cyan]{invoke_result.agent_arn}[/cyan]")
533
+ # CloudWatch logs (if we have config with agent_id)
534
+ if config and hasattr(config, "bedrock_agentcore") and config.bedrock_agentcore.agent_id:
535
+ try:
536
+ from ...utils.runtime.logs import get_agent_log_paths, get_aws_tail_commands
537
+
538
+ runtime_logs, _ = get_agent_log_paths(config.bedrock_agentcore.agent_id)
539
+ follow_cmd, since_cmd = get_aws_tail_commands(runtime_logs)
540
+ info_lines.append(f"Logs: {follow_cmd}")
541
+ info_lines.append(f" {since_cmd}")
542
+ except Exception:
543
+ pass # nosec B110
544
+ panel_content = "\n".join(info_lines) if info_lines else "Invoke information unavailable"
545
+ console.print(
546
+ Panel(
547
+ panel_content,
548
+ title=f"{agent_name}",
549
+ border_style="bright_blue",
550
+ padding=(0, 1),
551
+ )
552
+ )
553
+
554
+
555
+ def _show_success_response(content):
556
+ """Show success response content below panel."""
557
+ if content:
558
+ console.print("\n[bold]Response:[/bold]")
559
+ console.print(content)
560
+
561
+
562
+ def _show_error_response(error_msg: str):
563
+ """Show error message in red below panel."""
564
+ console.print(f"\n[red]{error_msg}[/red]")
565
+
566
+
501
567
  def invoke(
502
568
  payload: str = typer.Argument(..., help="JSON payload to send"),
503
569
  agent: Optional[str] = typer.Option(
@@ -524,7 +590,7 @@ def invoke(
524
590
  try:
525
591
  payload_data = json.loads(payload)
526
592
  except json.JSONDecodeError:
527
- payload_data = {"message": payload}
593
+ payload_data = {"prompt": payload}
528
594
 
529
595
  # Handle bearer token - only use if auth config is defined in .bedrock_agentcore.yaml
530
596
  final_bearer_token = None
@@ -543,17 +609,6 @@ def invoke(
543
609
  "[yellow]Warning: Bearer token provided but OAuth is not configured in .bedrock_agentcore.yaml[/yellow]"
544
610
  )
545
611
 
546
- # Display payload
547
- console.print("[bold]Payload:[/bold]")
548
- console.print(
549
- Syntax(
550
- json.dumps(payload_data, indent=2, ensure_ascii=False),
551
- "json",
552
- background_color="default",
553
- word_wrap=True,
554
- )
555
- )
556
-
557
612
  # Invoke
558
613
  result = invoke_bedrock_agentcore(
559
614
  config_path=config_path,
@@ -564,37 +619,91 @@ def invoke(
564
619
  user_id=user_id,
565
620
  local_mode=local_mode,
566
621
  )
567
- console.print(f"Session ID: [cyan]{result.session_id}[/cyan]")
622
+ agent_display = config.name if config else (agent or "unknown")
623
+ _show_invoke_info_panel(agent_display, result, config)
568
624
  if result.response != {}:
569
- console.print("\n[bold]Response:[/bold]")
570
- console.print(
571
- Syntax(
572
- json.dumps(result.response, indent=2, default=str, ensure_ascii=False),
573
- "json",
574
- background_color="default",
575
- word_wrap=True,
576
- )
577
- )
625
+ content = result.response
626
+ if isinstance(content, dict) and "response" in content:
627
+ content = content["response"]
628
+ if isinstance(content, list):
629
+ if len(content) == 1:
630
+ content = content[0]
631
+ else:
632
+ # Handle mix of strings and bytes
633
+ string_items = []
634
+ for item in content:
635
+ if isinstance(item, bytes):
636
+ string_items.append(item.decode("utf-8", errors="replace"))
637
+ else:
638
+ string_items.append(str(item))
639
+ content = "".join(string_items)
640
+ # Parse JSON string if needed (handles escape sequences)
641
+ if isinstance(content, str):
642
+ try:
643
+ parsed = json.loads(content)
644
+ if isinstance(parsed, dict) and "response" in parsed:
645
+ content = parsed["response"]
646
+ elif isinstance(parsed, str):
647
+ content = parsed
648
+ except (json.JSONDecodeError, TypeError):
649
+ pass
650
+ _show_success_response(content)
578
651
 
579
652
  except FileNotFoundError:
580
- console.print("[red].bedrock_agentcore.yaml not found[/red]")
581
- console.print("Run the following commands to get started:")
582
- console.print(" 1. agentcore configure --entrypoint your_agent.py")
583
- console.print(" 2. agentcore launch")
584
- console.print(' 3. agentcore invoke \'{"message": "Hello"}\'')
653
+ _show_configuration_not_found_panel()
585
654
  raise typer.Exit(1) from None
586
655
  except ValueError as e:
656
+ try:
657
+ agent_display = config.name if config else (agent or "unknown")
658
+ agent_config = config
659
+ except NameError:
660
+ agent_display = agent or "unknown"
661
+ agent_config = None
662
+ _show_invoke_info_panel(agent_display, invoke_result=None, config=agent_config)
587
663
  if "not deployed" in str(e):
588
- console.print("[yellow]Agent not deployed yet[/yellow]")
589
- console.print("Deploy your agent first:")
590
- console.print(" agentcore launch # Deploy to AWS (recommended)")
591
- console.print(" agentcore launch --local # Run locally")
592
- console.print("Then check status: agentcore status")
593
- _handle_error("Bedrock AgentCore not deployed. Run 'bedrock_agentcore launch' first", e)
664
+ _show_error_response("Agent not deployed - run 'agentcore launch' to deploy")
594
665
  else:
595
- _handle_error(f"Invocation failed: {e}", e)
666
+ _show_error_response(f"Invocation failed: {str(e)}")
667
+ raise typer.Exit(1) from e
596
668
  except Exception as e:
597
- _handle_error(f"Invocation failed: {e}", e)
669
+ try:
670
+ agent_config = config
671
+ agent_name = config.name if config else (agent or "unknown")
672
+ except (NameError, AttributeError):
673
+ try:
674
+ from ...utils.runtime.config import load_config
675
+
676
+ fallback_project_config = load_config(config_path)
677
+ agent_config = fallback_project_config.get_agent_config(agent)
678
+ agent_name = agent_config.name if agent_config else (agent or "unknown")
679
+ except Exception:
680
+ agent_config = None
681
+ agent_name = agent or "unknown"
682
+
683
+ from ...operations.runtime.models import InvokeResult
684
+
685
+ request_id = getattr(e, "response", {}).get("ResponseMetadata", {}).get("RequestId")
686
+ effective_session = session_id or (
687
+ agent_config.bedrock_agentcore.agent_session_id
688
+ if agent_config and hasattr(agent_config, "bedrock_agentcore")
689
+ else None
690
+ )
691
+
692
+ error_result = (
693
+ InvokeResult(
694
+ response={"ResponseMetadata": {"RequestId": request_id}} if request_id else {},
695
+ session_id=effective_session or "unknown",
696
+ agent_arn=agent_config.bedrock_agentcore.agent_arn
697
+ if agent_config and hasattr(agent_config, "bedrock_agentcore")
698
+ else None,
699
+ )
700
+ if (request_id or effective_session or agent_config)
701
+ else None
702
+ )
703
+
704
+ _show_invoke_info_panel(agent_name, invoke_result=error_result, config=agent_config)
705
+ _show_error_response(f"Invocation failed: {str(e)}")
706
+ raise typer.Exit(1) from e
598
707
 
599
708
 
600
709
  def status(
@@ -620,104 +729,99 @@ def status(
620
729
  if status_json["agent"] is None:
621
730
  console.print(
622
731
  Panel(
623
- f"[green]Status of the current Agent:[/green]\n\n"
624
- f"[green]Agent Name: {status_json['config']['name']}[/green]\n"
625
- f"[cyan]Configuration details:[/cyan]\n"
626
- f"[cyan]- region: {status_json['config']['region']}[/cyan]\n"
627
- f"[cyan]- account: {status_json['config']['account']}[/cyan]\n"
628
- f"[cyan]- execution role: {status_json['config']['execution_role']}[/cyan]\n"
629
- f"[cyan]- ecr repository: {status_json['config']['ecr_repository']}[/cyan]\n",
630
- title="Bedrock AgentCore Agent Status",
631
- border_style="green",
632
- )
633
- )
634
-
635
- console.print(
636
- Panel(
637
- "[yellow]Agent is configured, but not launched yet. "
638
- "Please use `agentcore launch` to launch the agent. [/yellow]\n\n",
639
- title="Bedrock AgentCore Agent Status",
640
- border_style="yellow",
732
+ f"⚠️ [yellow]Configured but not deployed[/yellow]\n\n"
733
+ f"[bold]Agent Details:[/bold]\n"
734
+ f"Agent Name: [cyan]{status_json['config']['name']}[/cyan]\n"
735
+ f"Region: [cyan]{status_json['config']['region']}[/cyan]\n"
736
+ f"Account: [cyan]{status_json['config']['account']}[/cyan]\n\n"
737
+ f"[bold]Configuration:[/bold]\n"
738
+ f"Execution Role: [dim]{status_json['config']['execution_role']}[/dim]\n"
739
+ f"ECR Repository: [dim]{status_json['config']['ecr_repository']}[/dim]\n\n"
740
+ f"Your agent is configured but not yet launched.\n\n"
741
+ f"[bold]Next Steps:[/bold]\n"
742
+ f" [cyan]agentcore launch[/cyan]",
743
+ title=f"Agent Status: {status_json['config']['name']}",
744
+ border_style="bright_blue",
641
745
  )
642
746
  )
643
747
 
644
748
  elif "agent" in status_json and status_json["agent"] is not None:
645
749
  agent_data = status_json["agent"]
646
- console.print(
647
- Panel(
648
- f"[green]Status of the current Agent:[/green]\n\n"
649
- f"[green]Agent Name: {status_json['config']['name']}[/green]\n"
650
- f"[green]Agent ID: {status_json['config']['agent_id']}[/green]\n"
651
- f"[green]Agent Arn: {status_json['config']['agent_arn']}[/green]\n"
652
- f"[green]Created at: {agent_data.get('createdAt', 'Not available')}[/green]\n"
653
- f"[green]Last Updated at: {agent_data.get('lastUpdatedAt', 'Not available')}[/green]\n"
654
- f"[cyan]Configuration details:[/cyan]\n"
655
- f"[cyan]- region: {status_json['config']['region']}[/cyan]\n"
656
- f"[cyan]- account: {status_json['config'].get('account', 'Not available')}[/cyan]\n"
657
- f"[cyan]- execution role: "
658
- f"{status_json['config'].get('execution_role', 'Not available')}[/cyan]\n"
659
- f"[cyan]- ecr repository: "
660
- f"{status_json['config'].get('ecr_repository', 'Not available')}[/cyan]\n",
661
- title="Bedrock AgentCore Agent Status",
662
- border_style="green",
663
- )
750
+ endpoint_data = status_json.get("endpoint", {})
751
+
752
+ # Determine overall status
753
+ endpoint_status = endpoint_data.get("status", "Unknown") if endpoint_data else "Not Ready"
754
+ if endpoint_status == "READY":
755
+ status_text = "Ready - Agent deployed and endpoint available"
756
+ else:
757
+ status_text = "Deploying - Agent created, endpoint starting"
758
+
759
+ # Build consolidated panel with logs
760
+ panel_content = (
761
+ f"{status_text}\n\n"
762
+ f"[bold]Agent Details:[/bold]\n"
763
+ f"Agent Name: [cyan]{status_json['config']['name']}[/cyan]\n"
764
+ f"Agent ARN: [cyan]{status_json['config']['agent_arn']}[/cyan]\n"
765
+ f"Endpoint: [cyan]{endpoint_data.get('name', 'DEFAULT')}[/cyan] "
766
+ f"([cyan]{endpoint_status}[/cyan])\n"
767
+ f"Region: [cyan]{status_json['config']['region']}[/cyan] | "
768
+ f"Account: [dim]{status_json['config'].get('account', 'Not available')}[/dim]\n\n"
769
+ f"[bold]Deployment Info:[/bold]\n"
770
+ f"Created: [dim]{agent_data.get('createdAt', 'Not available')}[/dim]\n"
771
+ f"Last Updated: [dim]"
772
+ f"{endpoint_data.get('lastUpdatedAt') or agent_data.get('lastUpdatedAt', 'Not available')}"
773
+ f"[/dim]\n\n"
664
774
  )
665
- else:
666
- console.print(
667
- Panel(
668
- "[green]Please launch agent first![/green]\n\n",
669
- title="Bedrock AgentCore Agent Status",
670
- border_style="yellow",
775
+
776
+ # Add CloudWatch logs information
777
+ agent_id = status_json.get("config", {}).get("agent_id")
778
+ if agent_id:
779
+ try:
780
+ from ...utils.runtime.logs import get_agent_log_paths, get_aws_tail_commands
781
+
782
+ endpoint_name = endpoint_data.get("name")
783
+ runtime_logs, otel_logs = get_agent_log_paths(agent_id, endpoint_name)
784
+ follow_cmd, since_cmd = get_aws_tail_commands(runtime_logs)
785
+
786
+ panel_content += (
787
+ f"📋 [cyan]CloudWatch Logs:[/cyan]\n"
788
+ f" {runtime_logs}\n"
789
+ f" {otel_logs}\n\n"
790
+ f"💡 [dim]Tail logs with:[/dim]\n"
791
+ f" {follow_cmd}\n"
792
+ f" {since_cmd}\n\n"
793
+ )
794
+ except Exception: # nosec B110
795
+ # If log retrieval fails, continue without logs section
796
+ pass
797
+
798
+ # Add ready-to-invoke message if endpoint is ready
799
+ if endpoint_status == "READY":
800
+ panel_content += (
801
+ '[bold]Ready to invoke:[/bold]\n [cyan]agentcore invoke \'{"prompt": "Hello"}\'[/cyan]'
802
+ )
803
+ else:
804
+ panel_content += (
805
+ "[bold]Next Steps:[/bold]\n"
806
+ " [cyan]agentcore status[/cyan] # Check when endpoint is ready"
671
807
  )
672
- )
673
808
 
674
- if "endpoint" in status_json and status_json["endpoint"] is not None:
675
- endpoint_data = status_json["endpoint"]
676
809
  console.print(
677
810
  Panel(
678
- f"[green]Status of the current Endpoint:[/green]\n\n"
679
- f"[green]Endpoint Id: {endpoint_data.get('id', 'Not available')}[/green]\n"
680
- f"[green]Endpoint Name: {endpoint_data.get('name', 'Not available')}[/green]\n"
681
- f"[green]Endpoint Arn: "
682
- f"{endpoint_data.get('agentRuntimeEndpointArn', 'Not available')}[/green]\n"
683
- f"[green]Agent Arn: {endpoint_data.get('agentRuntimeArn', 'Not available')}[/green]\n"
684
- f"[green]STATUS: [cyan]{endpoint_data.get('status', 'Unknown')}[/cyan][/green]\n"
685
- f"[green]Last Updated at: "
686
- f"{endpoint_data.get('lastUpdatedAt', 'Not available')}[/green]\n",
687
- title="Bedrock AgentCore Endpoint Status",
688
- border_style="green",
811
+ panel_content,
812
+ title=f"Agent Status: {status_json['config']['name']}",
813
+ border_style="bright_blue",
689
814
  )
690
815
  )
691
816
  else:
692
817
  console.print(
693
818
  Panel(
694
- "[yellow]Please launch agent first and make sure endpoint status is READY "
695
- "before invoking![/yellow]\n\n",
696
- title="Bedrock AgentCore Endpoint Status",
697
- border_style="yellow",
819
+ "[green]Please launch agent first![/green]\n\n",
820
+ title="Bedrock AgentCore Agent Status",
821
+ border_style="bright_blue",
698
822
  )
699
823
  )
700
824
 
701
- # Show log information
702
- agent_id = status_json.get("config", {}).get("agent_id")
703
- if agent_id:
704
- try:
705
- from ...utils.runtime.logs import get_agent_log_paths, get_aws_tail_commands
706
-
707
- endpoint_name = status_json.get("endpoint", {}).get("name")
708
-
709
- runtime_logs, otel_logs = get_agent_log_paths(agent_id, endpoint_name)
710
- follow_cmd, since_cmd = get_aws_tail_commands(runtime_logs)
711
-
712
- console.print("\n📋 [cyan]Agent logs available at:[/cyan]")
713
- console.print(f" {runtime_logs}")
714
- console.print(f" {otel_logs}")
715
- console.print("\n💡 [dim]Tail logs with:[/dim]")
716
- console.print(f" {follow_cmd}")
717
- console.print(f" {since_cmd}")
718
- except (ValueError, TypeError) as e:
719
- # If logging info fails, log the error and continue
720
- logger.debug("Failed to display log paths: %s", str(e))
721
825
  else: # full json verbose output
722
826
  console.print(
723
827
  Syntax(
@@ -729,13 +833,179 @@ def status(
729
833
  )
730
834
 
731
835
  except FileNotFoundError:
732
- console.print("[yellow]Configuration not found[/yellow]")
836
+ _show_configuration_not_found_panel()
837
+ raise typer.Exit(1) from None
838
+ except ValueError as e:
839
+ console.print(
840
+ Panel(
841
+ f"❌ [red]Status Check Failed[/red]\n\n"
842
+ f"Error: {str(e)}\n\n"
843
+ f"[bold]Next Steps:[/bold]\n"
844
+ f" [cyan]agentcore configure --entrypoint your_agent.py[/cyan]\n"
845
+ f" [cyan]agentcore launch[/cyan]",
846
+ title="❌ Status Error",
847
+ border_style="bright_blue",
848
+ )
849
+ )
850
+ raise typer.Exit(1) from e
851
+ except Exception as e:
852
+ console.print(
853
+ Panel(
854
+ f"❌ [red]Status Check Failed[/red]\n\n"
855
+ f"Unexpected error: {str(e)}\n\n"
856
+ f"[bold]Next Steps:[/bold]\n"
857
+ f" [cyan]agentcore configure --entrypoint your_agent.py[/cyan]\n"
858
+ f" [cyan]agentcore launch[/cyan]",
859
+ title="❌ Status Error",
860
+ border_style="bright_blue",
861
+ )
862
+ )
863
+ raise typer.Exit(1) from e
864
+
865
+
866
+ def destroy(
867
+ agent: Optional[str] = typer.Option(
868
+ None, "--agent", "-a", help="Agent name (use 'agentcore configure list' to see available agents)"
869
+ ),
870
+ dry_run: bool = typer.Option(
871
+ False, "--dry-run", help="Show what would be destroyed without actually destroying anything"
872
+ ),
873
+ force: bool = typer.Option(
874
+ False, "--force", help="Skip confirmation prompts and destroy immediately"
875
+ ),
876
+ delete_ecr_repo: bool = typer.Option(
877
+ False, "--delete-ecr-repo", help="Also delete the ECR repository after removing images"
878
+ ),
879
+ ) -> None:
880
+ """Destroy Bedrock AgentCore resources.
881
+
882
+ This command removes the following AWS resources for the specified agent:
883
+ - Bedrock AgentCore endpoint (if exists)
884
+ - Bedrock AgentCore agent runtime
885
+ - ECR images (all images in the agent's repository)
886
+ - CodeBuild project
887
+ - IAM execution role (only if not used by other agents)
888
+ - Agent deployment configuration
889
+ - ECR repository (only if --delete-ecr-repo is specified)
890
+
891
+ CAUTION: This action cannot be undone. Use --dry-run to preview changes first.
892
+ """
893
+ config_path = Path.cwd() / ".bedrock_agentcore.yaml"
894
+
895
+ try:
896
+ from ...utils.runtime.config import load_config
897
+
898
+ # Load project configuration to get agent details
899
+ project_config = load_config(config_path)
900
+ agent_config = project_config.get_agent_config(agent)
901
+
902
+ if not agent_config:
903
+ _handle_error(f"Agent '{agent or 'default'}' not found in configuration")
904
+
905
+ actual_agent_name = agent_config.name
906
+
907
+ # Show what will be destroyed
908
+ if dry_run:
909
+ console.print(f"[cyan]🔍 Dry run: Preview of resources that would be destroyed for agent '{actual_agent_name}'[/cyan]\n")
910
+ else:
911
+ console.print(f"[yellow]⚠️ About to destroy resources for agent '{actual_agent_name}'[/yellow]\n")
912
+
913
+ # Check if agent is deployed
914
+ if not agent_config.bedrock_agentcore:
915
+ console.print("[yellow]Agent is not deployed, nothing to destroy[/yellow]")
916
+ return
917
+
918
+ # Show deployment details
919
+ console.print("[cyan]Current deployment:[/cyan]")
920
+ if agent_config.bedrock_agentcore.agent_arn:
921
+ console.print(f" • Agent ARN: {agent_config.bedrock_agentcore.agent_arn}")
922
+ if agent_config.bedrock_agentcore.agent_id:
923
+ console.print(f" • Agent ID: {agent_config.bedrock_agentcore.agent_id}")
924
+ if agent_config.aws.ecr_repository:
925
+ console.print(f" • ECR Repository: {agent_config.aws.ecr_repository}")
926
+ if agent_config.aws.execution_role:
927
+ console.print(f" • Execution Role: {agent_config.aws.execution_role}")
928
+ console.print()
929
+
930
+ # Confirmation prompt (unless force or dry_run)
931
+ if not dry_run and not force:
932
+ console.print("[red]This will permanently delete AWS resources and cannot be undone![/red]")
933
+ if delete_ecr_repo:
934
+ console.print("[red]This includes deleting the ECR repository itself![/red]")
935
+ response = typer.confirm(
936
+ f"Are you sure you want to destroy the agent '{actual_agent_name}' and all its resources?"
937
+ )
938
+ if not response:
939
+ console.print("[yellow]Destruction cancelled[/yellow]")
940
+ return
941
+
942
+ # Perform the destroy operation
943
+ with console.status(f"[bold]{'Analyzing' if dry_run else 'Destroying'} Bedrock AgentCore resources...[/bold]"):
944
+ result = destroy_bedrock_agentcore(
945
+ config_path=config_path,
946
+ agent_name=actual_agent_name,
947
+ dry_run=dry_run,
948
+ force=force,
949
+ delete_ecr_repo=delete_ecr_repo,
950
+ )
951
+
952
+ # Display results
953
+ if dry_run:
954
+ console.print(f"[cyan]📋 Dry run completed for agent '{result.agent_name}'[/cyan]\n")
955
+ title = "Resources That Would Be Destroyed"
956
+ color = "cyan"
957
+ else:
958
+ if result.errors:
959
+ console.print(f"[yellow]⚠️ Destruction completed with errors for agent '{result.agent_name}'[/yellow]\n")
960
+ title = "Destruction Results (With Errors)"
961
+ color = "yellow"
962
+ else:
963
+ console.print(f"[green]✅ Successfully destroyed resources for agent '{result.agent_name}'[/green]\n")
964
+ title = "Resources Successfully Destroyed"
965
+ color = "green"
966
+
967
+ # Show resources removed
968
+ if result.resources_removed:
969
+ resources_text = "\n".join([f" ✓ {resource}" for resource in result.resources_removed])
970
+ console.print(Panel(resources_text, title=title, border_style=color))
971
+ else:
972
+ console.print(Panel("No resources were found to destroy", title="Results", border_style="yellow"))
973
+
974
+ # Show warnings
975
+ if result.warnings:
976
+ warnings_text = "\n".join([f" ⚠️ {warning}" for warning in result.warnings])
977
+ console.print(Panel(warnings_text, title="Warnings", border_style="yellow"))
978
+
979
+ # Show errors
980
+ if result.errors:
981
+ errors_text = "\n".join([f" ❌ {error}" for error in result.errors])
982
+ console.print(Panel(errors_text, title="Errors", border_style="red"))
983
+
984
+ # Next steps
985
+ if not dry_run and not result.errors:
986
+ console.print("\n[dim]Next steps:[/dim]")
987
+ console.print(" • Run 'agentcore configure --entrypoint <file>' to set up a new agent")
988
+ console.print(" • Run 'agentcore launch' to deploy to Bedrock AgentCore")
989
+ elif dry_run:
990
+ console.print(f"\n[dim]To actually destroy these resources, run:[/dim]")
991
+ destroy_cmd = f" agentcore destroy{f' --agent {actual_agent_name}' if agent else ''}"
992
+ if delete_ecr_repo:
993
+ destroy_cmd += " --delete-ecr-repo"
994
+ console.print(destroy_cmd)
995
+
996
+ except FileNotFoundError:
997
+ console.print("[red].bedrock_agentcore.yaml not found[/red]")
733
998
  console.print("Run the following commands to get started:")
734
999
  console.print(" 1. agentcore configure --entrypoint your_agent.py")
735
1000
  console.print(" 2. agentcore launch")
736
1001
  console.print(' 3. agentcore invoke \'{"message": "Hello"}\'')
737
1002
  raise typer.Exit(1) from None
738
1003
  except ValueError as e:
739
- _handle_error(f"Status failed: {e}", e)
1004
+ if "not found" in str(e):
1005
+ _handle_error("Agent not found. Use 'agentcore configure list' to see available agents", e)
1006
+ else:
1007
+ _handle_error(f"Destruction failed: {e}", e)
1008
+ except RuntimeError as e:
1009
+ _handle_error(f"Destruction failed: {e}", e)
740
1010
  except Exception as e:
741
- _handle_error(f"Status failed: {e}", e)
1011
+ _handle_error(f"Destruction failed: {e}", e)