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.
- bedrock_agentcore_starter_toolkit/cli/cli.py +3 -1
- bedrock_agentcore_starter_toolkit/cli/runtime/commands.py +431 -161
- bedrock_agentcore_starter_toolkit/operations/gateway/create_role.py +48 -12
- bedrock_agentcore_starter_toolkit/operations/runtime/__init__.py +4 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/destroy.py +542 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/invoke.py +1 -1
- bedrock_agentcore_starter_toolkit/operations/runtime/models.py +10 -0
- bedrock_agentcore_starter_toolkit/services/import_agent/scripts/base_bedrock_translate.py +7 -2
- bedrock_agentcore_starter_toolkit/services/runtime.py +34 -4
- bedrock_agentcore_starter_toolkit/utils/runtime/logs.py +6 -2
- {bedrock_agentcore_starter_toolkit-0.1.8.dist-info → bedrock_agentcore_starter_toolkit-0.1.10.dist-info}/METADATA +4 -3
- {bedrock_agentcore_starter_toolkit-0.1.8.dist-info → bedrock_agentcore_starter_toolkit-0.1.10.dist-info}/RECORD +16 -15
- {bedrock_agentcore_starter_toolkit-0.1.8.dist-info → bedrock_agentcore_starter_toolkit-0.1.10.dist-info}/WHEEL +0 -0
- {bedrock_agentcore_starter_toolkit-0.1.8.dist-info → bedrock_agentcore_starter_toolkit-0.1.10.dist-info}/entry_points.txt +0 -0
- {bedrock_agentcore_starter_toolkit-0.1.8.dist-info → bedrock_agentcore_starter_toolkit-0.1.10.dist-info}/licenses/LICENSE.txt +0 -0
- {bedrock_agentcore_starter_toolkit-0.1.8.dist-info → bedrock_agentcore_starter_toolkit-0.1.10.dist-info}/licenses/NOTICE.txt +0 -0
|
@@ -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
|
|
241
|
-
f"
|
|
242
|
-
f"
|
|
243
|
-
f"
|
|
244
|
-
f"
|
|
245
|
-
f"
|
|
246
|
-
f"
|
|
247
|
-
f"
|
|
248
|
-
f"
|
|
249
|
-
|
|
250
|
-
|
|
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
|
|
407
|
-
f"Agent
|
|
408
|
-
f"
|
|
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
|
|
411
|
-
f"
|
|
412
|
-
f"
|
|
413
|
-
f"[
|
|
414
|
-
f"
|
|
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]
|
|
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="
|
|
437
|
-
border_style="
|
|
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
|
|
450
|
-
deployment_type = "Local
|
|
465
|
+
title = "Local Build Success"
|
|
466
|
+
deployment_type = "✅ [green]Local Build Deployment Successful![/green]"
|
|
467
|
+
icon = "🔧"
|
|
451
468
|
else:
|
|
452
|
-
title = "
|
|
453
|
-
deployment_type = "
|
|
469
|
+
title = "Deployment Success"
|
|
470
|
+
deployment_type = "✅ [green]Deployment Successful![/green]"
|
|
471
|
+
icon = "🚀"
|
|
454
472
|
|
|
455
473
|
deploy_panel = (
|
|
456
|
-
f"
|
|
457
|
-
f"Agent
|
|
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"
|
|
461
|
-
f"[
|
|
462
|
-
f"
|
|
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]
|
|
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="
|
|
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 = {"
|
|
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
|
-
|
|
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
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
666
|
+
_show_error_response(f"Invocation failed: {str(e)}")
|
|
667
|
+
raise typer.Exit(1) from e
|
|
596
668
|
except Exception as e:
|
|
597
|
-
|
|
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"[
|
|
624
|
-
f"[
|
|
625
|
-
f"[cyan]
|
|
626
|
-
f"[cyan]
|
|
627
|
-
f"[cyan]
|
|
628
|
-
f"[
|
|
629
|
-
f"
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
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
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
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
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
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
|
-
|
|
679
|
-
f"
|
|
680
|
-
|
|
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
|
-
"[
|
|
695
|
-
"
|
|
696
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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"
|
|
1011
|
+
_handle_error(f"Destruction failed: {e}", e)
|