bedrock-agentcore-starter-toolkit 0.0.1__py3-none-any.whl → 0.1.1__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/__init__.py +5 -0
- bedrock_agentcore_starter_toolkit/cli/cli.py +32 -0
- bedrock_agentcore_starter_toolkit/cli/common.py +44 -0
- bedrock_agentcore_starter_toolkit/cli/gateway/__init__.py +1 -0
- bedrock_agentcore_starter_toolkit/cli/gateway/commands.py +88 -0
- bedrock_agentcore_starter_toolkit/cli/runtime/__init__.py +1 -0
- bedrock_agentcore_starter_toolkit/cli/runtime/commands.py +651 -0
- bedrock_agentcore_starter_toolkit/cli/runtime/configuration_manager.py +133 -0
- bedrock_agentcore_starter_toolkit/notebook/__init__.py +5 -0
- bedrock_agentcore_starter_toolkit/notebook/runtime/__init__.py +1 -0
- bedrock_agentcore_starter_toolkit/notebook/runtime/bedrock_agentcore.py +239 -0
- bedrock_agentcore_starter_toolkit/operations/__init__.py +1 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/README.md +277 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/__init__.py +6 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/client.py +456 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/constants.py +152 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/create_lambda.py +85 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/create_role.py +90 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/exceptions.py +13 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/__init__.py +26 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/configure.py +241 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/create_role.py +404 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/invoke.py +129 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/launch.py +439 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/models.py +79 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/status.py +66 -0
- bedrock_agentcore_starter_toolkit/services/codebuild.py +332 -0
- bedrock_agentcore_starter_toolkit/services/ecr.py +84 -0
- bedrock_agentcore_starter_toolkit/services/runtime.py +473 -0
- bedrock_agentcore_starter_toolkit/utils/endpoints.py +32 -0
- bedrock_agentcore_starter_toolkit/utils/logging_config.py +72 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/config.py +129 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/container.py +310 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/entrypoint.py +197 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/logs.py +33 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/policy_template.py +74 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/schema.py +151 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/templates/Dockerfile.j2 +44 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/templates/dockerignore.template +68 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/templates/execution_role_policy.json.j2 +98 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/templates/execution_role_trust_policy.json.j2 +21 -0
- bedrock_agentcore_starter_toolkit-0.1.1.dist-info/METADATA +137 -0
- bedrock_agentcore_starter_toolkit-0.1.1.dist-info/RECORD +47 -0
- bedrock_agentcore_starter_toolkit-0.1.1.dist-info/entry_points.txt +2 -0
- bedrock_agentcore_starter_toolkit-0.1.1.dist-info/licenses/NOTICE.txt +190 -0
- bedrock_agentcore_starter_toolkit/init.py +0 -3
- bedrock_agentcore_starter_toolkit-0.0.1.dist-info/METADATA +0 -26
- bedrock_agentcore_starter_toolkit-0.0.1.dist-info/RECORD +0 -5
- {bedrock_agentcore_starter_toolkit-0.0.1.dist-info → bedrock_agentcore_starter_toolkit-0.1.1.dist-info}/WHEEL +0 -0
- /bedrock_agentcore_starter_toolkit-0.0.1.dist-info/licenses/LICENSE → /bedrock_agentcore_starter_toolkit-0.1.1.dist-info/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
"""Bedrock AgentCore CLI - Command line interface for Bedrock AgentCore."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import List, Optional
|
|
8
|
+
|
|
9
|
+
import typer
|
|
10
|
+
from prompt_toolkit import prompt
|
|
11
|
+
from prompt_toolkit.completion import PathCompleter
|
|
12
|
+
from rich.panel import Panel
|
|
13
|
+
from rich.syntax import Syntax
|
|
14
|
+
|
|
15
|
+
from ...operations.runtime import (
|
|
16
|
+
configure_bedrock_agentcore,
|
|
17
|
+
get_status,
|
|
18
|
+
invoke_bedrock_agentcore,
|
|
19
|
+
launch_bedrock_agentcore,
|
|
20
|
+
validate_agent_name,
|
|
21
|
+
)
|
|
22
|
+
from ...utils.runtime.entrypoint import parse_entrypoint
|
|
23
|
+
from ..common import _handle_error, _print_success, console
|
|
24
|
+
from .configuration_manager import ConfigurationManager
|
|
25
|
+
|
|
26
|
+
# Create a module-specific logger
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _validate_requirements_file(file_path: str) -> str:
|
|
31
|
+
"""Validate requirements file and return the path."""
|
|
32
|
+
from ...utils.runtime.entrypoint import validate_requirements_file
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
deps = validate_requirements_file(Path.cwd(), file_path)
|
|
36
|
+
_print_success(f"Using requirements file: [dim]{deps.resolved_path}[/dim]")
|
|
37
|
+
return file_path
|
|
38
|
+
except (FileNotFoundError, ValueError) as e:
|
|
39
|
+
_handle_error(str(e), e)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _prompt_for_requirements_file(prompt_text: str, default: str = "") -> Optional[str]:
|
|
43
|
+
"""Prompt user for requirements file path with validation."""
|
|
44
|
+
response = prompt(prompt_text, completer=PathCompleter(), default=default)
|
|
45
|
+
|
|
46
|
+
if response.strip():
|
|
47
|
+
return _validate_requirements_file(response.strip())
|
|
48
|
+
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _handle_requirements_file_display(requirements_file: Optional[str]) -> Optional[str]:
|
|
53
|
+
"""Handle requirements file with display logic for CLI."""
|
|
54
|
+
from ...utils.runtime.entrypoint import detect_dependencies
|
|
55
|
+
|
|
56
|
+
if requirements_file:
|
|
57
|
+
# User provided file - validate and show confirmation
|
|
58
|
+
return _validate_requirements_file(requirements_file)
|
|
59
|
+
|
|
60
|
+
# Auto-detection with interactive prompt
|
|
61
|
+
deps = detect_dependencies(Path.cwd())
|
|
62
|
+
|
|
63
|
+
if deps.found:
|
|
64
|
+
console.print(f"\n🔍 [cyan]Detected dependency file:[/cyan] [bold]{deps.file}[/bold]")
|
|
65
|
+
console.print("[dim]Press Enter to use this file, or type a different path (use Tab for autocomplete):[/dim]")
|
|
66
|
+
|
|
67
|
+
result = _prompt_for_requirements_file("Path or Press Enter to use detected dependency file: ", default="")
|
|
68
|
+
|
|
69
|
+
if result is None:
|
|
70
|
+
# Use detected file
|
|
71
|
+
_print_success(f"Using detected file: [dim]{deps.file}[/dim]")
|
|
72
|
+
|
|
73
|
+
return result
|
|
74
|
+
else:
|
|
75
|
+
console.print("\n[yellow]⚠️ No dependency file found (requirements.txt or pyproject.toml)[/yellow]")
|
|
76
|
+
console.print("[dim]Enter path to requirements file (use Tab for autocomplete), or press Enter to skip:[/dim]")
|
|
77
|
+
|
|
78
|
+
result = _prompt_for_requirements_file("Path: ")
|
|
79
|
+
|
|
80
|
+
if result is None:
|
|
81
|
+
_handle_error("No requirements file specified and none found automatically")
|
|
82
|
+
|
|
83
|
+
return result
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# Define options at module level to avoid B008
|
|
87
|
+
ENV_OPTION = typer.Option(None, "--env", "-env", help="Environment variables for local mode (format: KEY=VALUE)")
|
|
88
|
+
|
|
89
|
+
# Configure command group
|
|
90
|
+
configure_app = typer.Typer(name="configure", help="Configuration management")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@configure_app.command("list")
|
|
94
|
+
def list_agents():
|
|
95
|
+
"""List configured agents."""
|
|
96
|
+
config_path = Path.cwd() / ".bedrock_agentcore.yaml"
|
|
97
|
+
try:
|
|
98
|
+
from ...utils.runtime.config import load_config
|
|
99
|
+
|
|
100
|
+
project_config = load_config(config_path)
|
|
101
|
+
if not project_config.agents:
|
|
102
|
+
console.print("[yellow]No agents configured.[/yellow]")
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
console.print("[bold]Configured Agents:[/bold]")
|
|
106
|
+
for name, agent in project_config.agents.items():
|
|
107
|
+
default_marker = " (default)" if name == project_config.default_agent else ""
|
|
108
|
+
status_icon = "✅" if agent.bedrock_agentcore.agent_arn else "⚠️"
|
|
109
|
+
status_text = "Ready" if agent.bedrock_agentcore.agent_arn else "Config only"
|
|
110
|
+
|
|
111
|
+
console.print(f" {status_icon} [cyan]{name}[/cyan]{default_marker} - {status_text}")
|
|
112
|
+
console.print(f" Entrypoint: {agent.entrypoint}")
|
|
113
|
+
console.print(f" Region: {agent.aws.region}")
|
|
114
|
+
console.print()
|
|
115
|
+
except FileNotFoundError:
|
|
116
|
+
console.print("[red].bedrock_agentcore.yaml not found.[/red]")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@configure_app.command("set-default")
|
|
120
|
+
def set_default(name: str = typer.Argument(...)):
|
|
121
|
+
"""Set default agent."""
|
|
122
|
+
config_path = Path.cwd() / ".bedrock_agentcore.yaml"
|
|
123
|
+
try:
|
|
124
|
+
from ...utils.runtime.config import load_config, save_config
|
|
125
|
+
|
|
126
|
+
project_config = load_config(config_path)
|
|
127
|
+
if name not in project_config.agents:
|
|
128
|
+
available = list(project_config.agents.keys())
|
|
129
|
+
_handle_error(f"Agent '{name}' not found. Available: {available}")
|
|
130
|
+
|
|
131
|
+
project_config.default_agent = name
|
|
132
|
+
save_config(project_config, config_path)
|
|
133
|
+
_print_success(f"Set '{name}' as default")
|
|
134
|
+
except Exception as e:
|
|
135
|
+
_handle_error(f"Failed: {e}")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@configure_app.callback(invoke_without_command=True)
|
|
139
|
+
def configure(
|
|
140
|
+
ctx: typer.Context,
|
|
141
|
+
entrypoint: Optional[str] = typer.Option(None, "--entrypoint", "-e", help="Python file with BedrockAgentCoreApp"),
|
|
142
|
+
agent_name: Optional[str] = typer.Option(None, "--name", "-n"),
|
|
143
|
+
execution_role: Optional[str] = typer.Option(None, "--execution-role", "-er"),
|
|
144
|
+
ecr_repository: Optional[str] = typer.Option(None, "--ecr", "-ecr"),
|
|
145
|
+
container_runtime: Optional[str] = typer.Option(None, "--container-runtime", "-ctr"),
|
|
146
|
+
requirements_file: Optional[str] = typer.Option(
|
|
147
|
+
None, "--requirements-file", "-rf", help="Path to requirements file"
|
|
148
|
+
),
|
|
149
|
+
disable_otel: bool = typer.Option(False, "--disable-otel", "-do", help="Disable OpenTelemetry"),
|
|
150
|
+
authorizer_config: Optional[str] = typer.Option(
|
|
151
|
+
None, "--authorizer-config", "-ac", help="OAuth authorizer configuration as JSON string"
|
|
152
|
+
),
|
|
153
|
+
verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose output"),
|
|
154
|
+
region: Optional[str] = typer.Option(None, "--region", "-r"),
|
|
155
|
+
protocol: Optional[str] = typer.Option(None, "--protocol", "-p", help="Server protocol (HTTP or MCP)"),
|
|
156
|
+
):
|
|
157
|
+
"""Configure a Bedrock AgentCore agent. The agent name defaults to your Python file name."""
|
|
158
|
+
if ctx.invoked_subcommand is not None:
|
|
159
|
+
return
|
|
160
|
+
|
|
161
|
+
if not entrypoint:
|
|
162
|
+
_handle_error("--entrypoint is required")
|
|
163
|
+
|
|
164
|
+
if protocol and protocol.upper() not in ["HTTP", "MCP"]:
|
|
165
|
+
_handle_error("Error: --protocol must be either HTTP or MCP")
|
|
166
|
+
|
|
167
|
+
console.print("[cyan]Configuring Bedrock AgentCore...[/cyan]")
|
|
168
|
+
try:
|
|
169
|
+
_, file_name = parse_entrypoint(entrypoint)
|
|
170
|
+
agent_name = agent_name or file_name
|
|
171
|
+
|
|
172
|
+
valid, error = validate_agent_name(agent_name)
|
|
173
|
+
if not valid:
|
|
174
|
+
_handle_error(error)
|
|
175
|
+
|
|
176
|
+
console.print(f"[dim]Agent name: {agent_name}[/dim]")
|
|
177
|
+
except ValueError as e:
|
|
178
|
+
_handle_error(f"Error: {e}", e)
|
|
179
|
+
|
|
180
|
+
# Create configuration manager for clean, elegant prompting
|
|
181
|
+
config_path = Path.cwd() / ".bedrock_agentcore.yaml"
|
|
182
|
+
config_manager = ConfigurationManager(config_path)
|
|
183
|
+
|
|
184
|
+
# Interactive prompts for missing values - clean and elegant
|
|
185
|
+
if not execution_role:
|
|
186
|
+
execution_role = config_manager.prompt_execution_role()
|
|
187
|
+
|
|
188
|
+
# Handle ECR repository
|
|
189
|
+
auto_create_ecr = True
|
|
190
|
+
if ecr_repository and ecr_repository.lower() == "auto":
|
|
191
|
+
# User explicitly requested auto-creation
|
|
192
|
+
ecr_repository = None
|
|
193
|
+
auto_create_ecr = True
|
|
194
|
+
_print_success("Will auto-create ECR repository")
|
|
195
|
+
elif not ecr_repository:
|
|
196
|
+
ecr_repository, auto_create_ecr = config_manager.prompt_ecr_repository()
|
|
197
|
+
else:
|
|
198
|
+
# User provided a specific ECR repository
|
|
199
|
+
auto_create_ecr = False
|
|
200
|
+
_print_success(f"Using existing ECR repository: [dim]{ecr_repository}[/dim]")
|
|
201
|
+
|
|
202
|
+
# Handle dependency file selection with simplified logic
|
|
203
|
+
final_requirements_file = _handle_requirements_file_display(requirements_file)
|
|
204
|
+
|
|
205
|
+
# Handle OAuth authorization configuration
|
|
206
|
+
oauth_config = None
|
|
207
|
+
if authorizer_config:
|
|
208
|
+
# Parse provided JSON configuration
|
|
209
|
+
try:
|
|
210
|
+
oauth_config = json.loads(authorizer_config)
|
|
211
|
+
_print_success("Using provided OAuth authorizer configuration")
|
|
212
|
+
except json.JSONDecodeError as e:
|
|
213
|
+
_handle_error(f"Invalid JSON in --authorizer-config: {e}", e)
|
|
214
|
+
else:
|
|
215
|
+
oauth_config = config_manager.prompt_oauth_config()
|
|
216
|
+
|
|
217
|
+
try:
|
|
218
|
+
result = configure_bedrock_agentcore(
|
|
219
|
+
agent_name=agent_name,
|
|
220
|
+
entrypoint_path=Path(entrypoint),
|
|
221
|
+
execution_role=execution_role,
|
|
222
|
+
ecr_repository=ecr_repository,
|
|
223
|
+
container_runtime=container_runtime,
|
|
224
|
+
auto_create_ecr=auto_create_ecr,
|
|
225
|
+
enable_observability=not disable_otel,
|
|
226
|
+
requirements_file=final_requirements_file,
|
|
227
|
+
authorizer_configuration=oauth_config,
|
|
228
|
+
verbose=verbose,
|
|
229
|
+
region=region,
|
|
230
|
+
protocol=protocol.upper() if protocol else None,
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Prepare authorization info for summary
|
|
234
|
+
auth_info = "IAM (default)"
|
|
235
|
+
if oauth_config:
|
|
236
|
+
auth_info = "OAuth (customJWTAuthorizer)"
|
|
237
|
+
|
|
238
|
+
console.print(
|
|
239
|
+
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",
|
|
251
|
+
)
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
except ValueError as e:
|
|
255
|
+
# Handle validation errors from core layer
|
|
256
|
+
_handle_error(str(e), e)
|
|
257
|
+
except Exception as e:
|
|
258
|
+
_handle_error(f"Configuration failed: {e}", e)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def launch(
|
|
262
|
+
agent: Optional[str] = typer.Option(
|
|
263
|
+
None, "--agent", "-a", help="Agent name (use 'agentcore configure list' to see available agents)"
|
|
264
|
+
),
|
|
265
|
+
local: bool = typer.Option(False, "--local", "-l", help="Run locally"),
|
|
266
|
+
push_ecr: bool = typer.Option(False, "--push-ecr", "-p", help="Build and push to ECR only (no deployment)"),
|
|
267
|
+
codebuild: bool = typer.Option(False, "--codebuild", "-cb", help="Use CodeBuild for ARM64 builds"),
|
|
268
|
+
auto_update_on_conflict: bool = typer.Option(
|
|
269
|
+
False, "--auto-update-on-conflict", help="Enable automatic update when agent already exists"
|
|
270
|
+
),
|
|
271
|
+
envs: List[str] = typer.Option( # noqa: B008
|
|
272
|
+
None, "--env", "-env", help="Environment variables for agent (format: KEY=VALUE)"
|
|
273
|
+
),
|
|
274
|
+
):
|
|
275
|
+
"""Launch Bedrock AgentCore locally or to cloud."""
|
|
276
|
+
# Validate mutually exclusive options
|
|
277
|
+
if sum([local, push_ecr, codebuild]) > 1:
|
|
278
|
+
_handle_error("Error: --local, --push-ecr, and --codebuild cannot be used together")
|
|
279
|
+
|
|
280
|
+
config_path = Path.cwd() / ".bedrock_agentcore.yaml"
|
|
281
|
+
|
|
282
|
+
try:
|
|
283
|
+
# Show launch mode
|
|
284
|
+
if local:
|
|
285
|
+
mode = "local"
|
|
286
|
+
elif push_ecr:
|
|
287
|
+
mode = "push-ecr"
|
|
288
|
+
elif codebuild:
|
|
289
|
+
mode = "codebuild"
|
|
290
|
+
else:
|
|
291
|
+
mode = "cloud"
|
|
292
|
+
|
|
293
|
+
console.print(f"[cyan]Launching Bedrock AgentCore ({mode} mode)...[/cyan]\n")
|
|
294
|
+
|
|
295
|
+
# Use the operations module
|
|
296
|
+
with console.status("[bold]Launching Bedrock AgentCore...[/bold]"):
|
|
297
|
+
# Parse environment variables for local mode
|
|
298
|
+
env_vars = None
|
|
299
|
+
if envs:
|
|
300
|
+
env_vars = {}
|
|
301
|
+
for env_var in envs:
|
|
302
|
+
if "=" not in env_var:
|
|
303
|
+
_handle_error(f"Invalid environment variable format: {env_var}. Use KEY=VALUE format.")
|
|
304
|
+
key, value = env_var.split("=", 1)
|
|
305
|
+
env_vars[key] = value
|
|
306
|
+
|
|
307
|
+
# Call the operation
|
|
308
|
+
result = launch_bedrock_agentcore(
|
|
309
|
+
config_path=config_path,
|
|
310
|
+
agent_name=agent,
|
|
311
|
+
local=local,
|
|
312
|
+
push_ecr_only=push_ecr,
|
|
313
|
+
use_codebuild=codebuild,
|
|
314
|
+
env_vars=env_vars,
|
|
315
|
+
auto_update_on_conflict=auto_update_on_conflict,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
# Handle result based on mode
|
|
319
|
+
if result.mode == "local":
|
|
320
|
+
_print_success(f"Docker image built: {result.tag}")
|
|
321
|
+
_print_success("Ready to run locally")
|
|
322
|
+
console.print("Starting server at http://localhost:8080")
|
|
323
|
+
console.print("[yellow]Press Ctrl+C to stop[/yellow]\n")
|
|
324
|
+
|
|
325
|
+
if result.runtime is None or result.port is None:
|
|
326
|
+
_handle_error("Unable to launch locally")
|
|
327
|
+
|
|
328
|
+
try:
|
|
329
|
+
result.runtime.run_local(result.tag, result.port, result.env_vars)
|
|
330
|
+
except KeyboardInterrupt:
|
|
331
|
+
console.print("\n[yellow]Stopped[/yellow]")
|
|
332
|
+
|
|
333
|
+
elif result.mode == "push-ecr":
|
|
334
|
+
_print_success(f"Image pushed to ECR: [cyan]{result.ecr_uri}:latest[/cyan]")
|
|
335
|
+
console.print(
|
|
336
|
+
Panel(
|
|
337
|
+
f"[green]ECR Push Successful![/green]\n\n"
|
|
338
|
+
f"Image: [cyan]{result.tag}[/cyan]\n"
|
|
339
|
+
f"ECR URI: [cyan]{result.ecr_uri}:latest[/cyan]\n\n"
|
|
340
|
+
f"Your image is now available in ECR.\n"
|
|
341
|
+
f"Run [cyan]agentcore launch[/cyan] to deploy to Bedrock AgentCore.",
|
|
342
|
+
title="Push to ECR Complete",
|
|
343
|
+
border_style="green",
|
|
344
|
+
)
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
elif result.mode == "codebuild":
|
|
348
|
+
_print_success(f"CodeBuild completed: [cyan]{result.codebuild_id}[/cyan]")
|
|
349
|
+
_print_success(f"ARM64 image pushed to ECR: [cyan]{result.ecr_uri}:latest[/cyan]")
|
|
350
|
+
|
|
351
|
+
# Show deployment success panel
|
|
352
|
+
agent_name = result.tag.split(":")[0].replace("bedrock_agentcore-", "")
|
|
353
|
+
deploy_panel = (
|
|
354
|
+
f"[green]CodeBuild ARM64 Deployment Successful![/green]\n\n"
|
|
355
|
+
f"Agent Name: {agent_name}\n"
|
|
356
|
+
f"CodeBuild ID: [cyan]{result.codebuild_id}[/cyan]\n"
|
|
357
|
+
f"Agent ARN: [cyan]{result.agent_arn}[/cyan]\n"
|
|
358
|
+
f"ECR URI: [cyan]{result.ecr_uri}:latest[/cyan]\n\n"
|
|
359
|
+
f"ARM64 container deployed to Bedrock AgentCore.\n\n"
|
|
360
|
+
f"You can now check the status of your Bedrock AgentCore endpoint with:\n"
|
|
361
|
+
f"[cyan]agentcore status[/cyan]\n\n"
|
|
362
|
+
f"You can now invoke your Bedrock AgentCore endpoint with:\n"
|
|
363
|
+
f'[cyan]agentcore invoke \'{{"prompt": "Hello"}}\'[/cyan]'
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
# Add log information if we have agent_id
|
|
367
|
+
if result.agent_id:
|
|
368
|
+
from ...utils.runtime.logs import get_agent_log_paths, get_aws_tail_commands
|
|
369
|
+
|
|
370
|
+
runtime_logs, otel_logs = get_agent_log_paths(result.agent_id)
|
|
371
|
+
follow_cmd, since_cmd = get_aws_tail_commands(runtime_logs)
|
|
372
|
+
deploy_panel += (
|
|
373
|
+
f"\n\n📋 [cyan]Agent logs available at:[/cyan]\n"
|
|
374
|
+
f" {runtime_logs}\n"
|
|
375
|
+
f" {otel_logs}\n\n"
|
|
376
|
+
f"💡 [dim]Tail logs with:[/dim]\n"
|
|
377
|
+
f" {follow_cmd}\n"
|
|
378
|
+
f" {since_cmd}"
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
console.print(
|
|
382
|
+
Panel(
|
|
383
|
+
deploy_panel,
|
|
384
|
+
title="CodeBuild Deployment Complete",
|
|
385
|
+
border_style="green",
|
|
386
|
+
)
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
else: # cloud mode
|
|
390
|
+
_print_success(f"Image pushed to ECR: [cyan]{result.ecr_uri}:latest[/cyan]")
|
|
391
|
+
|
|
392
|
+
# Show deployment success panel
|
|
393
|
+
agent_name = result.tag.split(":")[0].replace("bedrock_agentcore-", "")
|
|
394
|
+
deploy_panel = (
|
|
395
|
+
f"[green]Deployment Successful![/green]\n\n"
|
|
396
|
+
f"Agent Name: {agent_name}\n"
|
|
397
|
+
f"Agent ARN: [cyan]{result.agent_arn}[/cyan]\n"
|
|
398
|
+
f"ECR URI: [cyan]{result.ecr_uri}[/cyan]\n\n"
|
|
399
|
+
f"You can now check the status of your Bedrock AgentCore endpoint with:\n"
|
|
400
|
+
f"[cyan]agentcore status[/cyan]\n\n"
|
|
401
|
+
f"You can now invoke your Bedrock AgentCore endpoint with:\n"
|
|
402
|
+
f'[cyan]agentcore invoke \'{{"prompt": "Hello"}}\'[/cyan]'
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
# Add log information if we have agent_id
|
|
406
|
+
if result.agent_id:
|
|
407
|
+
from ...utils.runtime.logs import get_agent_log_paths, get_aws_tail_commands
|
|
408
|
+
|
|
409
|
+
runtime_logs, otel_logs = get_agent_log_paths(result.agent_id)
|
|
410
|
+
follow_cmd, since_cmd = get_aws_tail_commands(runtime_logs)
|
|
411
|
+
deploy_panel += (
|
|
412
|
+
f"\n\n📋 [cyan]Agent logs available at:[/cyan]\n"
|
|
413
|
+
f" {runtime_logs}\n"
|
|
414
|
+
f" {otel_logs}\n\n"
|
|
415
|
+
f"💡 [dim]Tail logs with:[/dim]\n"
|
|
416
|
+
f" {follow_cmd}\n"
|
|
417
|
+
f" {since_cmd}"
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
console.print(
|
|
421
|
+
Panel(
|
|
422
|
+
deploy_panel,
|
|
423
|
+
title="Bedrock AgentCore Deployed",
|
|
424
|
+
border_style="green",
|
|
425
|
+
)
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
except FileNotFoundError:
|
|
429
|
+
_handle_error(".bedrock_agentcore.yaml not found. Run 'agentcore configure --entrypoint <file>' first")
|
|
430
|
+
except ValueError as e:
|
|
431
|
+
_handle_error(str(e), e)
|
|
432
|
+
except RuntimeError as e:
|
|
433
|
+
_handle_error(str(e), e)
|
|
434
|
+
except Exception as e:
|
|
435
|
+
if not isinstance(e, typer.Exit):
|
|
436
|
+
_handle_error(f"Launch failed: {e}", e)
|
|
437
|
+
raise
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def invoke(
|
|
441
|
+
payload: str = typer.Argument(..., help="JSON payload to send"),
|
|
442
|
+
agent: Optional[str] = typer.Option(
|
|
443
|
+
None, "--agent", "-a", help="Agent name (use 'bedrock_agentcore configure list' to see available)"
|
|
444
|
+
),
|
|
445
|
+
session_id: Optional[str] = typer.Option(None, "--session-id", "-s"),
|
|
446
|
+
bearer_token: Optional[str] = typer.Option(
|
|
447
|
+
None, "--bearer-token", "-bt", help="Bearer token for OAuth authentication"
|
|
448
|
+
),
|
|
449
|
+
local_mode: Optional[bool] = typer.Option(False, "--local", "-l", help="Send request to a running local container"),
|
|
450
|
+
user_id: Optional[str] = typer.Option(None, "--user-id", "-u", help="User id for authorization flows"),
|
|
451
|
+
):
|
|
452
|
+
"""Invoke Bedrock AgentCore endpoint."""
|
|
453
|
+
config_path = Path.cwd() / ".bedrock_agentcore.yaml"
|
|
454
|
+
|
|
455
|
+
try:
|
|
456
|
+
from ...utils.runtime.config import load_config
|
|
457
|
+
|
|
458
|
+
# Load project configuration to check if auth is configured
|
|
459
|
+
project_config = load_config(config_path)
|
|
460
|
+
config = project_config.get_agent_config(agent)
|
|
461
|
+
|
|
462
|
+
# Parse payload
|
|
463
|
+
try:
|
|
464
|
+
payload_data = json.loads(payload)
|
|
465
|
+
except json.JSONDecodeError:
|
|
466
|
+
payload_data = {"message": payload}
|
|
467
|
+
|
|
468
|
+
# Handle bearer token - only use if auth config is defined in .bedrock_agentcore.yaml
|
|
469
|
+
final_bearer_token = None
|
|
470
|
+
if config.authorizer_configuration is not None:
|
|
471
|
+
# Auth is configured, check for bearer token
|
|
472
|
+
final_bearer_token = bearer_token
|
|
473
|
+
if not final_bearer_token:
|
|
474
|
+
final_bearer_token = os.getenv("BEDROCK_AGENTCORE_BEARER_TOKEN")
|
|
475
|
+
|
|
476
|
+
if final_bearer_token:
|
|
477
|
+
console.print("[dim]Using bearer token for OAuth authentication[/dim]")
|
|
478
|
+
else:
|
|
479
|
+
console.print("[yellow]Warning: OAuth is configured but no bearer token provided[/yellow]")
|
|
480
|
+
elif bearer_token or os.getenv("BEDROCK_AGENTCORE_BEARER_TOKEN"):
|
|
481
|
+
console.print(
|
|
482
|
+
"[yellow]Warning: Bearer token provided but OAuth is not configured in .bedrock_agentcore.yaml[/yellow]"
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
# Display payload
|
|
486
|
+
console.print("[bold]Payload:[/bold]")
|
|
487
|
+
console.print(Syntax(json.dumps(payload_data, indent=2), "json", background_color="default", word_wrap=True))
|
|
488
|
+
|
|
489
|
+
# Invoke
|
|
490
|
+
result = invoke_bedrock_agentcore(
|
|
491
|
+
config_path=config_path,
|
|
492
|
+
payload=payload_data,
|
|
493
|
+
agent_name=agent,
|
|
494
|
+
session_id=session_id,
|
|
495
|
+
bearer_token=final_bearer_token,
|
|
496
|
+
user_id=user_id,
|
|
497
|
+
local_mode=local_mode,
|
|
498
|
+
)
|
|
499
|
+
console.print(f"Session ID: [cyan]{result.session_id}[/cyan]")
|
|
500
|
+
console.print("\n[bold]Response:[/bold]")
|
|
501
|
+
console.print(
|
|
502
|
+
Syntax(
|
|
503
|
+
json.dumps(result.response, indent=2, default=str), "json", background_color="default", word_wrap=True
|
|
504
|
+
)
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
except FileNotFoundError:
|
|
508
|
+
_handle_error(".bedrock_agentcore.yaml not found. Run 'bedrock_agentcore configure --entrypoint <file>' first")
|
|
509
|
+
except ValueError as e:
|
|
510
|
+
if "not deployed" in str(e):
|
|
511
|
+
_handle_error("Bedrock AgentCore not deployed. Run 'bedrock_agentcore launch' first", e)
|
|
512
|
+
else:
|
|
513
|
+
_handle_error(f"Invocation failed: {e}", e)
|
|
514
|
+
except Exception as e:
|
|
515
|
+
_handle_error(f"Invocation failed: {e}", e)
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def status(
|
|
519
|
+
agent: Optional[str] = typer.Option(
|
|
520
|
+
None, "--agent", "-a", help="Agent name (use 'bedrock_agentcore configure list' to see available)"
|
|
521
|
+
),
|
|
522
|
+
verbose: Optional[bool] = typer.Option(
|
|
523
|
+
None, "--verbose", "-v", help="Verbose json output of config, agent and endpoint status"
|
|
524
|
+
),
|
|
525
|
+
):
|
|
526
|
+
"""Get Bedrock AgentCore status including config and runtime details."""
|
|
527
|
+
config_path = Path.cwd() / ".bedrock_agentcore.yaml"
|
|
528
|
+
|
|
529
|
+
# Get status
|
|
530
|
+
result = get_status(config_path, agent)
|
|
531
|
+
|
|
532
|
+
# Output JSON
|
|
533
|
+
status_json = result.model_dump()
|
|
534
|
+
|
|
535
|
+
try:
|
|
536
|
+
if not verbose:
|
|
537
|
+
if "config" in status_json:
|
|
538
|
+
if status_json["agent"] is None:
|
|
539
|
+
console.print(
|
|
540
|
+
Panel(
|
|
541
|
+
f"[green]Status of the current Agent:[/green]\n\n"
|
|
542
|
+
f"[green]Agent Name: {status_json['config']['name']}[/green]\n"
|
|
543
|
+
f"[cyan]Configuration details:[/cyan]\n"
|
|
544
|
+
f"[cyan]- region: {status_json['config']['region']}[/cyan]\n"
|
|
545
|
+
f"[cyan]- account: {status_json['config']['account']}[/cyan]\n"
|
|
546
|
+
f"[cyan]- execution role: {status_json['config']['execution_role']}[/cyan]\n"
|
|
547
|
+
f"[cyan]- ecr repository: {status_json['config']['ecr_repository']}[/cyan]\n",
|
|
548
|
+
title="Bedrock AgentCore Agent Status",
|
|
549
|
+
border_style="green",
|
|
550
|
+
)
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
console.print(
|
|
554
|
+
Panel(
|
|
555
|
+
"[yellow]Agent is configured, but not launched yet. "
|
|
556
|
+
"Please use `agentcore launch` to launch the agent. [/yellow]\n\n",
|
|
557
|
+
title="Bedrock AgentCore Agent Status",
|
|
558
|
+
border_style="yellow",
|
|
559
|
+
)
|
|
560
|
+
)
|
|
561
|
+
|
|
562
|
+
elif "agent" in status_json and status_json["agent"] is not None:
|
|
563
|
+
agent_data = status_json["agent"]
|
|
564
|
+
console.print(
|
|
565
|
+
Panel(
|
|
566
|
+
f"[green]Status of the current Agent:[/green]\n\n"
|
|
567
|
+
f"[green]Agent Name: {status_json['config']['name']}[/green]\n"
|
|
568
|
+
f"[green]Agent ID: {status_json['config']['agent_id']}[/green]\n"
|
|
569
|
+
f"[green]Agent Arn: {status_json['config']['agent_arn']}[/green]\n"
|
|
570
|
+
f"[green]Created at: {agent_data.get('createdAt', 'Not available')}[/green]\n"
|
|
571
|
+
f"[green]Last Updated at: {agent_data.get('lastUpdatedAt', 'Not available')}[/green]\n"
|
|
572
|
+
f"[cyan]Configuration details:[/cyan]\n"
|
|
573
|
+
f"[cyan]- region: {status_json['config']['region']}[/cyan]\n"
|
|
574
|
+
f"[cyan]- account: {status_json['config'].get('account', 'Not available')}[/cyan]\n"
|
|
575
|
+
f"[cyan]- execution role: "
|
|
576
|
+
f"{status_json['config'].get('execution_role', 'Not available')}[/cyan]\n"
|
|
577
|
+
f"[cyan]- ecr repository: "
|
|
578
|
+
f"{status_json['config'].get('ecr_repository', 'Not available')}[/cyan]\n",
|
|
579
|
+
title="Bedrock AgentCore Agent Status",
|
|
580
|
+
border_style="green",
|
|
581
|
+
)
|
|
582
|
+
)
|
|
583
|
+
else:
|
|
584
|
+
console.print(
|
|
585
|
+
Panel(
|
|
586
|
+
"[green]Please launch agent first![/green]\n\n",
|
|
587
|
+
title="Bedrock AgentCore Agent Status",
|
|
588
|
+
border_style="yellow",
|
|
589
|
+
)
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
if "endpoint" in status_json and status_json["endpoint"] is not None:
|
|
593
|
+
endpoint_data = status_json["endpoint"]
|
|
594
|
+
console.print(
|
|
595
|
+
Panel(
|
|
596
|
+
f"[green]Status of the current Endpoint:[/green]\n\n"
|
|
597
|
+
f"[green]Endpoint Id: {endpoint_data.get('id', 'Not available')}[/green]\n"
|
|
598
|
+
f"[green]Endpoint Name: {endpoint_data.get('name', 'Not available')}[/green]\n"
|
|
599
|
+
f"[green]Endpoint Arn: "
|
|
600
|
+
f"{endpoint_data.get('agentRuntimeEndpointArn', 'Not available')}[/green]\n"
|
|
601
|
+
f"[green]Agent Arn: {endpoint_data.get('agentRuntimeArn', 'Not available')}[/green]\n"
|
|
602
|
+
f"[green]STATUS: [cyan]{endpoint_data.get('status', 'Unknown')}[/cyan][/green]\n"
|
|
603
|
+
f"[green]Last Updated at: "
|
|
604
|
+
f"{endpoint_data.get('lastUpdatedAt', 'Not available')}[/green]\n",
|
|
605
|
+
title="Bedrock AgentCore Endpoint Status",
|
|
606
|
+
border_style="green",
|
|
607
|
+
)
|
|
608
|
+
)
|
|
609
|
+
else:
|
|
610
|
+
console.print(
|
|
611
|
+
Panel(
|
|
612
|
+
"[yellow]Please launch agent first and make sure endpoint status is READY "
|
|
613
|
+
"before invoking![/yellow]\n\n",
|
|
614
|
+
title="Bedrock AgentCore Endpoint Status",
|
|
615
|
+
border_style="yellow",
|
|
616
|
+
)
|
|
617
|
+
)
|
|
618
|
+
|
|
619
|
+
# Show log information
|
|
620
|
+
agent_id = status_json.get("config", {}).get("agent_id")
|
|
621
|
+
if agent_id:
|
|
622
|
+
try:
|
|
623
|
+
from ...utils.runtime.logs import get_agent_log_paths, get_aws_tail_commands
|
|
624
|
+
|
|
625
|
+
endpoint_name = status_json.get("endpoint", {}).get("name")
|
|
626
|
+
|
|
627
|
+
runtime_logs, otel_logs = get_agent_log_paths(agent_id, endpoint_name)
|
|
628
|
+
follow_cmd, since_cmd = get_aws_tail_commands(runtime_logs)
|
|
629
|
+
|
|
630
|
+
console.print("\n📋 [cyan]Agent logs available at:[/cyan]")
|
|
631
|
+
console.print(f" {runtime_logs}")
|
|
632
|
+
console.print(f" {otel_logs}")
|
|
633
|
+
console.print("\n💡 [dim]Tail logs with:[/dim]")
|
|
634
|
+
console.print(f" {follow_cmd}")
|
|
635
|
+
console.print(f" {since_cmd}")
|
|
636
|
+
except (ValueError, TypeError) as e:
|
|
637
|
+
# If logging info fails, log the error and continue
|
|
638
|
+
logger.debug("Failed to display log paths: %s", str(e))
|
|
639
|
+
else: # full json verbose output
|
|
640
|
+
console.print(
|
|
641
|
+
Syntax(
|
|
642
|
+
json.dumps(status_json, indent=2, default=str), "json", background_color="default", word_wrap=True
|
|
643
|
+
)
|
|
644
|
+
)
|
|
645
|
+
|
|
646
|
+
except FileNotFoundError:
|
|
647
|
+
_handle_error(".bedrock_agentcore.yaml not found. Run 'bedrock_agentcore configure --entrypoint <file>' first")
|
|
648
|
+
except ValueError as e:
|
|
649
|
+
_handle_error(f"Status failed: {e}", e)
|
|
650
|
+
except Exception as e:
|
|
651
|
+
_handle_error(f"Status failed: {e}", e)
|