bedrock-agentcore-starter-toolkit 0.1.25__py3-none-any.whl → 0.1.27__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 +9 -1
- bedrock_agentcore_starter_toolkit/cli/runtime/commands.py +263 -7
- bedrock_agentcore_starter_toolkit/cli/runtime/configuration_manager.py +31 -7
- bedrock_agentcore_starter_toolkit/notebook/runtime/bedrock_agentcore.py +240 -2
- bedrock_agentcore_starter_toolkit/operations/identity/__init__.py +5 -0
- bedrock_agentcore_starter_toolkit/operations/identity/oauth2_callback_server.py +86 -0
- bedrock_agentcore_starter_toolkit/operations/memory/manager.py +20 -33
- bedrock_agentcore_starter_toolkit/operations/memory/models/strategies/base.py +2 -0
- bedrock_agentcore_starter_toolkit/operations/memory/models/strategies/self_managed.py +107 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/__init__.py +4 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/configure.py +120 -5
- bedrock_agentcore_starter_toolkit/operations/runtime/invoke.py +30 -54
- bedrock_agentcore_starter_toolkit/operations/runtime/launch.py +213 -16
- bedrock_agentcore_starter_toolkit/operations/runtime/models.py +19 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/status.py +30 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/stop_session.py +123 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/vpc_validation.py +196 -0
- bedrock_agentcore_starter_toolkit/services/runtime.py +46 -2
- bedrock_agentcore_starter_toolkit/utils/runtime/schema.py +44 -1
- {bedrock_agentcore_starter_toolkit-0.1.25.dist-info → bedrock_agentcore_starter_toolkit-0.1.27.dist-info}/METADATA +13 -12
- {bedrock_agentcore_starter_toolkit-0.1.25.dist-info → bedrock_agentcore_starter_toolkit-0.1.27.dist-info}/RECORD +25 -20
- {bedrock_agentcore_starter_toolkit-0.1.25.dist-info → bedrock_agentcore_starter_toolkit-0.1.27.dist-info}/WHEEL +0 -0
- {bedrock_agentcore_starter_toolkit-0.1.25.dist-info → bedrock_agentcore_starter_toolkit-0.1.27.dist-info}/entry_points.txt +0 -0
- {bedrock_agentcore_starter_toolkit-0.1.25.dist-info → bedrock_agentcore_starter_toolkit-0.1.27.dist-info}/licenses/LICENSE.txt +0 -0
- {bedrock_agentcore_starter_toolkit-0.1.25.dist-info → bedrock_agentcore_starter_toolkit-0.1.27.dist-info}/licenses/NOTICE.txt +0 -0
|
@@ -5,7 +5,14 @@ import typer
|
|
|
5
5
|
from ..cli.gateway.commands import create_mcp_gateway, create_mcp_gateway_target, gateway_app
|
|
6
6
|
from ..utils.logging_config import setup_toolkit_logging
|
|
7
7
|
from .import_agent.commands import import_agent
|
|
8
|
-
from .runtime.commands import
|
|
8
|
+
from .runtime.commands import (
|
|
9
|
+
configure_app,
|
|
10
|
+
destroy,
|
|
11
|
+
invoke,
|
|
12
|
+
launch,
|
|
13
|
+
status,
|
|
14
|
+
stop_session,
|
|
15
|
+
)
|
|
9
16
|
|
|
10
17
|
app = typer.Typer(name="agentcore", help="BedrockAgentCore CLI", add_completion=False, rich_markup_mode="rich")
|
|
11
18
|
|
|
@@ -18,6 +25,7 @@ app.command("status")(status)
|
|
|
18
25
|
app.command("launch")(launch)
|
|
19
26
|
app.command("import-agent")(import_agent)
|
|
20
27
|
app.command("destroy")(destroy)
|
|
28
|
+
app.command("stop-session")(stop_session)
|
|
21
29
|
app.add_typer(configure_app)
|
|
22
30
|
|
|
23
31
|
# gateway
|
|
@@ -4,6 +4,7 @@ import json
|
|
|
4
4
|
import logging
|
|
5
5
|
import os
|
|
6
6
|
from pathlib import Path
|
|
7
|
+
from threading import Thread
|
|
7
8
|
from typing import List, Optional
|
|
8
9
|
|
|
9
10
|
import typer
|
|
@@ -12,6 +13,7 @@ from prompt_toolkit.completion import PathCompleter
|
|
|
12
13
|
from rich.panel import Panel
|
|
13
14
|
from rich.syntax import Syntax
|
|
14
15
|
|
|
16
|
+
from ...operations.identity.oauth2_callback_server import start_oauth2_callback_server
|
|
15
17
|
from ...operations.runtime import (
|
|
16
18
|
configure_bedrock_agentcore,
|
|
17
19
|
destroy_bedrock_agentcore,
|
|
@@ -255,6 +257,33 @@ def configure(
|
|
|
255
257
|
help="Comma-separated list of allowed request headers "
|
|
256
258
|
"(Authorization or X-Amzn-Bedrock-AgentCore-Runtime-Custom-*)",
|
|
257
259
|
),
|
|
260
|
+
vpc: bool = typer.Option(
|
|
261
|
+
False, "--vpc", help="Enable VPC networking mode (requires --subnets and --security-groups)"
|
|
262
|
+
),
|
|
263
|
+
subnets: Optional[str] = typer.Option(
|
|
264
|
+
None,
|
|
265
|
+
"--subnets",
|
|
266
|
+
help="Comma-separated list of subnet IDs (e.g., subnet-abc123,subnet-def456). Required with --vpc.",
|
|
267
|
+
),
|
|
268
|
+
security_groups: Optional[str] = typer.Option(
|
|
269
|
+
None,
|
|
270
|
+
"--security-groups",
|
|
271
|
+
help="Comma-separated list of security group IDs (e.g., sg-xyz789). Required with --vpc.",
|
|
272
|
+
),
|
|
273
|
+
idle_timeout: Optional[int] = typer.Option(
|
|
274
|
+
None,
|
|
275
|
+
"--idle-timeout",
|
|
276
|
+
help="Idle runtime session timeout in seconds (60-28800, default: 900)",
|
|
277
|
+
min=60,
|
|
278
|
+
max=28800,
|
|
279
|
+
),
|
|
280
|
+
max_lifetime: Optional[int] = typer.Option(
|
|
281
|
+
None,
|
|
282
|
+
"--max-lifetime",
|
|
283
|
+
help="Maximum instance lifetime in seconds (60-28800, default: 28800)",
|
|
284
|
+
min=60,
|
|
285
|
+
max=28800,
|
|
286
|
+
),
|
|
258
287
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose output"),
|
|
259
288
|
region: Optional[str] = typer.Option(None, "--region", "-r"),
|
|
260
289
|
protocol: Optional[str] = typer.Option(None, "--protocol", "-p", help="Server protocol (HTTP or MCP or A2A)"),
|
|
@@ -275,6 +304,64 @@ def configure(
|
|
|
275
304
|
if protocol and protocol.upper() not in ["HTTP", "MCP", "A2A"]:
|
|
276
305
|
_handle_error("Error: --protocol must be either HTTP or MCP or A2A")
|
|
277
306
|
|
|
307
|
+
# Validate VPC configuration
|
|
308
|
+
vpc_subnets = None
|
|
309
|
+
vpc_security_groups = None
|
|
310
|
+
|
|
311
|
+
if vpc:
|
|
312
|
+
# VPC mode requires both subnets and security groups
|
|
313
|
+
if not subnets or not security_groups:
|
|
314
|
+
_handle_error(
|
|
315
|
+
"VPC mode requires both --subnets and --security-groups.\n"
|
|
316
|
+
"Example: agentcore configure --entrypoint my_agent.py --vpc "
|
|
317
|
+
"--subnets subnet-abc123,subnet-def456 --security-groups sg-xyz789"
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
# Parse and validate subnet IDs - UPDATED VALIDATION
|
|
321
|
+
vpc_subnets = [s.strip() for s in subnets.split(",") if s.strip()]
|
|
322
|
+
for subnet_id in vpc_subnets:
|
|
323
|
+
# Format: subnet-{8-17 hex characters}
|
|
324
|
+
if not subnet_id.startswith("subnet-"):
|
|
325
|
+
_handle_error(
|
|
326
|
+
f"Invalid subnet ID format: {subnet_id}\nSubnet IDs must start with 'subnet-' (e.g., subnet-abc123)"
|
|
327
|
+
)
|
|
328
|
+
# Check minimum length (subnet- + at least 8 chars)
|
|
329
|
+
if len(subnet_id) < 15: # "subnet-" (7) + 8 chars = 15
|
|
330
|
+
_handle_error(
|
|
331
|
+
f"Invalid subnet ID format: {subnet_id}\nSubnet ID is too short. Expected format: subnet-xxxxxxxx"
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
# Parse and validate security group IDs - UPDATED VALIDATION
|
|
335
|
+
vpc_security_groups = [sg.strip() for sg in security_groups.split(",") if sg.strip()]
|
|
336
|
+
for sg_id in vpc_security_groups:
|
|
337
|
+
# Format: sg-{8-17 hex characters}
|
|
338
|
+
if not sg_id.startswith("sg-"):
|
|
339
|
+
_handle_error(
|
|
340
|
+
f"Invalid security group ID format: {sg_id}\n"
|
|
341
|
+
f"Security group IDs must start with 'sg-' (e.g., sg-abc123)"
|
|
342
|
+
)
|
|
343
|
+
# Check minimum length (sg- + at least 8 chars)
|
|
344
|
+
if len(sg_id) < 11: # "sg-" (3) + 8 chars = 11
|
|
345
|
+
_handle_error(
|
|
346
|
+
f"Invalid security group ID format: {sg_id}\n"
|
|
347
|
+
f"Security group ID is too short. Expected format: sg-xxxxxxxx"
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
_print_success(
|
|
351
|
+
f"VPC mode enabled with {len(vpc_subnets)} subnets and {len(vpc_security_groups)} security groups"
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
elif subnets or security_groups:
|
|
355
|
+
# Error: VPC resources provided without --vpc flag
|
|
356
|
+
_handle_error(
|
|
357
|
+
"The --subnets and --security-groups flags require --vpc flag.\n"
|
|
358
|
+
"Use: agentcore configure --entrypoint my_agent.py --vpc --subnets ... --security-groups ..."
|
|
359
|
+
)
|
|
360
|
+
# Validate lifecycle configuration
|
|
361
|
+
if idle_timeout is not None and max_lifetime is not None:
|
|
362
|
+
if idle_timeout > max_lifetime:
|
|
363
|
+
_handle_error(f"Error: --idle-timeout ({idle_timeout}s) must be <= --max-lifetime ({max_lifetime}s)")
|
|
364
|
+
|
|
278
365
|
console.print("[cyan]Configuring Bedrock AgentCore...[/cyan]")
|
|
279
366
|
|
|
280
367
|
# Create configuration manager early for consistent prompting
|
|
@@ -397,6 +484,11 @@ def configure(
|
|
|
397
484
|
protocol=protocol.upper() if protocol else None,
|
|
398
485
|
non_interactive=non_interactive,
|
|
399
486
|
source_path=source_path,
|
|
487
|
+
vpc_enabled=vpc,
|
|
488
|
+
vpc_subnets=vpc_subnets,
|
|
489
|
+
vpc_security_groups=vpc_security_groups,
|
|
490
|
+
idle_timeout=idle_timeout,
|
|
491
|
+
max_lifetime=max_lifetime,
|
|
400
492
|
)
|
|
401
493
|
|
|
402
494
|
# Prepare authorization info for summary
|
|
@@ -410,10 +502,29 @@ def configure(
|
|
|
410
502
|
headers = request_header_config.get("requestHeaderAllowlist", [])
|
|
411
503
|
headers_info = f"Request Headers Allowlist: [dim]{len(headers)} headers configured[/dim]\n"
|
|
412
504
|
|
|
505
|
+
network_info = "Public"
|
|
506
|
+
if vpc:
|
|
507
|
+
network_info = f"VPC ({len(vpc_subnets)} subnets, {len(vpc_security_groups)} security groups)"
|
|
508
|
+
|
|
413
509
|
execution_role_display = "Auto-create" if not result.execution_role else result.execution_role
|
|
414
|
-
|
|
415
|
-
|
|
510
|
+
saved_config = load_config(result.config_path)
|
|
511
|
+
saved_agent = saved_config.get_agent_config(agent_name)
|
|
512
|
+
|
|
513
|
+
# Display memory status based on actual configuration
|
|
514
|
+
if saved_agent.memory.mode == "NO_MEMORY":
|
|
416
515
|
memory_info = "Disabled"
|
|
516
|
+
elif saved_agent.memory.mode == "STM_AND_LTM":
|
|
517
|
+
memory_info = "Short-term + Long-term memory (30-day retention)"
|
|
518
|
+
else: # STM_ONLY
|
|
519
|
+
memory_info = "Short-term memory (30-day retention)"
|
|
520
|
+
|
|
521
|
+
lifecycle_info = ""
|
|
522
|
+
if idle_timeout or max_lifetime:
|
|
523
|
+
lifecycle_info = "\n[bold]Lifecycle Settings:[/bold]\n"
|
|
524
|
+
if idle_timeout:
|
|
525
|
+
lifecycle_info += f"Idle Timeout: [cyan]{idle_timeout}s ({idle_timeout // 60} minutes)[/cyan]\n"
|
|
526
|
+
if max_lifetime:
|
|
527
|
+
lifecycle_info += f"Max Lifetime: [cyan]{max_lifetime}s ({max_lifetime // 3600} hours)[/cyan]\n"
|
|
417
528
|
|
|
418
529
|
console.print(
|
|
419
530
|
Panel(
|
|
@@ -427,9 +538,11 @@ def configure(
|
|
|
427
538
|
f"ECR Repository: [cyan]"
|
|
428
539
|
f"{'Auto-create' if result.auto_create_ecr else result.ecr_repository or 'N/A'}"
|
|
429
540
|
f"[/cyan]\n"
|
|
541
|
+
f"Network Mode: [cyan]{network_info}[/cyan]\n"
|
|
430
542
|
f"Authorization: [cyan]{auth_info}[/cyan]\n\n"
|
|
431
543
|
f"{headers_info}\n"
|
|
432
544
|
f"Memory: [cyan]{memory_info}[/cyan]\n\n"
|
|
545
|
+
f"{lifecycle_info}\n"
|
|
433
546
|
f"📄 Config saved to: [dim]{result.config_path}[/dim]\n\n"
|
|
434
547
|
f"[bold]Next Steps:[/bold]\n"
|
|
435
548
|
f" [cyan]agentcore launch[/cyan]",
|
|
@@ -566,6 +679,7 @@ def launch(
|
|
|
566
679
|
use_codebuild=not local_build,
|
|
567
680
|
env_vars=env_vars,
|
|
568
681
|
auto_update_on_conflict=auto_update_on_conflict,
|
|
682
|
+
console=console,
|
|
569
683
|
)
|
|
570
684
|
|
|
571
685
|
project_config = load_config(config_path)
|
|
@@ -575,12 +689,23 @@ def launch(
|
|
|
575
689
|
_print_success(f"Docker image built: {result.tag}")
|
|
576
690
|
_print_success("Ready to run locally")
|
|
577
691
|
console.print("Starting server at http://localhost:8080")
|
|
692
|
+
console.print("Starting OAuth2 3LO callback server at http://localhost:8081")
|
|
578
693
|
console.print("[yellow]Press Ctrl+C to stop[/yellow]\n")
|
|
579
694
|
|
|
580
695
|
if result.runtime is None or result.port is None:
|
|
581
696
|
_handle_error("Unable to launch locally")
|
|
582
697
|
|
|
583
698
|
try:
|
|
699
|
+
oauth2_callback_endpoint = Thread(
|
|
700
|
+
target=start_oauth2_callback_server,
|
|
701
|
+
args=(
|
|
702
|
+
config_path,
|
|
703
|
+
agent,
|
|
704
|
+
),
|
|
705
|
+
name="OAuth2 3LO Callback Server",
|
|
706
|
+
daemon=True,
|
|
707
|
+
)
|
|
708
|
+
oauth2_callback_endpoint.start()
|
|
584
709
|
result.runtime.run_local(result.tag, result.port, result.env_vars)
|
|
585
710
|
except KeyboardInterrupt:
|
|
586
711
|
console.print("\n[yellow]Stopped[/yellow]")
|
|
@@ -970,11 +1095,6 @@ def status(
|
|
|
970
1095
|
|
|
971
1096
|
# Determine overall status
|
|
972
1097
|
endpoint_status = endpoint_data.get("status", "Unknown") if endpoint_data else "Not Ready"
|
|
973
|
-
# memory_info = ""
|
|
974
|
-
# if hasattr(status_json["config"], "memory_id") and status_json["config"].get("memory_id"):
|
|
975
|
-
# memory_type = status_json["config"].get("memory_type", "Short-term")
|
|
976
|
-
# memory_id = status_json["config"].get("memory_id")
|
|
977
|
-
# memory_info = f"Memory: [cyan]{memory_type}[/cyan] ([dim]{memory_id}[/dim])\n"
|
|
978
1098
|
if endpoint_status == "READY":
|
|
979
1099
|
status_text = "Ready - Agent deployed and endpoint available"
|
|
980
1100
|
else:
|
|
@@ -992,6 +1112,26 @@ def status(
|
|
|
992
1112
|
f"Account: [dim]{status_json['config'].get('account', 'Not available')}[/dim]\n\n"
|
|
993
1113
|
)
|
|
994
1114
|
|
|
1115
|
+
# Add network information
|
|
1116
|
+
network_mode = status_json.get("agent", {}).get("networkConfiguration", {}).get("networkMode")
|
|
1117
|
+
if network_mode == "VPC":
|
|
1118
|
+
# Get VPC info from agent response (not config)
|
|
1119
|
+
network_config = (
|
|
1120
|
+
status_json.get("agent", {}).get("networkConfiguration", {}).get("networkModeConfig", {})
|
|
1121
|
+
)
|
|
1122
|
+
vpc_subnets = network_config.get("subnets", [])
|
|
1123
|
+
vpc_security_groups = network_config.get("securityGroups", [])
|
|
1124
|
+
subnet_count = len(vpc_subnets)
|
|
1125
|
+
sg_count = len(vpc_security_groups)
|
|
1126
|
+
vpc_id = status_json.get("config", {}).get("network_vpc_id", "unknown")
|
|
1127
|
+
if vpc_id:
|
|
1128
|
+
panel_content += f"Network: [cyan]VPC[/cyan] ([dim]{vpc_id}[/dim])\n"
|
|
1129
|
+
panel_content += f" {subnet_count} subnets, {sg_count} security groups\n\n"
|
|
1130
|
+
else:
|
|
1131
|
+
panel_content += "Network: [cyan]VPC[/cyan]\n\n"
|
|
1132
|
+
else:
|
|
1133
|
+
panel_content += "Network: [cyan]Public[/cyan]\n\n"
|
|
1134
|
+
|
|
995
1135
|
# Add memory status with proper provisioning indication
|
|
996
1136
|
if "memory_id" in status_json.get("config", {}) and status_json["config"]["memory_id"]:
|
|
997
1137
|
memory_type = status_json["config"].get("memory_type", "Unknown")
|
|
@@ -1021,6 +1161,19 @@ def status(
|
|
|
1021
1161
|
f"[/dim]\n\n"
|
|
1022
1162
|
)
|
|
1023
1163
|
|
|
1164
|
+
if status_json["config"].get("idle_timeout") or status_json["config"].get("max_lifetime"):
|
|
1165
|
+
panel_content += "[bold]Lifecycle Settings:[/bold]\n"
|
|
1166
|
+
|
|
1167
|
+
idle = status_json["config"].get("idle_timeout")
|
|
1168
|
+
if idle:
|
|
1169
|
+
panel_content += f"Idle Timeout: [cyan]{idle}s ({idle // 60} minutes)[/cyan]\n"
|
|
1170
|
+
|
|
1171
|
+
max_life = status_json["config"].get("max_lifetime")
|
|
1172
|
+
if max_life:
|
|
1173
|
+
panel_content += f"Max Lifetime: [cyan]{max_life}s ({max_life // 3600} hours)[/cyan]\n"
|
|
1174
|
+
|
|
1175
|
+
panel_content += "\n"
|
|
1176
|
+
|
|
1024
1177
|
# Add CloudWatch logs information
|
|
1025
1178
|
agent_id = status_json.get("config", {}).get("agent_id")
|
|
1026
1179
|
if agent_id:
|
|
@@ -1115,6 +1268,109 @@ def status(
|
|
|
1115
1268
|
raise typer.Exit(1) from e
|
|
1116
1269
|
|
|
1117
1270
|
|
|
1271
|
+
def stop_session(
|
|
1272
|
+
session_id: Optional[str] = typer.Option(
|
|
1273
|
+
None,
|
|
1274
|
+
"--session-id",
|
|
1275
|
+
"-s",
|
|
1276
|
+
help="Runtime session ID to stop. If not provided, stops the last active session from invoke.",
|
|
1277
|
+
),
|
|
1278
|
+
agent: Optional[str] = typer.Option(
|
|
1279
|
+
None,
|
|
1280
|
+
"--agent",
|
|
1281
|
+
"-a",
|
|
1282
|
+
help="Agent name (use 'agentcore configure list' to see available agents)",
|
|
1283
|
+
),
|
|
1284
|
+
):
|
|
1285
|
+
"""Stop an active runtime session.
|
|
1286
|
+
|
|
1287
|
+
Terminates the compute session for the running agent. This frees up resources
|
|
1288
|
+
and ends any ongoing agent processing for that session.
|
|
1289
|
+
|
|
1290
|
+
🔍 How to find session IDs:
|
|
1291
|
+
• Last invoked session is automatically tracked (no flag needed)
|
|
1292
|
+
• Check 'agentcore status' to see the tracked session ID
|
|
1293
|
+
• Check CloudWatch logs for session IDs from previous invokes
|
|
1294
|
+
• Session IDs are also visible in the config file: .bedrock_agentcore.yaml
|
|
1295
|
+
|
|
1296
|
+
⏱️ Session Lifecycle:
|
|
1297
|
+
• Runtime sessions are created when you invoke an agent
|
|
1298
|
+
• They automatically expire after the configured idle timeout
|
|
1299
|
+
• Stopping a session immediately frees resources without waiting for timeout
|
|
1300
|
+
|
|
1301
|
+
Examples:
|
|
1302
|
+
# Stop the last invoked session (most common)
|
|
1303
|
+
agentcore stop-session
|
|
1304
|
+
|
|
1305
|
+
# Stop a specific session by ID
|
|
1306
|
+
agentcore stop-session --session-id abc123xyz
|
|
1307
|
+
|
|
1308
|
+
# Stop last session for a specific agent
|
|
1309
|
+
agentcore stop-session --agent my-agent
|
|
1310
|
+
|
|
1311
|
+
# Get current session ID before stopping
|
|
1312
|
+
agentcore status # Shows tracked session ID
|
|
1313
|
+
agentcore stop-session
|
|
1314
|
+
"""
|
|
1315
|
+
config_path = Path.cwd() / ".bedrock_agentcore.yaml"
|
|
1316
|
+
|
|
1317
|
+
try:
|
|
1318
|
+
from ...operations.runtime import stop_runtime_session
|
|
1319
|
+
|
|
1320
|
+
result = stop_runtime_session(
|
|
1321
|
+
config_path=config_path,
|
|
1322
|
+
session_id=session_id,
|
|
1323
|
+
agent_name=agent,
|
|
1324
|
+
)
|
|
1325
|
+
|
|
1326
|
+
# Show result panel
|
|
1327
|
+
status_icon = "✅" if result.status_code == 200 else "⚠️"
|
|
1328
|
+
status_color = "green" if result.status_code == 200 else "yellow"
|
|
1329
|
+
|
|
1330
|
+
console.print(
|
|
1331
|
+
Panel(
|
|
1332
|
+
f"[{status_color}]{status_icon} {result.message}[/{status_color}]\n\n"
|
|
1333
|
+
f"[bold]Session Details:[/bold]\n"
|
|
1334
|
+
f"Session ID: [cyan]{result.session_id}[/cyan]\n"
|
|
1335
|
+
f"Agent: [cyan]{result.agent_name}[/cyan]\n"
|
|
1336
|
+
f"Status Code: [cyan]{result.status_code}[/cyan]\n\n"
|
|
1337
|
+
f"[dim]💡 Runtime sessions automatically expire after idle timeout.\n"
|
|
1338
|
+
f" Manually stopping frees resources immediately.[/dim]",
|
|
1339
|
+
title="Session Stopped",
|
|
1340
|
+
border_style="bright_blue",
|
|
1341
|
+
)
|
|
1342
|
+
)
|
|
1343
|
+
|
|
1344
|
+
except FileNotFoundError:
|
|
1345
|
+
_show_configuration_not_found_panel()
|
|
1346
|
+
raise typer.Exit(1) from None
|
|
1347
|
+
except ValueError as e:
|
|
1348
|
+
console.print(
|
|
1349
|
+
Panel(
|
|
1350
|
+
f"[red]❌ Failed to Stop Session[/red]\n\n"
|
|
1351
|
+
f"Error: {str(e)}\n\n"
|
|
1352
|
+
f"[bold]How to find session IDs:[/bold]\n"
|
|
1353
|
+
f" • Check 'agentcore status' for the tracked session ID\n"
|
|
1354
|
+
f" • Check CloudWatch logs for session IDs\n"
|
|
1355
|
+
f" • Invoke the agent first to create a session\n\n"
|
|
1356
|
+
f"[dim]Note: Runtime sessions cannot be listed. You can only stop\n"
|
|
1357
|
+
f"the session from your last invoke or a specific session ID.[/dim]",
|
|
1358
|
+
title="Stop Session Error",
|
|
1359
|
+
border_style="red",
|
|
1360
|
+
)
|
|
1361
|
+
)
|
|
1362
|
+
raise typer.Exit(1) from e
|
|
1363
|
+
except Exception as e:
|
|
1364
|
+
console.print(
|
|
1365
|
+
Panel(
|
|
1366
|
+
f"[red]❌ Unexpected Error[/red]\n\n{str(e)}",
|
|
1367
|
+
title="Stop Session Error",
|
|
1368
|
+
border_style="red",
|
|
1369
|
+
)
|
|
1370
|
+
)
|
|
1371
|
+
raise typer.Exit(1) from e
|
|
1372
|
+
|
|
1373
|
+
|
|
1118
1374
|
def destroy(
|
|
1119
1375
|
agent: Optional[str] = typer.Option(
|
|
1120
1376
|
None, "--agent", "-a", help="Agent name (use 'agentcore configure list' to see available agents)"
|
|
@@ -267,8 +267,8 @@ class ConfigurationManager:
|
|
|
267
267
|
|
|
268
268
|
Returns:
|
|
269
269
|
Tuple of (action, value) where:
|
|
270
|
-
- action is "USE_EXISTING", "CREATE_NEW"
|
|
271
|
-
- value is memory_id for USE_EXISTING, mode for CREATE_NEW
|
|
270
|
+
- action is "USE_EXISTING", "CREATE_NEW", "SKIP"
|
|
271
|
+
- value is memory_id for USE_EXISTING, mode for CREATE_NEW, None for SKIP
|
|
272
272
|
"""
|
|
273
273
|
if self.non_interactive:
|
|
274
274
|
# In non-interactive mode, default to creating new STM
|
|
@@ -285,8 +285,19 @@ class ConfigurationManager:
|
|
|
285
285
|
region = self.region or (self.existing_config.aws.region if self.existing_config else None)
|
|
286
286
|
|
|
287
287
|
if not region:
|
|
288
|
-
# No region available - skip
|
|
289
|
-
console.print("[dim]No region configured yet
|
|
288
|
+
# No region available - offer skip option
|
|
289
|
+
console.print("[dim]No region configured yet[/dim]")
|
|
290
|
+
console.print("\n[dim]Options:[/dim]")
|
|
291
|
+
console.print("[dim] • Press Enter to create new memory[/dim]")
|
|
292
|
+
console.print("[dim] • Type 's' to skip memory setup[/dim]") # <-- ADD
|
|
293
|
+
console.print()
|
|
294
|
+
|
|
295
|
+
response = _prompt_with_default("Your choice", "").strip().lower()
|
|
296
|
+
|
|
297
|
+
if response == "s" or response == "skip": # <-- ADD
|
|
298
|
+
_print_success("Skipping memory configuration")
|
|
299
|
+
return ("SKIP", None)
|
|
300
|
+
|
|
290
301
|
return self._prompt_new_memory_config()
|
|
291
302
|
|
|
292
303
|
memory_manager = MemoryManager(region_name=region)
|
|
@@ -311,10 +322,14 @@ class ConfigurationManager:
|
|
|
311
322
|
console.print("\n[dim]Options:[/dim]")
|
|
312
323
|
console.print("[dim] • Enter a number to use existing memory[/dim]")
|
|
313
324
|
console.print("[dim] • Press Enter to create new memory[/dim]")
|
|
325
|
+
console.print("[dim] • Type 's' to skip memory setup[/dim]")
|
|
314
326
|
|
|
315
327
|
response = _prompt_with_default("Your choice", "").strip().lower()
|
|
316
328
|
|
|
317
|
-
if response
|
|
329
|
+
if response == "s" or response == "skip":
|
|
330
|
+
_print_success("Skipping memory configuration")
|
|
331
|
+
return ("SKIP", None)
|
|
332
|
+
elif response.isdigit():
|
|
318
333
|
idx = int(response) - 1
|
|
319
334
|
if 0 <= idx < len(existing_memories):
|
|
320
335
|
selected = existing_memories[idx]
|
|
@@ -323,7 +338,16 @@ class ConfigurationManager:
|
|
|
323
338
|
else:
|
|
324
339
|
# No existing memories found
|
|
325
340
|
console.print("[yellow]No existing memory resources found in your account[/yellow]")
|
|
326
|
-
console.print("[dim]
|
|
341
|
+
console.print("\n[dim]Options:[/dim]")
|
|
342
|
+
console.print("[dim] • Press Enter to create new memory[/dim]")
|
|
343
|
+
console.print("[dim] • Type 's' to skip memory setup[/dim]")
|
|
344
|
+
console.print()
|
|
345
|
+
|
|
346
|
+
response = _prompt_with_default("Your choice", "").strip().lower()
|
|
347
|
+
|
|
348
|
+
if response == "s" or response == "skip":
|
|
349
|
+
_print_success("Skipping memory configuration")
|
|
350
|
+
return ("SKIP", None)
|
|
327
351
|
|
|
328
352
|
except Exception as e:
|
|
329
353
|
console.print(f"[dim]Could not list existing memories: {e}[/dim]")
|
|
@@ -332,7 +356,7 @@ class ConfigurationManager:
|
|
|
332
356
|
return self._prompt_new_memory_config()
|
|
333
357
|
|
|
334
358
|
def _prompt_new_memory_config(self) -> Tuple[str, str]:
|
|
335
|
-
"""Prompt for new memory configuration
|
|
359
|
+
"""Prompt for new memory configuration - LTM yes/no only."""
|
|
336
360
|
console.print("[green]✓ Short-term memory will be enabled (default)[/green]")
|
|
337
361
|
console.print(" • Stores conversations within sessions")
|
|
338
362
|
console.print(" • Provides immediate context recall")
|