bedrock-agentcore-starter-toolkit 0.1.26__py3-none-any.whl → 0.1.28__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 -12
- 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/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 +130 -11
- bedrock_agentcore_starter_toolkit/operations/runtime/invoke.py +0 -53
- 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 +43 -1
- bedrock_agentcore_starter_toolkit/utils/runtime/schema.py +44 -1
- {bedrock_agentcore_starter_toolkit-0.1.26.dist-info → bedrock_agentcore_starter_toolkit-0.1.28.dist-info}/METADATA +8 -8
- {bedrock_agentcore_starter_toolkit-0.1.26.dist-info → bedrock_agentcore_starter_toolkit-0.1.28.dist-info}/RECORD +23 -20
- {bedrock_agentcore_starter_toolkit-0.1.26.dist-info → bedrock_agentcore_starter_toolkit-0.1.28.dist-info}/WHEEL +0 -0
- {bedrock_agentcore_starter_toolkit-0.1.26.dist-info → bedrock_agentcore_starter_toolkit-0.1.28.dist-info}/entry_points.txt +0 -0
- {bedrock_agentcore_starter_toolkit-0.1.26.dist-info → bedrock_agentcore_starter_toolkit-0.1.28.dist-info}/licenses/LICENSE.txt +0 -0
- {bedrock_agentcore_starter_toolkit-0.1.26.dist-info → bedrock_agentcore_starter_toolkit-0.1.28.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
|
|
@@ -162,20 +162,28 @@ def _detect_entrypoint_in_source(source_path: str, non_interactive: bool = False
|
|
|
162
162
|
# Use operations layer for detection
|
|
163
163
|
detected = detect_entrypoint(source_dir)
|
|
164
164
|
|
|
165
|
-
if
|
|
166
|
-
# No
|
|
165
|
+
if len(detected) == 0:
|
|
166
|
+
# No files found - error
|
|
167
167
|
rel_source = get_relative_path(source_dir)
|
|
168
168
|
_handle_error(
|
|
169
169
|
f"No entrypoint file found in {rel_source}\n"
|
|
170
170
|
f"Expected one of: main.py, agent.py, app.py, __main__.py\n"
|
|
171
171
|
f"Please specify full file path (e.g., {rel_source}/your_agent.py)"
|
|
172
172
|
)
|
|
173
|
+
elif len(detected) > 1:
|
|
174
|
+
# Multiple files found - error with list
|
|
175
|
+
rel_source = get_relative_path(source_dir)
|
|
176
|
+
files_list = ", ".join(f.name for f in detected)
|
|
177
|
+
_handle_error(
|
|
178
|
+
f"Multiple entrypoint files found in {rel_source}: {files_list}\n"
|
|
179
|
+
f"Please specify full file path (e.g., {rel_source}/main.py)"
|
|
180
|
+
)
|
|
173
181
|
|
|
174
|
-
#
|
|
175
|
-
rel_entrypoint = get_relative_path(detected)
|
|
182
|
+
# Exactly one file - show detection and confirm
|
|
183
|
+
rel_entrypoint = get_relative_path(detected[0])
|
|
176
184
|
|
|
177
185
|
_print_success(f"Using entrypoint file: [cyan]{rel_entrypoint}[/cyan]")
|
|
178
|
-
return str(detected)
|
|
186
|
+
return str(detected[0])
|
|
179
187
|
|
|
180
188
|
|
|
181
189
|
# Define options at module level to avoid B008
|
|
@@ -257,6 +265,33 @@ def configure(
|
|
|
257
265
|
help="Comma-separated list of allowed request headers "
|
|
258
266
|
"(Authorization or X-Amzn-Bedrock-AgentCore-Runtime-Custom-*)",
|
|
259
267
|
),
|
|
268
|
+
vpc: bool = typer.Option(
|
|
269
|
+
False, "--vpc", help="Enable VPC networking mode (requires --subnets and --security-groups)"
|
|
270
|
+
),
|
|
271
|
+
subnets: Optional[str] = typer.Option(
|
|
272
|
+
None,
|
|
273
|
+
"--subnets",
|
|
274
|
+
help="Comma-separated list of subnet IDs (e.g., subnet-abc123,subnet-def456). Required with --vpc.",
|
|
275
|
+
),
|
|
276
|
+
security_groups: Optional[str] = typer.Option(
|
|
277
|
+
None,
|
|
278
|
+
"--security-groups",
|
|
279
|
+
help="Comma-separated list of security group IDs (e.g., sg-xyz789). Required with --vpc.",
|
|
280
|
+
),
|
|
281
|
+
idle_timeout: Optional[int] = typer.Option(
|
|
282
|
+
None,
|
|
283
|
+
"--idle-timeout",
|
|
284
|
+
help="Idle runtime session timeout in seconds (60-28800, default: 900)",
|
|
285
|
+
min=60,
|
|
286
|
+
max=28800,
|
|
287
|
+
),
|
|
288
|
+
max_lifetime: Optional[int] = typer.Option(
|
|
289
|
+
None,
|
|
290
|
+
"--max-lifetime",
|
|
291
|
+
help="Maximum instance lifetime in seconds (60-28800, default: 28800)",
|
|
292
|
+
min=60,
|
|
293
|
+
max=28800,
|
|
294
|
+
),
|
|
260
295
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose output"),
|
|
261
296
|
region: Optional[str] = typer.Option(None, "--region", "-r"),
|
|
262
297
|
protocol: Optional[str] = typer.Option(None, "--protocol", "-p", help="Server protocol (HTTP or MCP or A2A)"),
|
|
@@ -277,6 +312,64 @@ def configure(
|
|
|
277
312
|
if protocol and protocol.upper() not in ["HTTP", "MCP", "A2A"]:
|
|
278
313
|
_handle_error("Error: --protocol must be either HTTP or MCP or A2A")
|
|
279
314
|
|
|
315
|
+
# Validate VPC configuration
|
|
316
|
+
vpc_subnets = None
|
|
317
|
+
vpc_security_groups = None
|
|
318
|
+
|
|
319
|
+
if vpc:
|
|
320
|
+
# VPC mode requires both subnets and security groups
|
|
321
|
+
if not subnets or not security_groups:
|
|
322
|
+
_handle_error(
|
|
323
|
+
"VPC mode requires both --subnets and --security-groups.\n"
|
|
324
|
+
"Example: agentcore configure --entrypoint my_agent.py --vpc "
|
|
325
|
+
"--subnets subnet-abc123,subnet-def456 --security-groups sg-xyz789"
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
# Parse and validate subnet IDs - UPDATED VALIDATION
|
|
329
|
+
vpc_subnets = [s.strip() for s in subnets.split(",") if s.strip()]
|
|
330
|
+
for subnet_id in vpc_subnets:
|
|
331
|
+
# Format: subnet-{8-17 hex characters}
|
|
332
|
+
if not subnet_id.startswith("subnet-"):
|
|
333
|
+
_handle_error(
|
|
334
|
+
f"Invalid subnet ID format: {subnet_id}\nSubnet IDs must start with 'subnet-' (e.g., subnet-abc123)"
|
|
335
|
+
)
|
|
336
|
+
# Check minimum length (subnet- + at least 8 chars)
|
|
337
|
+
if len(subnet_id) < 15: # "subnet-" (7) + 8 chars = 15
|
|
338
|
+
_handle_error(
|
|
339
|
+
f"Invalid subnet ID format: {subnet_id}\nSubnet ID is too short. Expected format: subnet-xxxxxxxx"
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
# Parse and validate security group IDs - UPDATED VALIDATION
|
|
343
|
+
vpc_security_groups = [sg.strip() for sg in security_groups.split(",") if sg.strip()]
|
|
344
|
+
for sg_id in vpc_security_groups:
|
|
345
|
+
# Format: sg-{8-17 hex characters}
|
|
346
|
+
if not sg_id.startswith("sg-"):
|
|
347
|
+
_handle_error(
|
|
348
|
+
f"Invalid security group ID format: {sg_id}\n"
|
|
349
|
+
f"Security group IDs must start with 'sg-' (e.g., sg-abc123)"
|
|
350
|
+
)
|
|
351
|
+
# Check minimum length (sg- + at least 8 chars)
|
|
352
|
+
if len(sg_id) < 11: # "sg-" (3) + 8 chars = 11
|
|
353
|
+
_handle_error(
|
|
354
|
+
f"Invalid security group ID format: {sg_id}\n"
|
|
355
|
+
f"Security group ID is too short. Expected format: sg-xxxxxxxx"
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
_print_success(
|
|
359
|
+
f"VPC mode enabled with {len(vpc_subnets)} subnets and {len(vpc_security_groups)} security groups"
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
elif subnets or security_groups:
|
|
363
|
+
# Error: VPC resources provided without --vpc flag
|
|
364
|
+
_handle_error(
|
|
365
|
+
"The --subnets and --security-groups flags require --vpc flag.\n"
|
|
366
|
+
"Use: agentcore configure --entrypoint my_agent.py --vpc --subnets ... --security-groups ..."
|
|
367
|
+
)
|
|
368
|
+
# Validate lifecycle configuration
|
|
369
|
+
if idle_timeout is not None and max_lifetime is not None:
|
|
370
|
+
if idle_timeout > max_lifetime:
|
|
371
|
+
_handle_error(f"Error: --idle-timeout ({idle_timeout}s) must be <= --max-lifetime ({max_lifetime}s)")
|
|
372
|
+
|
|
280
373
|
console.print("[cyan]Configuring Bedrock AgentCore...[/cyan]")
|
|
281
374
|
|
|
282
375
|
# Create configuration manager early for consistent prompting
|
|
@@ -399,6 +492,11 @@ def configure(
|
|
|
399
492
|
protocol=protocol.upper() if protocol else None,
|
|
400
493
|
non_interactive=non_interactive,
|
|
401
494
|
source_path=source_path,
|
|
495
|
+
vpc_enabled=vpc,
|
|
496
|
+
vpc_subnets=vpc_subnets,
|
|
497
|
+
vpc_security_groups=vpc_security_groups,
|
|
498
|
+
idle_timeout=idle_timeout,
|
|
499
|
+
max_lifetime=max_lifetime,
|
|
402
500
|
)
|
|
403
501
|
|
|
404
502
|
# Prepare authorization info for summary
|
|
@@ -412,10 +510,29 @@ def configure(
|
|
|
412
510
|
headers = request_header_config.get("requestHeaderAllowlist", [])
|
|
413
511
|
headers_info = f"Request Headers Allowlist: [dim]{len(headers)} headers configured[/dim]\n"
|
|
414
512
|
|
|
513
|
+
network_info = "Public"
|
|
514
|
+
if vpc:
|
|
515
|
+
network_info = f"VPC ({len(vpc_subnets)} subnets, {len(vpc_security_groups)} security groups)"
|
|
516
|
+
|
|
415
517
|
execution_role_display = "Auto-create" if not result.execution_role else result.execution_role
|
|
416
|
-
|
|
417
|
-
|
|
518
|
+
saved_config = load_config(result.config_path)
|
|
519
|
+
saved_agent = saved_config.get_agent_config(agent_name)
|
|
520
|
+
|
|
521
|
+
# Display memory status based on actual configuration
|
|
522
|
+
if saved_agent.memory.mode == "NO_MEMORY":
|
|
418
523
|
memory_info = "Disabled"
|
|
524
|
+
elif saved_agent.memory.mode == "STM_AND_LTM":
|
|
525
|
+
memory_info = "Short-term + Long-term memory (30-day retention)"
|
|
526
|
+
else: # STM_ONLY
|
|
527
|
+
memory_info = "Short-term memory (30-day retention)"
|
|
528
|
+
|
|
529
|
+
lifecycle_info = ""
|
|
530
|
+
if idle_timeout or max_lifetime:
|
|
531
|
+
lifecycle_info = "\n[bold]Lifecycle Settings:[/bold]\n"
|
|
532
|
+
if idle_timeout:
|
|
533
|
+
lifecycle_info += f"Idle Timeout: [cyan]{idle_timeout}s ({idle_timeout // 60} minutes)[/cyan]\n"
|
|
534
|
+
if max_lifetime:
|
|
535
|
+
lifecycle_info += f"Max Lifetime: [cyan]{max_lifetime}s ({max_lifetime // 3600} hours)[/cyan]\n"
|
|
419
536
|
|
|
420
537
|
console.print(
|
|
421
538
|
Panel(
|
|
@@ -429,9 +546,11 @@ def configure(
|
|
|
429
546
|
f"ECR Repository: [cyan]"
|
|
430
547
|
f"{'Auto-create' if result.auto_create_ecr else result.ecr_repository or 'N/A'}"
|
|
431
548
|
f"[/cyan]\n"
|
|
549
|
+
f"Network Mode: [cyan]{network_info}[/cyan]\n"
|
|
432
550
|
f"Authorization: [cyan]{auth_info}[/cyan]\n\n"
|
|
433
551
|
f"{headers_info}\n"
|
|
434
552
|
f"Memory: [cyan]{memory_info}[/cyan]\n\n"
|
|
553
|
+
f"{lifecycle_info}\n"
|
|
435
554
|
f"📄 Config saved to: [dim]{result.config_path}[/dim]\n\n"
|
|
436
555
|
f"[bold]Next Steps:[/bold]\n"
|
|
437
556
|
f" [cyan]agentcore launch[/cyan]",
|
|
@@ -568,6 +687,7 @@ def launch(
|
|
|
568
687
|
use_codebuild=not local_build,
|
|
569
688
|
env_vars=env_vars,
|
|
570
689
|
auto_update_on_conflict=auto_update_on_conflict,
|
|
690
|
+
console=console,
|
|
571
691
|
)
|
|
572
692
|
|
|
573
693
|
project_config = load_config(config_path)
|
|
@@ -983,11 +1103,6 @@ def status(
|
|
|
983
1103
|
|
|
984
1104
|
# Determine overall status
|
|
985
1105
|
endpoint_status = endpoint_data.get("status", "Unknown") if endpoint_data else "Not Ready"
|
|
986
|
-
# memory_info = ""
|
|
987
|
-
# if hasattr(status_json["config"], "memory_id") and status_json["config"].get("memory_id"):
|
|
988
|
-
# memory_type = status_json["config"].get("memory_type", "Short-term")
|
|
989
|
-
# memory_id = status_json["config"].get("memory_id")
|
|
990
|
-
# memory_info = f"Memory: [cyan]{memory_type}[/cyan] ([dim]{memory_id}[/dim])\n"
|
|
991
1106
|
if endpoint_status == "READY":
|
|
992
1107
|
status_text = "Ready - Agent deployed and endpoint available"
|
|
993
1108
|
else:
|
|
@@ -1005,6 +1120,26 @@ def status(
|
|
|
1005
1120
|
f"Account: [dim]{status_json['config'].get('account', 'Not available')}[/dim]\n\n"
|
|
1006
1121
|
)
|
|
1007
1122
|
|
|
1123
|
+
# Add network information
|
|
1124
|
+
network_mode = status_json.get("agent", {}).get("networkConfiguration", {}).get("networkMode")
|
|
1125
|
+
if network_mode == "VPC":
|
|
1126
|
+
# Get VPC info from agent response (not config)
|
|
1127
|
+
network_config = (
|
|
1128
|
+
status_json.get("agent", {}).get("networkConfiguration", {}).get("networkModeConfig", {})
|
|
1129
|
+
)
|
|
1130
|
+
vpc_subnets = network_config.get("subnets", [])
|
|
1131
|
+
vpc_security_groups = network_config.get("securityGroups", [])
|
|
1132
|
+
subnet_count = len(vpc_subnets)
|
|
1133
|
+
sg_count = len(vpc_security_groups)
|
|
1134
|
+
vpc_id = status_json.get("config", {}).get("network_vpc_id", "unknown")
|
|
1135
|
+
if vpc_id:
|
|
1136
|
+
panel_content += f"Network: [cyan]VPC[/cyan] ([dim]{vpc_id}[/dim])\n"
|
|
1137
|
+
panel_content += f" {subnet_count} subnets, {sg_count} security groups\n\n"
|
|
1138
|
+
else:
|
|
1139
|
+
panel_content += "Network: [cyan]VPC[/cyan]\n\n"
|
|
1140
|
+
else:
|
|
1141
|
+
panel_content += "Network: [cyan]Public[/cyan]\n\n"
|
|
1142
|
+
|
|
1008
1143
|
# Add memory status with proper provisioning indication
|
|
1009
1144
|
if "memory_id" in status_json.get("config", {}) and status_json["config"]["memory_id"]:
|
|
1010
1145
|
memory_type = status_json["config"].get("memory_type", "Unknown")
|
|
@@ -1034,6 +1169,19 @@ def status(
|
|
|
1034
1169
|
f"[/dim]\n\n"
|
|
1035
1170
|
)
|
|
1036
1171
|
|
|
1172
|
+
if status_json["config"].get("idle_timeout") or status_json["config"].get("max_lifetime"):
|
|
1173
|
+
panel_content += "[bold]Lifecycle Settings:[/bold]\n"
|
|
1174
|
+
|
|
1175
|
+
idle = status_json["config"].get("idle_timeout")
|
|
1176
|
+
if idle:
|
|
1177
|
+
panel_content += f"Idle Timeout: [cyan]{idle}s ({idle // 60} minutes)[/cyan]\n"
|
|
1178
|
+
|
|
1179
|
+
max_life = status_json["config"].get("max_lifetime")
|
|
1180
|
+
if max_life:
|
|
1181
|
+
panel_content += f"Max Lifetime: [cyan]{max_life}s ({max_life // 3600} hours)[/cyan]\n"
|
|
1182
|
+
|
|
1183
|
+
panel_content += "\n"
|
|
1184
|
+
|
|
1037
1185
|
# Add CloudWatch logs information
|
|
1038
1186
|
agent_id = status_json.get("config", {}).get("agent_id")
|
|
1039
1187
|
if agent_id:
|
|
@@ -1128,6 +1276,109 @@ def status(
|
|
|
1128
1276
|
raise typer.Exit(1) from e
|
|
1129
1277
|
|
|
1130
1278
|
|
|
1279
|
+
def stop_session(
|
|
1280
|
+
session_id: Optional[str] = typer.Option(
|
|
1281
|
+
None,
|
|
1282
|
+
"--session-id",
|
|
1283
|
+
"-s",
|
|
1284
|
+
help="Runtime session ID to stop. If not provided, stops the last active session from invoke.",
|
|
1285
|
+
),
|
|
1286
|
+
agent: Optional[str] = typer.Option(
|
|
1287
|
+
None,
|
|
1288
|
+
"--agent",
|
|
1289
|
+
"-a",
|
|
1290
|
+
help="Agent name (use 'agentcore configure list' to see available agents)",
|
|
1291
|
+
),
|
|
1292
|
+
):
|
|
1293
|
+
"""Stop an active runtime session.
|
|
1294
|
+
|
|
1295
|
+
Terminates the compute session for the running agent. This frees up resources
|
|
1296
|
+
and ends any ongoing agent processing for that session.
|
|
1297
|
+
|
|
1298
|
+
🔍 How to find session IDs:
|
|
1299
|
+
• Last invoked session is automatically tracked (no flag needed)
|
|
1300
|
+
• Check 'agentcore status' to see the tracked session ID
|
|
1301
|
+
• Check CloudWatch logs for session IDs from previous invokes
|
|
1302
|
+
• Session IDs are also visible in the config file: .bedrock_agentcore.yaml
|
|
1303
|
+
|
|
1304
|
+
⏱️ Session Lifecycle:
|
|
1305
|
+
• Runtime sessions are created when you invoke an agent
|
|
1306
|
+
• They automatically expire after the configured idle timeout
|
|
1307
|
+
• Stopping a session immediately frees resources without waiting for timeout
|
|
1308
|
+
|
|
1309
|
+
Examples:
|
|
1310
|
+
# Stop the last invoked session (most common)
|
|
1311
|
+
agentcore stop-session
|
|
1312
|
+
|
|
1313
|
+
# Stop a specific session by ID
|
|
1314
|
+
agentcore stop-session --session-id abc123xyz
|
|
1315
|
+
|
|
1316
|
+
# Stop last session for a specific agent
|
|
1317
|
+
agentcore stop-session --agent my-agent
|
|
1318
|
+
|
|
1319
|
+
# Get current session ID before stopping
|
|
1320
|
+
agentcore status # Shows tracked session ID
|
|
1321
|
+
agentcore stop-session
|
|
1322
|
+
"""
|
|
1323
|
+
config_path = Path.cwd() / ".bedrock_agentcore.yaml"
|
|
1324
|
+
|
|
1325
|
+
try:
|
|
1326
|
+
from ...operations.runtime import stop_runtime_session
|
|
1327
|
+
|
|
1328
|
+
result = stop_runtime_session(
|
|
1329
|
+
config_path=config_path,
|
|
1330
|
+
session_id=session_id,
|
|
1331
|
+
agent_name=agent,
|
|
1332
|
+
)
|
|
1333
|
+
|
|
1334
|
+
# Show result panel
|
|
1335
|
+
status_icon = "✅" if result.status_code == 200 else "⚠️"
|
|
1336
|
+
status_color = "green" if result.status_code == 200 else "yellow"
|
|
1337
|
+
|
|
1338
|
+
console.print(
|
|
1339
|
+
Panel(
|
|
1340
|
+
f"[{status_color}]{status_icon} {result.message}[/{status_color}]\n\n"
|
|
1341
|
+
f"[bold]Session Details:[/bold]\n"
|
|
1342
|
+
f"Session ID: [cyan]{result.session_id}[/cyan]\n"
|
|
1343
|
+
f"Agent: [cyan]{result.agent_name}[/cyan]\n"
|
|
1344
|
+
f"Status Code: [cyan]{result.status_code}[/cyan]\n\n"
|
|
1345
|
+
f"[dim]💡 Runtime sessions automatically expire after idle timeout.\n"
|
|
1346
|
+
f" Manually stopping frees resources immediately.[/dim]",
|
|
1347
|
+
title="Session Stopped",
|
|
1348
|
+
border_style="bright_blue",
|
|
1349
|
+
)
|
|
1350
|
+
)
|
|
1351
|
+
|
|
1352
|
+
except FileNotFoundError:
|
|
1353
|
+
_show_configuration_not_found_panel()
|
|
1354
|
+
raise typer.Exit(1) from None
|
|
1355
|
+
except ValueError as e:
|
|
1356
|
+
console.print(
|
|
1357
|
+
Panel(
|
|
1358
|
+
f"[red]❌ Failed to Stop Session[/red]\n\n"
|
|
1359
|
+
f"Error: {str(e)}\n\n"
|
|
1360
|
+
f"[bold]How to find session IDs:[/bold]\n"
|
|
1361
|
+
f" • Check 'agentcore status' for the tracked session ID\n"
|
|
1362
|
+
f" • Check CloudWatch logs for session IDs\n"
|
|
1363
|
+
f" • Invoke the agent first to create a session\n\n"
|
|
1364
|
+
f"[dim]Note: Runtime sessions cannot be listed. You can only stop\n"
|
|
1365
|
+
f"the session from your last invoke or a specific session ID.[/dim]",
|
|
1366
|
+
title="Stop Session Error",
|
|
1367
|
+
border_style="red",
|
|
1368
|
+
)
|
|
1369
|
+
)
|
|
1370
|
+
raise typer.Exit(1) from e
|
|
1371
|
+
except Exception as e:
|
|
1372
|
+
console.print(
|
|
1373
|
+
Panel(
|
|
1374
|
+
f"[red]❌ Unexpected Error[/red]\n\n{str(e)}",
|
|
1375
|
+
title="Stop Session Error",
|
|
1376
|
+
border_style="red",
|
|
1377
|
+
)
|
|
1378
|
+
)
|
|
1379
|
+
raise typer.Exit(1) from e
|
|
1380
|
+
|
|
1381
|
+
|
|
1131
1382
|
def destroy(
|
|
1132
1383
|
agent: Optional[str] = typer.Option(
|
|
1133
1384
|
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")
|