bedrock-agentcore-starter-toolkit 0.1.21__py3-none-any.whl → 0.1.22__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.
- bedrock_agentcore_starter_toolkit/cli/runtime/commands.py +23 -6
- bedrock_agentcore_starter_toolkit/cli/runtime/configuration_manager.py +0 -1
- bedrock_agentcore_starter_toolkit/notebook/runtime/bedrock_agentcore.py +3 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/configure.py +37 -7
- bedrock_agentcore_starter_toolkit/operations/runtime/destroy.py +2 -1
- bedrock_agentcore_starter_toolkit/operations/runtime/exceptions.py +27 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/launch.py +81 -41
- bedrock_agentcore_starter_toolkit/services/codebuild.py +51 -25
- bedrock_agentcore_starter_toolkit/utils/runtime/config.py +43 -1
- bedrock_agentcore_starter_toolkit/utils/runtime/container.py +83 -27
- bedrock_agentcore_starter_toolkit/utils/runtime/schema.py +69 -1
- bedrock_agentcore_starter_toolkit/utils/runtime/templates/Dockerfile.j2 +1 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/templates/dockerignore.template +1 -0
- {bedrock_agentcore_starter_toolkit-0.1.21.dist-info → bedrock_agentcore_starter_toolkit-0.1.22.dist-info}/METADATA +2 -2
- {bedrock_agentcore_starter_toolkit-0.1.21.dist-info → bedrock_agentcore_starter_toolkit-0.1.22.dist-info}/RECORD +19 -18
- {bedrock_agentcore_starter_toolkit-0.1.21.dist-info → bedrock_agentcore_starter_toolkit-0.1.22.dist-info}/WHEEL +0 -0
- {bedrock_agentcore_starter_toolkit-0.1.21.dist-info → bedrock_agentcore_starter_toolkit-0.1.22.dist-info}/entry_points.txt +0 -0
- {bedrock_agentcore_starter_toolkit-0.1.21.dist-info → bedrock_agentcore_starter_toolkit-0.1.22.dist-info}/licenses/LICENSE.txt +0 -0
- {bedrock_agentcore_starter_toolkit-0.1.21.dist-info → bedrock_agentcore_starter_toolkit-0.1.22.dist-info}/licenses/NOTICE.txt +0 -0
|
@@ -68,17 +68,34 @@ def _prompt_for_requirements_file(prompt_text: str, default: str = "") -> Option
|
|
|
68
68
|
return None
|
|
69
69
|
|
|
70
70
|
|
|
71
|
-
def _handle_requirements_file_display(
|
|
72
|
-
|
|
71
|
+
def _handle_requirements_file_display(
|
|
72
|
+
requirements_file: Optional[str], non_interactive: bool = False, source_path: Optional[str] = None
|
|
73
|
+
) -> Optional[str]:
|
|
74
|
+
"""Handle requirements file with display logic for CLI.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
requirements_file: Explicit requirements file path
|
|
78
|
+
non_interactive: Whether to skip interactive prompts
|
|
79
|
+
source_path: Optional source code directory (checks here first, then falls back to project root)
|
|
80
|
+
"""
|
|
73
81
|
from ...utils.runtime.entrypoint import detect_dependencies
|
|
74
82
|
|
|
75
83
|
if requirements_file:
|
|
76
84
|
# User provided file - validate and show confirmation
|
|
77
85
|
return _validate_requirements_file(requirements_file)
|
|
78
86
|
|
|
87
|
+
# Detect dependencies:
|
|
88
|
+
# - If source_path provided: check source_path only
|
|
89
|
+
# - Otherwise: check project root (Path.cwd())
|
|
90
|
+
if source_path:
|
|
91
|
+
source_dir = Path(source_path)
|
|
92
|
+
deps = detect_dependencies(source_dir)
|
|
93
|
+
else:
|
|
94
|
+
# No source_path, check project root
|
|
95
|
+
deps = detect_dependencies(Path.cwd())
|
|
96
|
+
|
|
79
97
|
if non_interactive:
|
|
80
98
|
# Auto-detection for non-interactive mode
|
|
81
|
-
deps = detect_dependencies(Path.cwd())
|
|
82
99
|
if deps.found:
|
|
83
100
|
_print_success(f"Using detected file: [dim]{deps.file}[/dim]")
|
|
84
101
|
return None # Use detected file
|
|
@@ -86,8 +103,6 @@ def _handle_requirements_file_display(requirements_file: Optional[str], non_inte
|
|
|
86
103
|
_handle_error("No requirements file specified and none found automatically")
|
|
87
104
|
|
|
88
105
|
# Auto-detection with interactive prompt
|
|
89
|
-
deps = detect_dependencies(Path.cwd())
|
|
90
|
-
|
|
91
106
|
if deps.found:
|
|
92
107
|
console.print(f"\n🔍 [cyan]Detected dependency file:[/cyan] [bold]{deps.file}[/bold]")
|
|
93
108
|
console.print("[dim]Press Enter to use this file, or type a different path (use Tab for autocomplete):[/dim]")
|
|
@@ -190,6 +205,7 @@ def configure(
|
|
|
190
205
|
non_interactive: bool = typer.Option(
|
|
191
206
|
False, "--non-interactive", "-ni", help="Skip prompts; use defaults unless overridden"
|
|
192
207
|
),
|
|
208
|
+
source_path: Optional[str] = typer.Option(None, "--source-path", "-sp", help="Path to agent source code directory"),
|
|
193
209
|
):
|
|
194
210
|
"""Configure a Bedrock AgentCore agent. The agent name defaults to your Python file name."""
|
|
195
211
|
if ctx.invoked_subcommand is not None:
|
|
@@ -237,7 +253,7 @@ def configure(
|
|
|
237
253
|
_print_success(f"Using existing ECR repository: [dim]{ecr_repository}[/dim]")
|
|
238
254
|
|
|
239
255
|
# Handle dependency file selection with simplified logic
|
|
240
|
-
final_requirements_file = _handle_requirements_file_display(requirements_file, non_interactive)
|
|
256
|
+
final_requirements_file = _handle_requirements_file_display(requirements_file, non_interactive, source_path)
|
|
241
257
|
|
|
242
258
|
# Handle OAuth authorization configuration
|
|
243
259
|
oauth_config = None
|
|
@@ -281,6 +297,7 @@ def configure(
|
|
|
281
297
|
region=region,
|
|
282
298
|
protocol=protocol.upper() if protocol else None,
|
|
283
299
|
non_interactive=non_interactive,
|
|
300
|
+
source_path=source_path,
|
|
284
301
|
)
|
|
285
302
|
|
|
286
303
|
# Prepare authorization info for summary
|
|
@@ -304,7 +304,6 @@ class ConfigurationManager:
|
|
|
304
304
|
|
|
305
305
|
def _prompt_new_memory_config(self) -> Tuple[str, str]:
|
|
306
306
|
"""Prompt for new memory configuration."""
|
|
307
|
-
console.print("\n🧠 [cyan]Memory Configuration[/cyan]")
|
|
308
307
|
console.print("[green]✓ Short-term memory is enabled by default[/green]")
|
|
309
308
|
console.print(" • Stores conversations within sessions")
|
|
310
309
|
console.print(" • Provides immediate context recall")
|
|
@@ -44,6 +44,7 @@ class Runtime:
|
|
|
44
44
|
auto_create_ecr: bool = True,
|
|
45
45
|
auto_create_execution_role: bool = False,
|
|
46
46
|
authorizer_configuration: Optional[Dict[str, Any]] = None,
|
|
47
|
+
request_header_configuration: Optional[Dict[str, Any]] = None,
|
|
47
48
|
region: Optional[str] = None,
|
|
48
49
|
protocol: Optional[Literal["HTTP", "MCP", "A2A"]] = None,
|
|
49
50
|
disable_otel: bool = False,
|
|
@@ -64,6 +65,7 @@ class Runtime:
|
|
|
64
65
|
auto_create_ecr: Whether to auto-create ECR repository
|
|
65
66
|
auto_create_execution_role: Whether to auto-create execution role (makes execution_role optional)
|
|
66
67
|
authorizer_configuration: JWT authorizer configuration dictionary
|
|
68
|
+
request_header_configuration: Request header configuration dictionary
|
|
67
69
|
region: AWS region for deployment
|
|
68
70
|
protocol: agent server protocol, must be either HTTP or MCP or A2A
|
|
69
71
|
disable_otel: Whether to disable OpenTelemetry observability (default: False)
|
|
@@ -120,6 +122,7 @@ class Runtime:
|
|
|
120
122
|
enable_observability=not disable_otel,
|
|
121
123
|
requirements_file=final_requirements_file,
|
|
122
124
|
authorizer_configuration=authorizer_configuration,
|
|
125
|
+
request_header_configuration=request_header_configuration,
|
|
123
126
|
region=region,
|
|
124
127
|
protocol=protocol.upper() if protocol else None,
|
|
125
128
|
non_interactive=non_interactive,
|
|
@@ -41,6 +41,7 @@ def configure_bedrock_agentcore(
|
|
|
41
41
|
region: Optional[str] = None,
|
|
42
42
|
protocol: Optional[str] = None,
|
|
43
43
|
non_interactive: bool = False,
|
|
44
|
+
source_path: Optional[str] = None,
|
|
44
45
|
) -> ConfigureResult:
|
|
45
46
|
"""Configure Bedrock AgentCore application with deployment settings.
|
|
46
47
|
|
|
@@ -61,6 +62,7 @@ def configure_bedrock_agentcore(
|
|
|
61
62
|
region: AWS region for deployment
|
|
62
63
|
protocol: agent server protocol, must be either HTTP or MCP or A2A
|
|
63
64
|
non_interactive: Skip interactive prompts and use defaults
|
|
65
|
+
source_path: Optional path to agent source code directory
|
|
64
66
|
|
|
65
67
|
Returns:
|
|
66
68
|
ConfigureResult model with configuration details
|
|
@@ -73,10 +75,13 @@ def configure_bedrock_agentcore(
|
|
|
73
75
|
log.setLevel(logging.INFO)
|
|
74
76
|
# Log agent name at the start of configuration
|
|
75
77
|
log.info("Configuring BedrockAgentCore agent: %s", agent_name)
|
|
78
|
+
|
|
79
|
+
# Build directory is always project root for module validation and dependency detection
|
|
76
80
|
build_dir = Path.cwd()
|
|
77
81
|
|
|
78
82
|
if verbose:
|
|
79
83
|
log.debug("Build directory: %s", build_dir)
|
|
84
|
+
log.debug("Source path: %s", source_path or "None (using build directory)")
|
|
80
85
|
log.debug("Bedrock AgentCore name: %s", agent_name)
|
|
81
86
|
log.debug("Entrypoint path: %s", entrypoint_path)
|
|
82
87
|
|
|
@@ -196,24 +201,48 @@ def configure_bedrock_agentcore(
|
|
|
196
201
|
if memory_id:
|
|
197
202
|
log.debug(" Memory ID: %s", memory_id)
|
|
198
203
|
|
|
204
|
+
# Determine output directory for Dockerfile based on source_path
|
|
205
|
+
# If source_path provided: write to .bedrock_agentcore/{agent_name}/ directly
|
|
206
|
+
# Otherwise: write to project root (legacy)
|
|
207
|
+
if source_path:
|
|
208
|
+
from ...utils.runtime.config import get_agentcore_directory
|
|
209
|
+
|
|
210
|
+
dockerfile_output_dir = get_agentcore_directory(Path.cwd(), agent_name, source_path)
|
|
211
|
+
else:
|
|
212
|
+
dockerfile_output_dir = build_dir
|
|
213
|
+
|
|
214
|
+
# Generate Dockerfile in the correct location (no moving needed)
|
|
199
215
|
dockerfile_path = runtime.generate_dockerfile(
|
|
200
216
|
entrypoint_path,
|
|
201
|
-
|
|
217
|
+
dockerfile_output_dir,
|
|
202
218
|
bedrock_agentcore_name or "bedrock_agentcore",
|
|
203
219
|
region,
|
|
204
220
|
enable_observability,
|
|
205
221
|
requirements_file,
|
|
206
222
|
memory_id,
|
|
207
223
|
memory_name,
|
|
224
|
+
source_path,
|
|
208
225
|
protocol,
|
|
209
226
|
)
|
|
210
|
-
|
|
211
|
-
# Check if .dockerignore was created
|
|
212
|
-
dockerignore_path = build_dir / ".dockerignore"
|
|
213
|
-
|
|
214
227
|
log.info("Generated Dockerfile: %s", dockerfile_path)
|
|
215
|
-
|
|
216
|
-
|
|
228
|
+
|
|
229
|
+
# Ensure .dockerignore exists at Docker build context location
|
|
230
|
+
if source_path:
|
|
231
|
+
# For source_path: .dockerignore at source directory (Docker build context)
|
|
232
|
+
source_dockerignore = Path(source_path) / ".dockerignore"
|
|
233
|
+
if not source_dockerignore.exists():
|
|
234
|
+
template_path = (
|
|
235
|
+
Path(__file__).parent.parent.parent / "utils" / "runtime" / "templates" / "dockerignore.template"
|
|
236
|
+
)
|
|
237
|
+
if template_path.exists():
|
|
238
|
+
source_dockerignore.write_text(template_path.read_text())
|
|
239
|
+
log.info("Generated .dockerignore: %s", source_dockerignore)
|
|
240
|
+
dockerignore_path = source_dockerignore
|
|
241
|
+
else:
|
|
242
|
+
# Legacy: .dockerignore at project root
|
|
243
|
+
dockerignore_path = build_dir / ".dockerignore"
|
|
244
|
+
if dockerignore_path.exists():
|
|
245
|
+
log.info("Generated .dockerignore: %s", dockerignore_path)
|
|
217
246
|
|
|
218
247
|
# Handle project configuration (named agents)
|
|
219
248
|
config_path = build_dir / ".bedrock_agentcore.yaml"
|
|
@@ -258,6 +287,7 @@ def configure_bedrock_agentcore(
|
|
|
258
287
|
entrypoint=entrypoint,
|
|
259
288
|
platform=ContainerRuntime.DEFAULT_PLATFORM,
|
|
260
289
|
container_runtime=runtime.runtime,
|
|
290
|
+
source_path=str(Path(source_path).resolve()) if source_path else None,
|
|
261
291
|
aws=AWSConfig(
|
|
262
292
|
execution_role=execution_role_arn,
|
|
263
293
|
execution_role_auto_create=execution_role_auto_create,
|
|
@@ -11,6 +11,7 @@ from ...operations.memory.manager import MemoryManager
|
|
|
11
11
|
from ...services.runtime import BedrockAgentCoreClient
|
|
12
12
|
from ...utils.runtime.config import load_config, save_config
|
|
13
13
|
from ...utils.runtime.schema import BedrockAgentCoreAgentSchema, BedrockAgentCoreConfigSchema
|
|
14
|
+
from .exceptions import RuntimeToolkitException
|
|
14
15
|
from .models import DestroyResult
|
|
15
16
|
|
|
16
17
|
log = logging.getLogger(__name__)
|
|
@@ -102,7 +103,7 @@ def destroy_bedrock_agentcore(
|
|
|
102
103
|
|
|
103
104
|
except Exception as e:
|
|
104
105
|
log.error("Destroy operation failed: %s", str(e))
|
|
105
|
-
raise
|
|
106
|
+
raise RuntimeToolkitException(f"Destroy operation failed: {e}") from e
|
|
106
107
|
|
|
107
108
|
|
|
108
109
|
def _destroy_agentcore_endpoint(
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Exceptions for the Bedrock AgentCore Runtime module."""
|
|
2
|
+
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RuntimeException(Exception):
|
|
7
|
+
"""Base exception for all Runtime SDK errors."""
|
|
8
|
+
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class RuntimeToolkitException(RuntimeException):
|
|
13
|
+
"""Raised when runtime operations fail with resource tracking."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, message: str, created_resources: Optional[List[str]] = None):
|
|
16
|
+
"""Initialize RuntimeToolkitException with optional resource tracking.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
message: Error message
|
|
20
|
+
created_resources: List of resources created before failure
|
|
21
|
+
"""
|
|
22
|
+
self.created_resources = created_resources or []
|
|
23
|
+
if created_resources:
|
|
24
|
+
full_message = f"{message}. Resources created: {created_resources}"
|
|
25
|
+
else:
|
|
26
|
+
full_message = message
|
|
27
|
+
super().__init__(full_message)
|
|
@@ -19,6 +19,7 @@ from ...utils.runtime.container import ContainerRuntime
|
|
|
19
19
|
from ...utils.runtime.logs import get_genai_observability_url
|
|
20
20
|
from ...utils.runtime.schema import BedrockAgentCoreAgentSchema, BedrockAgentCoreConfigSchema
|
|
21
21
|
from .create_role import get_or_create_runtime_execution_role
|
|
22
|
+
from .exceptions import RuntimeToolkitException
|
|
22
23
|
from .models import LaunchResult
|
|
23
24
|
|
|
24
25
|
log = logging.getLogger(__name__)
|
|
@@ -479,14 +480,24 @@ def launch_bedrock_agentcore(
|
|
|
479
480
|
"💡 For local builds, please install Docker, Finch, or Podman"
|
|
480
481
|
)
|
|
481
482
|
|
|
482
|
-
# Get build context -
|
|
483
|
-
build_dir = config_path.parent
|
|
483
|
+
# Get build context - use source_path if configured, otherwise use project root
|
|
484
|
+
build_dir = Path(agent_config.source_path) if agent_config.source_path else config_path.parent
|
|
485
|
+
log.info("Using build directory: %s", build_dir)
|
|
484
486
|
|
|
485
487
|
bedrock_agentcore_name = agent_config.name
|
|
486
488
|
tag = f"bedrock_agentcore-{bedrock_agentcore_name}:latest"
|
|
487
489
|
|
|
488
490
|
# Step 1: Build Docker image (only if we need it)
|
|
489
|
-
|
|
491
|
+
# When using source_path, Dockerfile is in .bedrock_agentcore/{agent_name}/ directory
|
|
492
|
+
from ...utils.runtime.config import get_agentcore_directory
|
|
493
|
+
|
|
494
|
+
dockerfile_dir = get_agentcore_directory(config_path.parent, agent_config.name, agent_config.source_path)
|
|
495
|
+
dockerfile_path = dockerfile_dir / "Dockerfile"
|
|
496
|
+
|
|
497
|
+
if not dockerfile_path.exists():
|
|
498
|
+
raise RuntimeError(f"Dockerfile not found at {dockerfile_path}. Please run 'agentcore configure' first.")
|
|
499
|
+
|
|
500
|
+
success, output = runtime.build(build_dir, tag, dockerfile_path=dockerfile_path)
|
|
490
501
|
if not success:
|
|
491
502
|
error_lines = output[-10:] if len(output) > 10 else output
|
|
492
503
|
error_message = " ".join(error_lines)
|
|
@@ -573,53 +584,82 @@ def _execute_codebuild_workflow(
|
|
|
573
584
|
agent_config.aws.account,
|
|
574
585
|
agent_config.aws.region,
|
|
575
586
|
)
|
|
576
|
-
# Validate configuration
|
|
577
|
-
errors = agent_config.validate(for_local=False)
|
|
578
|
-
if errors:
|
|
579
|
-
raise ValueError(f"Invalid configuration: {', '.join(errors)}")
|
|
580
587
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
raise ValueError("Region not found in configuration")
|
|
588
|
+
# Track created resources for error context
|
|
589
|
+
created_resources = []
|
|
584
590
|
|
|
585
|
-
|
|
586
|
-
|
|
591
|
+
try:
|
|
592
|
+
# Validate configuration
|
|
593
|
+
errors = agent_config.validate(for_local=False)
|
|
594
|
+
if errors:
|
|
595
|
+
raise ValueError(f"Invalid configuration: {', '.join(errors)}")
|
|
596
|
+
|
|
597
|
+
region = agent_config.aws.region
|
|
598
|
+
if not region:
|
|
599
|
+
raise ValueError("Region not found in configuration")
|
|
600
|
+
|
|
601
|
+
session = boto3.Session(region_name=region)
|
|
602
|
+
account_id = agent_config.aws.account # Use existing account from config
|
|
603
|
+
|
|
604
|
+
# Setup AWS resources
|
|
605
|
+
log.info("Setting up AWS resources (ECR repository%s)...", "" if ecr_only else ", execution roles")
|
|
606
|
+
ecr_uri = _ensure_ecr_repository(agent_config, project_config, config_path, agent_name, region)
|
|
607
|
+
if ecr_uri:
|
|
608
|
+
created_resources.append(f"ECR Repository: {ecr_uri}")
|
|
609
|
+
ecr_repository_arn = f"arn:aws:ecr:{region}:{account_id}:repository/{ecr_uri.split('/')[-1]}"
|
|
610
|
+
|
|
611
|
+
# Setup execution role only if not ECR-only mode
|
|
612
|
+
if not ecr_only:
|
|
613
|
+
_ensure_execution_role(agent_config, project_config, config_path, agent_name, region, account_id)
|
|
614
|
+
if agent_config.aws.execution_role:
|
|
615
|
+
created_resources.append(f"Runtime Execution Role: {agent_config.aws.execution_role}")
|
|
616
|
+
|
|
617
|
+
# Prepare CodeBuild
|
|
618
|
+
log.info("Preparing CodeBuild project and uploading source...")
|
|
619
|
+
codebuild_service = CodeBuildService(session)
|
|
620
|
+
|
|
621
|
+
# Use cached CodeBuild role from config if available
|
|
622
|
+
if hasattr(agent_config, "codebuild") and agent_config.codebuild.execution_role:
|
|
623
|
+
log.info("Using CodeBuild role from config: %s", agent_config.codebuild.execution_role)
|
|
624
|
+
codebuild_execution_role = agent_config.codebuild.execution_role
|
|
625
|
+
else:
|
|
626
|
+
codebuild_execution_role = codebuild_service.create_codebuild_execution_role(
|
|
627
|
+
account_id=account_id, ecr_repository_arn=ecr_repository_arn, agent_name=agent_name
|
|
628
|
+
)
|
|
629
|
+
if codebuild_execution_role:
|
|
630
|
+
created_resources.append(f"CodeBuild Execution Role: {codebuild_execution_role}")
|
|
587
631
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
ecr_uri = _ensure_ecr_repository(agent_config, project_config, config_path, agent_name, region)
|
|
591
|
-
ecr_repository_arn = f"arn:aws:ecr:{region}:{account_id}:repository/{ecr_uri.split('/')[-1]}"
|
|
632
|
+
# Get source directory - use source_path if configured, otherwise use current directory
|
|
633
|
+
source_dir = str(Path(agent_config.source_path)) if agent_config.source_path else "."
|
|
592
634
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
_ensure_execution_role(agent_config, project_config, config_path, agent_name, region, account_id)
|
|
635
|
+
# Get Dockerfile directory - use agentcore directory if source_path provided
|
|
636
|
+
from ...utils.runtime.config import get_agentcore_directory
|
|
596
637
|
|
|
597
|
-
|
|
598
|
-
log.info("Preparing CodeBuild project and uploading source...")
|
|
599
|
-
codebuild_service = CodeBuildService(session)
|
|
638
|
+
dockerfile_dir = get_agentcore_directory(config_path.parent, agent_name, agent_config.source_path)
|
|
600
639
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
log.info("Using CodeBuild role from config: %s", agent_config.codebuild.execution_role)
|
|
604
|
-
codebuild_execution_role = agent_config.codebuild.execution_role
|
|
605
|
-
else:
|
|
606
|
-
codebuild_execution_role = codebuild_service.create_codebuild_execution_role(
|
|
607
|
-
account_id=account_id, ecr_repository_arn=ecr_repository_arn, agent_name=agent_name
|
|
640
|
+
source_location = codebuild_service.upload_source(
|
|
641
|
+
agent_name=agent_name, source_dir=source_dir, dockerfile_dir=str(dockerfile_dir)
|
|
608
642
|
)
|
|
609
643
|
|
|
610
|
-
|
|
644
|
+
# Use cached project name from config if available
|
|
645
|
+
if hasattr(agent_config, "codebuild") and agent_config.codebuild.project_name:
|
|
646
|
+
log.info("Using CodeBuild project from config: %s", agent_config.codebuild.project_name)
|
|
647
|
+
project_name = agent_config.codebuild.project_name
|
|
648
|
+
else:
|
|
649
|
+
project_name = codebuild_service.create_or_update_project(
|
|
650
|
+
agent_name=agent_name,
|
|
651
|
+
ecr_repository_uri=ecr_uri,
|
|
652
|
+
execution_role=codebuild_execution_role,
|
|
653
|
+
source_location=source_location,
|
|
654
|
+
)
|
|
655
|
+
if project_name:
|
|
656
|
+
created_resources.append(f"CodeBuild Project: {project_name}")
|
|
611
657
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
project_name = codebuild_service.create_or_update_project(
|
|
618
|
-
agent_name=agent_name,
|
|
619
|
-
ecr_repository_uri=ecr_uri,
|
|
620
|
-
execution_role=codebuild_execution_role,
|
|
621
|
-
source_location=source_location,
|
|
622
|
-
)
|
|
658
|
+
except Exception as e:
|
|
659
|
+
if created_resources:
|
|
660
|
+
log.error("Launch failed after creating the following resources: %s. Error: %s", created_resources, str(e))
|
|
661
|
+
raise RuntimeToolkitException("Launch failed", created_resources) from e
|
|
662
|
+
raise
|
|
623
663
|
|
|
624
664
|
# Execute CodeBuild
|
|
625
665
|
log.info("Starting CodeBuild build (this may take several minutes)...")
|
|
@@ -6,8 +6,9 @@ import os
|
|
|
6
6
|
import tempfile
|
|
7
7
|
import time
|
|
8
8
|
import zipfile
|
|
9
|
+
from importlib.resources import files
|
|
9
10
|
from pathlib import Path
|
|
10
|
-
from typing import List
|
|
11
|
+
from typing import List, Optional
|
|
11
12
|
|
|
12
13
|
import boto3
|
|
13
14
|
from botocore.exceptions import ClientError
|
|
@@ -70,21 +71,28 @@ class CodeBuildService:
|
|
|
70
71
|
|
|
71
72
|
return bucket_name
|
|
72
73
|
|
|
73
|
-
def upload_source(self, agent_name: str) -> str:
|
|
74
|
-
"""Upload
|
|
74
|
+
def upload_source(self, agent_name: str, source_dir: str = ".", dockerfile_dir: Optional[str] = None) -> str:
|
|
75
|
+
"""Upload source directory to S3, respecting .dockerignore patterns.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
agent_name: Name of the agent
|
|
79
|
+
source_dir: Directory to upload (defaults to current directory)
|
|
80
|
+
dockerfile_dir: Directory containing Dockerfile (may be different from source_dir)
|
|
81
|
+
"""
|
|
75
82
|
account_id = self.account_id
|
|
76
83
|
bucket_name = self.ensure_source_bucket(account_id)
|
|
77
84
|
self.source_bucket = bucket_name
|
|
78
85
|
|
|
79
|
-
# Parse .dockerignore patterns
|
|
86
|
+
# Parse .dockerignore patterns from template for consistent filtering
|
|
80
87
|
ignore_patterns = self._parse_dockerignore()
|
|
81
88
|
|
|
82
89
|
with tempfile.NamedTemporaryFile(suffix=".zip", delete=False) as temp_zip:
|
|
83
90
|
try:
|
|
84
91
|
with zipfile.ZipFile(temp_zip.name, "w", zipfile.ZIP_DEFLATED) as zipf:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
# First, add all files from source_dir
|
|
93
|
+
for root, dirs, files in os.walk(source_dir):
|
|
94
|
+
# Convert to relative path from source_dir
|
|
95
|
+
rel_root = os.path.relpath(root, source_dir)
|
|
88
96
|
if rel_root == ".":
|
|
89
97
|
rel_root = ""
|
|
90
98
|
|
|
@@ -107,6 +115,16 @@ class CodeBuildService:
|
|
|
107
115
|
file_path = Path(root) / file
|
|
108
116
|
zipf.write(file_path, file_rel_path)
|
|
109
117
|
|
|
118
|
+
# If Dockerfile is in a different directory, include it in the zip
|
|
119
|
+
if dockerfile_dir and source_dir != dockerfile_dir:
|
|
120
|
+
dockerfile_path = Path(dockerfile_dir) / "Dockerfile"
|
|
121
|
+
source_dockerfile = Path(source_dir) / "Dockerfile"
|
|
122
|
+
|
|
123
|
+
if dockerfile_path.exists() and not source_dockerfile.exists():
|
|
124
|
+
# Include the Dockerfile from dockerfile_dir
|
|
125
|
+
zipf.write(dockerfile_path, "Dockerfile")
|
|
126
|
+
self.logger.info("Including Dockerfile from %s in source.zip", dockerfile_dir)
|
|
127
|
+
|
|
110
128
|
# Create agent-organized S3 key: agentname/source.zip (fixed naming for cache consistency)
|
|
111
129
|
s3_key = f"{agent_name}/source.zip"
|
|
112
130
|
|
|
@@ -280,21 +298,32 @@ phases:
|
|
|
280
298
|
"""
|
|
281
299
|
|
|
282
300
|
def _parse_dockerignore(self) -> List[str]:
|
|
283
|
-
"""Parse .dockerignore
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
301
|
+
"""Parse .dockerignore patterns from template for consistent filtering.
|
|
302
|
+
|
|
303
|
+
Always uses the dockerignore.template to ensure consistent file filtering
|
|
304
|
+
during zip creation, regardless of source_path configuration.
|
|
305
|
+
"""
|
|
306
|
+
# Use dockerignore.template from package resources
|
|
307
|
+
try:
|
|
308
|
+
template_content = (
|
|
309
|
+
files("bedrock_agentcore_starter_toolkit")
|
|
310
|
+
.joinpath("utils/runtime/templates/dockerignore.template")
|
|
311
|
+
.read_text()
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
patterns = []
|
|
315
|
+
for line in template_content.splitlines():
|
|
316
|
+
line = line.strip()
|
|
317
|
+
if line and not line.startswith("#"):
|
|
318
|
+
patterns.append(line)
|
|
319
|
+
|
|
320
|
+
self.logger.info("Using dockerignore.template with %d patterns for zip filtering", len(patterns))
|
|
321
|
+
return patterns
|
|
322
|
+
|
|
323
|
+
except Exception as e:
|
|
324
|
+
# Fallback to minimal default patterns if template not found
|
|
325
|
+
self.logger.warning("Could not load dockerignore.template (%s), using minimal default patterns", e)
|
|
326
|
+
return [
|
|
298
327
|
".git",
|
|
299
328
|
"__pycache__",
|
|
300
329
|
"*.pyc",
|
|
@@ -305,9 +334,6 @@ phases:
|
|
|
305
334
|
"*.egg-info",
|
|
306
335
|
".bedrock_agentcore.yaml", # Always exclude config
|
|
307
336
|
]
|
|
308
|
-
self.logger.info("No .dockerignore found, using default exclude patterns")
|
|
309
|
-
|
|
310
|
-
return patterns
|
|
311
337
|
|
|
312
338
|
def _should_ignore(self, path: str, patterns: List[str], is_dir: bool = False) -> bool:
|
|
313
339
|
"""Check if path should be ignored based on dockerignore patterns."""
|
|
@@ -5,7 +5,9 @@ from pathlib import Path
|
|
|
5
5
|
from typing import Optional
|
|
6
6
|
|
|
7
7
|
import yaml
|
|
8
|
+
from pydantic import ValidationError
|
|
8
9
|
|
|
10
|
+
from ...operations.runtime.exceptions import RuntimeToolkitException
|
|
9
11
|
from .schema import BedrockAgentCoreAgentSchema, BedrockAgentCoreConfigSchema
|
|
10
12
|
|
|
11
13
|
log = logging.getLogger(__name__)
|
|
@@ -58,8 +60,25 @@ def load_config(config_path: Path) -> BedrockAgentCoreConfigSchema:
|
|
|
58
60
|
# New format
|
|
59
61
|
try:
|
|
60
62
|
return BedrockAgentCoreConfigSchema.model_validate(data)
|
|
63
|
+
except ValidationError as e:
|
|
64
|
+
# Convert Pydantic errors to user-friendly messages
|
|
65
|
+
friendly_errors = []
|
|
66
|
+
for error in e.errors():
|
|
67
|
+
field = ".".join(str(loc) for loc in error["loc"])
|
|
68
|
+
msg = error["msg"]
|
|
69
|
+
# Make common errors more user-friendly
|
|
70
|
+
if "Source path does not exist" in msg:
|
|
71
|
+
friendly_errors.append(f"{field}: {msg} (check if the directory exists)")
|
|
72
|
+
elif "field required" in msg:
|
|
73
|
+
friendly_errors.append(f"{field}: This field is required")
|
|
74
|
+
elif "Input should be" in msg:
|
|
75
|
+
friendly_errors.append(f"{field}: {msg}")
|
|
76
|
+
else:
|
|
77
|
+
friendly_errors.append(f"{field}: {msg}")
|
|
78
|
+
|
|
79
|
+
raise RuntimeToolkitException("Configuration validation failed:\n• " + "\n• ".join(friendly_errors)) from e
|
|
61
80
|
except Exception as e:
|
|
62
|
-
raise
|
|
81
|
+
raise RuntimeToolkitException(f"Invalid configuration format: {e}") from e
|
|
63
82
|
|
|
64
83
|
|
|
65
84
|
def save_config(config: BedrockAgentCoreConfigSchema, config_path: Path):
|
|
@@ -127,3 +146,26 @@ def merge_agent_config(
|
|
|
127
146
|
config.default_agent = agent_name
|
|
128
147
|
|
|
129
148
|
return config
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def get_agentcore_directory(project_root: Path, agent_name: str, source_path: Optional[str] = None) -> Path:
|
|
152
|
+
"""Get the agentcore directory for an agent's build artifacts.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
project_root: Project root directory (typically Path.cwd())
|
|
156
|
+
agent_name: Name of the agent
|
|
157
|
+
source_path: Optional source path configuration
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
Path to agentcore directory:
|
|
161
|
+
- If source_path provided: {project_root}/.bedrock_agentcore/{agent_name}/
|
|
162
|
+
- Otherwise: {project_root}/ (legacy single-agent behavior)
|
|
163
|
+
"""
|
|
164
|
+
if source_path:
|
|
165
|
+
# Multi-agent support: use .bedrock_agentcore/{agent_name}/ for artifact isolation
|
|
166
|
+
agentcore_dir = project_root / ".bedrock_agentcore" / agent_name
|
|
167
|
+
agentcore_dir.mkdir(parents=True, exist_ok=True)
|
|
168
|
+
return agentcore_dir
|
|
169
|
+
else:
|
|
170
|
+
# Legacy single-agent: artifacts at project root
|
|
171
|
+
return project_root
|
|
@@ -8,10 +8,13 @@ from pathlib import Path
|
|
|
8
8
|
from typing import List, Optional, Tuple
|
|
9
9
|
|
|
10
10
|
from jinja2 import Template
|
|
11
|
+
from rich.console import Console
|
|
11
12
|
|
|
12
|
-
from ...cli.common import _handle_warn
|
|
13
|
+
from ...cli.common import _handle_warn, _print_success
|
|
13
14
|
from .entrypoint import detect_dependencies, get_python_version
|
|
14
15
|
|
|
16
|
+
console = Console()
|
|
17
|
+
|
|
15
18
|
log = logging.getLogger(__name__)
|
|
16
19
|
|
|
17
20
|
|
|
@@ -40,12 +43,9 @@ class ContainerRuntime:
|
|
|
40
43
|
break
|
|
41
44
|
else:
|
|
42
45
|
# Informational message - default CodeBuild deployment works fine
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"💡 Run 'agentcore launch' for cloud-based building and deployment\n"
|
|
47
|
-
"💡 For local builds, install Docker, Finch, or Podman"
|
|
48
|
-
)
|
|
46
|
+
console.print("\n💡 [cyan]No container engine found (Docker/Finch/Podman not installed)[/cyan]")
|
|
47
|
+
_print_success("Default deployment uses CodeBuild (no container engine needed)")
|
|
48
|
+
console.print("[dim]For local builds, install Docker, Finch, or Podman[/dim]")
|
|
49
49
|
self.runtime = "none"
|
|
50
50
|
self.has_local_runtime = False
|
|
51
51
|
elif runtime_type in self.available_runtimes:
|
|
@@ -55,10 +55,9 @@ class ContainerRuntime:
|
|
|
55
55
|
else:
|
|
56
56
|
# Convert hard error to warning - suggest CodeBuild instead
|
|
57
57
|
_handle_warn(
|
|
58
|
-
f"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
f"💡 For local builds, please install {runtime_type.capitalize()}"
|
|
58
|
+
f"{runtime_type.capitalize()} is not installed\n"
|
|
59
|
+
"Recommendation: Use CodeBuild for building containers in the cloud\n"
|
|
60
|
+
f"For local builds, please install {runtime_type.capitalize()}"
|
|
62
61
|
)
|
|
63
62
|
self.runtime = "none"
|
|
64
63
|
self.has_local_runtime = False
|
|
@@ -110,9 +109,23 @@ class ContainerRuntime:
|
|
|
110
109
|
requirements_file: Optional[str] = None,
|
|
111
110
|
memory_id: Optional[str] = None,
|
|
112
111
|
memory_name: Optional[str] = None,
|
|
112
|
+
source_path: Optional[str] = None,
|
|
113
113
|
protocol: Optional[str] = None,
|
|
114
114
|
) -> Path:
|
|
115
|
-
"""Generate Dockerfile from template.
|
|
115
|
+
"""Generate Dockerfile from template.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
agent_path: Path to agent entrypoint file
|
|
119
|
+
output_dir: Output directory for Dockerfile (project root)
|
|
120
|
+
agent_name: Name of the agent
|
|
121
|
+
aws_region: AWS region
|
|
122
|
+
enable_observability: Whether to enable observability
|
|
123
|
+
requirements_file: Optional explicit requirements file path
|
|
124
|
+
memory_id: Optional memory ID
|
|
125
|
+
memory_name: Optional memory name
|
|
126
|
+
source_path: Optional source code directory (for dependency detection)
|
|
127
|
+
protocol: Optional protocol configuration (HTTP or HTTPS)
|
|
128
|
+
"""
|
|
116
129
|
current_platform = self._get_current_platform()
|
|
117
130
|
required_platform = self.DEFAULT_PLATFORM
|
|
118
131
|
|
|
@@ -133,23 +146,39 @@ class ContainerRuntime:
|
|
|
133
146
|
with open(template_path) as f:
|
|
134
147
|
template = Template(f.read())
|
|
135
148
|
|
|
149
|
+
# Calculate build context root first (needed for validation)
|
|
150
|
+
# If source_path provided: module path relative to source_path (Docker build context)
|
|
151
|
+
# Otherwise: module path relative to project root
|
|
152
|
+
build_context_root = Path(source_path) if source_path else output_dir
|
|
153
|
+
|
|
136
154
|
# Generate .dockerignore if it doesn't exist
|
|
137
155
|
self._ensure_dockerignore(output_dir)
|
|
138
156
|
|
|
139
|
-
# Validate module path
|
|
140
|
-
self._validate_module_path(agent_path,
|
|
157
|
+
# Validate module path against build context root
|
|
158
|
+
self._validate_module_path(agent_path, build_context_root)
|
|
141
159
|
|
|
142
|
-
# Calculate module path relative to
|
|
143
|
-
agent_module_path = self._get_module_path(agent_path,
|
|
160
|
+
# Calculate module path relative to Docker build context
|
|
161
|
+
agent_module_path = self._get_module_path(agent_path, build_context_root)
|
|
144
162
|
|
|
145
163
|
wheelhouse_dir = output_dir / "wheelhouse"
|
|
146
164
|
|
|
147
|
-
# Detect dependencies
|
|
148
|
-
|
|
165
|
+
# Detect dependencies:
|
|
166
|
+
# - If source_path provided: check source_path only
|
|
167
|
+
# - Otherwise: check project root (output_dir)
|
|
168
|
+
# - If explicit requirements_file provided: use that regardless
|
|
169
|
+
if source_path and not requirements_file:
|
|
170
|
+
# Check source_path directory for dependencies
|
|
171
|
+
source_dir = Path(source_path)
|
|
172
|
+
deps = detect_dependencies(source_dir, explicit_file=None)
|
|
173
|
+
else:
|
|
174
|
+
# Check project root for dependencies (or use explicit file)
|
|
175
|
+
deps = detect_dependencies(output_dir, explicit_file=requirements_file)
|
|
149
176
|
|
|
150
177
|
# Add logic to avoid duplicate installation
|
|
178
|
+
# Check for pyproject.toml in the appropriate directory
|
|
151
179
|
has_current_package = False
|
|
152
|
-
|
|
180
|
+
check_dir = Path(source_path) if source_path else output_dir
|
|
181
|
+
if (check_dir / "pyproject.toml").exists():
|
|
153
182
|
# Only install current package if deps isn't already pointing to it
|
|
154
183
|
if not (deps.found and deps.is_root_package):
|
|
155
184
|
has_current_package = True
|
|
@@ -189,6 +218,7 @@ class ContainerRuntime:
|
|
|
189
218
|
"""Validate that the agent path can be converted to a valid Python module path."""
|
|
190
219
|
try:
|
|
191
220
|
agent_path = agent_path.resolve()
|
|
221
|
+
project_root = project_root.resolve()
|
|
192
222
|
relative_path = agent_path.relative_to(project_root)
|
|
193
223
|
for part in relative_path.parts[:-1]: # Check all directory parts
|
|
194
224
|
if "-" in part:
|
|
@@ -206,6 +236,7 @@ class ContainerRuntime:
|
|
|
206
236
|
"""Get the Python module path for the agent file."""
|
|
207
237
|
try:
|
|
208
238
|
agent_path = agent_path.resolve()
|
|
239
|
+
project_root = project_root.resolve()
|
|
209
240
|
# Get relative path from project root
|
|
210
241
|
relative_path = agent_path.relative_to(project_root)
|
|
211
242
|
# Convert to module path (e.g., src/agents/my_agent.py -> src.agents.my_agent)
|
|
@@ -229,8 +260,21 @@ class ContainerRuntime:
|
|
|
229
260
|
arch = arch_map.get(machine, machine)
|
|
230
261
|
return f"linux/{arch}"
|
|
231
262
|
|
|
232
|
-
def build(
|
|
233
|
-
|
|
263
|
+
def build(
|
|
264
|
+
self,
|
|
265
|
+
build_context: Path,
|
|
266
|
+
tag: str,
|
|
267
|
+
dockerfile_path: Optional[Path] = None,
|
|
268
|
+
platform: Optional[str] = None,
|
|
269
|
+
) -> Tuple[bool, List[str]]:
|
|
270
|
+
"""Build container image.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
build_context: Directory to use as build context
|
|
274
|
+
tag: Tag for the built image
|
|
275
|
+
dockerfile_path: Optional path to Dockerfile (if not in build_context)
|
|
276
|
+
platform: Optional platform override
|
|
277
|
+
"""
|
|
234
278
|
if not self.has_local_runtime:
|
|
235
279
|
return False, [
|
|
236
280
|
"No container runtime available for local build",
|
|
@@ -239,17 +283,29 @@ class ContainerRuntime:
|
|
|
239
283
|
"💡 For local builds, please install Docker, Finch, or Podman",
|
|
240
284
|
]
|
|
241
285
|
|
|
242
|
-
if not
|
|
243
|
-
return False, [f"
|
|
286
|
+
if not build_context.exists():
|
|
287
|
+
return False, [f"Build context directory not found: {build_context}"]
|
|
244
288
|
|
|
245
|
-
|
|
246
|
-
if
|
|
247
|
-
|
|
289
|
+
# Determine Dockerfile location
|
|
290
|
+
if dockerfile_path:
|
|
291
|
+
# Use provided Dockerfile path
|
|
292
|
+
if not dockerfile_path.exists():
|
|
293
|
+
return False, [f"Dockerfile not found: {dockerfile_path}"]
|
|
294
|
+
else:
|
|
295
|
+
# Look for Dockerfile in build context
|
|
296
|
+
dockerfile_path = build_context / "Dockerfile"
|
|
297
|
+
if not dockerfile_path.exists():
|
|
298
|
+
return False, [f"Dockerfile not found in {build_context}"]
|
|
248
299
|
|
|
249
300
|
cmd = [self.runtime, "build", "-t", tag]
|
|
301
|
+
|
|
302
|
+
# Use -f flag if Dockerfile is not in the build context
|
|
303
|
+
if dockerfile_path.parent != build_context:
|
|
304
|
+
cmd.extend(["-f", str(dockerfile_path)])
|
|
305
|
+
|
|
250
306
|
build_platform = platform or self.DEFAULT_PLATFORM
|
|
251
307
|
cmd.extend(["--platform", build_platform])
|
|
252
|
-
cmd.append(str(
|
|
308
|
+
cmd.append(str(build_context))
|
|
253
309
|
|
|
254
310
|
return self._execute_command(cmd)
|
|
255
311
|
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
"""Typed configuration schema for Bedrock AgentCore SDK."""
|
|
2
2
|
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
from typing import Dict, List, Literal, Optional
|
|
4
5
|
|
|
5
6
|
from pydantic import BaseModel, Field, field_validator
|
|
6
7
|
|
|
7
8
|
|
|
9
|
+
class NetworkModeConfig(BaseModel):
|
|
10
|
+
"""Network mode configuration for VPC deployments."""
|
|
11
|
+
|
|
12
|
+
security_groups: List[str] = Field(default_factory=list, description="List of security group IDs")
|
|
13
|
+
subnets: List[str] = Field(default_factory=list, description="List of subnet IDs")
|
|
14
|
+
|
|
15
|
+
|
|
8
16
|
class MemoryConfig(BaseModel):
|
|
9
17
|
"""Memory configuration for BedrockAgentCore."""
|
|
10
18
|
|
|
@@ -34,10 +42,38 @@ class NetworkConfiguration(BaseModel):
|
|
|
34
42
|
"""Network configuration for BedrockAgentCore deployment."""
|
|
35
43
|
|
|
36
44
|
network_mode: str = Field(default="PUBLIC", description="Network mode for deployment")
|
|
45
|
+
network_mode_config: Optional[NetworkModeConfig] = Field(
|
|
46
|
+
default=None, description="Network mode configuration (required for VPC mode)"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
@field_validator("network_mode")
|
|
50
|
+
@classmethod
|
|
51
|
+
def validate_network_mode(cls, v: str) -> str:
|
|
52
|
+
"""Validate network mode and ensure VPC config is provided when needed."""
|
|
53
|
+
valid_modes = ["PUBLIC", "VPC"]
|
|
54
|
+
if v not in valid_modes:
|
|
55
|
+
raise ValueError(f"Invalid network_mode: {v}. Must be one of {valid_modes}")
|
|
56
|
+
return v
|
|
57
|
+
|
|
58
|
+
@field_validator("network_mode_config")
|
|
59
|
+
@classmethod
|
|
60
|
+
def validate_network_mode_config(cls, v: Optional[NetworkModeConfig], info) -> Optional[NetworkModeConfig]:
|
|
61
|
+
"""Validate that network_mode_config is provided when network_mode is VPC."""
|
|
62
|
+
if info.data.get("network_mode") == "VPC" and v is None:
|
|
63
|
+
raise ValueError("network_mode_config is required when network_mode is VPC")
|
|
64
|
+
return v
|
|
37
65
|
|
|
38
66
|
def to_aws_dict(self) -> dict:
|
|
39
67
|
"""Convert to AWS API format with camelCase keys."""
|
|
40
|
-
|
|
68
|
+
result = {"networkMode": self.network_mode}
|
|
69
|
+
|
|
70
|
+
if self.network_mode_config:
|
|
71
|
+
result["networkModeConfig"] = {
|
|
72
|
+
"securityGroups": self.network_mode_config.security_groups,
|
|
73
|
+
"subnets": self.network_mode_config.subnets,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return result
|
|
41
77
|
|
|
42
78
|
|
|
43
79
|
class ProtocolConfiguration(BaseModel):
|
|
@@ -113,6 +149,7 @@ class BedrockAgentCoreAgentSchema(BaseModel):
|
|
|
113
149
|
entrypoint: str = Field(..., description="Entrypoint file path")
|
|
114
150
|
platform: str = Field(default="linux/amd64", description="Target platform")
|
|
115
151
|
container_runtime: str = Field(default="docker", description="Container runtime to use")
|
|
152
|
+
source_path: Optional[str] = Field(default=None, description="Directory containing agent source code")
|
|
116
153
|
aws: AWSConfig = Field(default_factory=AWSConfig)
|
|
117
154
|
bedrock_agentcore: BedrockAgentCoreDeploymentInfo = Field(default_factory=BedrockAgentCoreDeploymentInfo)
|
|
118
155
|
codebuild: CodeBuildConfig = Field(default_factory=CodeBuildConfig)
|
|
@@ -121,6 +158,37 @@ class BedrockAgentCoreAgentSchema(BaseModel):
|
|
|
121
158
|
request_header_configuration: Optional[dict] = Field(default=None, description="Request header configuration")
|
|
122
159
|
oauth_configuration: Optional[dict] = Field(default=None, description="Oauth configuration")
|
|
123
160
|
|
|
161
|
+
@field_validator("source_path")
|
|
162
|
+
@classmethod
|
|
163
|
+
def validate_source_path(cls, v: Optional[str]) -> Optional[str]:
|
|
164
|
+
"""Validate source path if provided.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
v: Source path value
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
Validated source path or None
|
|
171
|
+
|
|
172
|
+
Raises:
|
|
173
|
+
ValueError: If source path is invalid
|
|
174
|
+
"""
|
|
175
|
+
if v is None:
|
|
176
|
+
return v
|
|
177
|
+
|
|
178
|
+
# Convert to Path for validation
|
|
179
|
+
source_path = Path(v)
|
|
180
|
+
|
|
181
|
+
# Check if path exists
|
|
182
|
+
if not source_path.exists():
|
|
183
|
+
raise ValueError(f"Source path does not exist: {v}")
|
|
184
|
+
|
|
185
|
+
# Check if it's a directory
|
|
186
|
+
if not source_path.is_dir():
|
|
187
|
+
raise ValueError(f"Source path must be a directory: {v}")
|
|
188
|
+
|
|
189
|
+
# Return absolute path string
|
|
190
|
+
return str(source_path.resolve())
|
|
191
|
+
|
|
124
192
|
def get_authorizer_configuration(self) -> Optional[dict]:
|
|
125
193
|
"""Get the authorizer configuration."""
|
|
126
194
|
return self.authorizer_configuration
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bedrock-agentcore-starter-toolkit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.22
|
|
4
4
|
Summary: A starter toolkit for using Bedrock AgentCore
|
|
5
5
|
Project-URL: Homepage, https://github.com/aws/bedrock-agentcore-starter-toolkit
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/aws/bedrock-agentcore-starter-toolkit/issues
|
|
@@ -22,7 +22,7 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
|
22
22
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
23
|
Requires-Python: >=3.10
|
|
24
24
|
Requires-Dist: autopep8>=2.3.2
|
|
25
|
-
Requires-Dist: bedrock-agentcore>=0.1.
|
|
25
|
+
Requires-Dist: bedrock-agentcore>=0.1.7
|
|
26
26
|
Requires-Dist: boto3>=1.40.35
|
|
27
27
|
Requires-Dist: botocore>=1.40.35
|
|
28
28
|
Requires-Dist: docstring-parser<1.0,>=0.15
|
|
@@ -9,11 +9,11 @@ bedrock_agentcore_starter_toolkit/cli/import_agent/__init__.py,sha256=tyM3dXM3Tc
|
|
|
9
9
|
bedrock_agentcore_starter_toolkit/cli/import_agent/agent_info.py,sha256=CcPXbKNnI9fc7NyFmZBjB3PkB0wAz2Q_kBGoUVcnngA,9736
|
|
10
10
|
bedrock_agentcore_starter_toolkit/cli/import_agent/commands.py,sha256=vpA66fGwKf6cxBelT3Yb_Af5Ow3AMquGLIDe-tBLjmc,22419
|
|
11
11
|
bedrock_agentcore_starter_toolkit/cli/runtime/__init__.py,sha256=0zKPPoYThoDIr3DZhIQJavq5nVTKRsgcE1s9--wx118,60
|
|
12
|
-
bedrock_agentcore_starter_toolkit/cli/runtime/commands.py,sha256=
|
|
13
|
-
bedrock_agentcore_starter_toolkit/cli/runtime/configuration_manager.py,sha256=
|
|
12
|
+
bedrock_agentcore_starter_toolkit/cli/runtime/commands.py,sha256=jmkgolQdY9qC7dpWWzel6zb6uI1VggMyZe7DNgepoC4,51960
|
|
13
|
+
bedrock_agentcore_starter_toolkit/cli/runtime/configuration_manager.py,sha256=qTpVMwZGORP2NmDO9uNfSocikKfzPSKgVSzuywSBlwk,14536
|
|
14
14
|
bedrock_agentcore_starter_toolkit/notebook/__init__.py,sha256=wH1ZzIVKsKT_P0qX2kIIoyVxeHj8K40odfR1YI3McHw,129
|
|
15
15
|
bedrock_agentcore_starter_toolkit/notebook/runtime/__init__.py,sha256=DoGfB_uGFLANJVE9rSZtTH3ymw76WBWmD9vORvBIdXs,66
|
|
16
|
-
bedrock_agentcore_starter_toolkit/notebook/runtime/bedrock_agentcore.py,sha256=
|
|
16
|
+
bedrock_agentcore_starter_toolkit/notebook/runtime/bedrock_agentcore.py,sha256=HbERHCoTExo6KqJ3vOg_jgupehjjd2kXYx8_o-B2Rls,15966
|
|
17
17
|
bedrock_agentcore_starter_toolkit/operations/__init__.py,sha256=L7sCNjfZviiVVoh2f3NEs2sbjNqFkmIRI3ZPYMMWMz0,51
|
|
18
18
|
bedrock_agentcore_starter_toolkit/operations/gateway/__init__.py,sha256=5Qo1GeN-DghNp9g0coFUs7WpUJDboJoidOVs-5Co7fo,233
|
|
19
19
|
bedrock_agentcore_starter_toolkit/operations/gateway/client.py,sha256=9KQzRAEGWbBDVVacdB1GqN_HJ06vwTBs6tLwfxYROoY,26498
|
|
@@ -38,15 +38,16 @@ bedrock_agentcore_starter_toolkit/operations/memory/models/strategies/semantic.p
|
|
|
38
38
|
bedrock_agentcore_starter_toolkit/operations/memory/models/strategies/summary.py,sha256=X0sVh-6Hw9PPnpPQucG_M7gVyXUiElZInFXBN8WDFUQ,1015
|
|
39
39
|
bedrock_agentcore_starter_toolkit/operations/memory/models/strategies/user_preference.py,sha256=JJPAzt_Shix5a-RJEf7xOEzN5kxtX3dpP8xoMvry61U,996
|
|
40
40
|
bedrock_agentcore_starter_toolkit/operations/runtime/__init__.py,sha256=0jRUuwSoqh4R_WqzfP4XAXngrgyFK5uH8JGXUVars6Y,793
|
|
41
|
-
bedrock_agentcore_starter_toolkit/operations/runtime/configure.py,sha256
|
|
41
|
+
bedrock_agentcore_starter_toolkit/operations/runtime/configure.py,sha256=-0j-LfGOo6wky339x3SnG3bq_DYQl0e8n6gweci1XOs,14451
|
|
42
42
|
bedrock_agentcore_starter_toolkit/operations/runtime/create_role.py,sha256=1-b_wBvkOXNh-HJsxATwHfXQqj0dpdETds0FNSTY0BE,16116
|
|
43
|
-
bedrock_agentcore_starter_toolkit/operations/runtime/destroy.py,sha256=
|
|
43
|
+
bedrock_agentcore_starter_toolkit/operations/runtime/destroy.py,sha256=Zy2U2SwW6Z4y05Wi5xlEg0Ue2O3Euf-pywaMZ1t4J7c,25206
|
|
44
|
+
bedrock_agentcore_starter_toolkit/operations/runtime/exceptions.py,sha256=7iZNVbsz5XyvnpMM4paJb5_LT6DYdEI3nHhM9f3BERE,869
|
|
44
45
|
bedrock_agentcore_starter_toolkit/operations/runtime/invoke.py,sha256=49bfVSGICisXlOiqtFc6vUfd24z3ibQxPPeZy1QMoWw,6764
|
|
45
|
-
bedrock_agentcore_starter_toolkit/operations/runtime/launch.py,sha256=
|
|
46
|
+
bedrock_agentcore_starter_toolkit/operations/runtime/launch.py,sha256=TL-EkrVPhrwqbC2yf9MwhibOogpGKov7IAdZWq2c7s4,29252
|
|
46
47
|
bedrock_agentcore_starter_toolkit/operations/runtime/models.py,sha256=TdUS-O1crCGmigKb_N3WaLBeubsuFiUczyZktzcAHjY,4894
|
|
47
48
|
bedrock_agentcore_starter_toolkit/operations/runtime/status.py,sha256=4lK-zp29rZhdEJpOoRKqRAjXpEGEMdsb-MBTQQHoJiM,5267
|
|
48
49
|
bedrock_agentcore_starter_toolkit/services/__init__.py,sha256=s7QtYYFCCX2ff0gZHUdDxCDI3zhUq0fPsjevZbF9xdA,66
|
|
49
|
-
bedrock_agentcore_starter_toolkit/services/codebuild.py,sha256
|
|
50
|
+
bedrock_agentcore_starter_toolkit/services/codebuild.py,sha256=uFumFMHE8eZU6pDM8LoUku5AezKFCDqRZ4FiOB5Be4U,15861
|
|
50
51
|
bedrock_agentcore_starter_toolkit/services/ecr.py,sha256=nW9wIZcXI6amZeLVSmM9F6awVBQP1-zrFXTozSNEDjo,2805
|
|
51
52
|
bedrock_agentcore_starter_toolkit/services/runtime.py,sha256=lqBB-4uJuxNKbnPHpRskQ7bajiZ2MpjnbqPnKnvTinY,22408
|
|
52
53
|
bedrock_agentcore_starter_toolkit/services/xray.py,sha256=CRlcfVXpghVy7PvZqLUC4rp49Sw5DQ98rUU61HAluRM,6363
|
|
@@ -62,19 +63,19 @@ bedrock_agentcore_starter_toolkit/services/import_agent/scripts/bedrock_to_langc
|
|
|
62
63
|
bedrock_agentcore_starter_toolkit/services/import_agent/scripts/bedrock_to_strands.py,sha256=eC3v2Ts7B_RUGl4bkUim2uFYYuZZYP9syYBlylJ2gXs,14642
|
|
63
64
|
bedrock_agentcore_starter_toolkit/utils/endpoints.py,sha256=1gIDRd1oO1fymYpiedVit7m6zl5k6N8Ns9N-2ix7ZaE,1153
|
|
64
65
|
bedrock_agentcore_starter_toolkit/utils/logging_config.py,sha256=NtZDyndNKCAbz7jZ0leb13bb3UmjjRUTSVwI8MMlOfw,2191
|
|
65
|
-
bedrock_agentcore_starter_toolkit/utils/runtime/config.py,sha256=
|
|
66
|
-
bedrock_agentcore_starter_toolkit/utils/runtime/container.py,sha256=
|
|
66
|
+
bedrock_agentcore_starter_toolkit/utils/runtime/config.py,sha256=ujl_3CNXv2VY48tLkYF7VjemnIrKulmHZ-t2OH3Wmzg,6398
|
|
67
|
+
bedrock_agentcore_starter_toolkit/utils/runtime/container.py,sha256=7r3qCVetkm2Dtmn8BnW31J_Fo5FYj1beMaG0yj2Ap-A,18293
|
|
67
68
|
bedrock_agentcore_starter_toolkit/utils/runtime/entrypoint.py,sha256=d-XjEwvQOdpRHvBGLdIBCs1fgUwNwB0EL_WkcdQXwXQ,5893
|
|
68
69
|
bedrock_agentcore_starter_toolkit/utils/runtime/logs.py,sha256=ZZ9PD4QO0BSms5KphhUb3-6-IPTkmwkY-Zn2AWM9Aew,1601
|
|
69
70
|
bedrock_agentcore_starter_toolkit/utils/runtime/policy_template.py,sha256=CgER7YXPh0BpR6JcTcumDL_k8bhmfLSEok1sf09-31I,2054
|
|
70
|
-
bedrock_agentcore_starter_toolkit/utils/runtime/schema.py,sha256=
|
|
71
|
-
bedrock_agentcore_starter_toolkit/utils/runtime/templates/Dockerfile.j2,sha256=
|
|
72
|
-
bedrock_agentcore_starter_toolkit/utils/runtime/templates/dockerignore.template,sha256=
|
|
71
|
+
bedrock_agentcore_starter_toolkit/utils/runtime/schema.py,sha256=tF-shNJhIqiycA_uab2c7G3XYqq3mUkfdXGXixdtfOk,10420
|
|
72
|
+
bedrock_agentcore_starter_toolkit/utils/runtime/templates/Dockerfile.j2,sha256=TUHfWCcuiHw5la-4fWDOmoZDIaY3v6GtKm4fLiqfIE0,1630
|
|
73
|
+
bedrock_agentcore_starter_toolkit/utils/runtime/templates/dockerignore.template,sha256=IDKPnAiCdMLjuvLdItzQiybCW--SEvHAN2yr-B5Mxj4,711
|
|
73
74
|
bedrock_agentcore_starter_toolkit/utils/runtime/templates/execution_role_policy.json.j2,sha256=hsYLCgaWMfXuwva90yb1DVEO_HUkIjHHNcPKb60E18k,6180
|
|
74
75
|
bedrock_agentcore_starter_toolkit/utils/runtime/templates/execution_role_trust_policy.json.j2,sha256=PPJF6Ofq70W5DUE0NlbmnZjw5RkgepPgkskxEgEG28o,473
|
|
75
|
-
bedrock_agentcore_starter_toolkit-0.1.
|
|
76
|
-
bedrock_agentcore_starter_toolkit-0.1.
|
|
77
|
-
bedrock_agentcore_starter_toolkit-0.1.
|
|
78
|
-
bedrock_agentcore_starter_toolkit-0.1.
|
|
79
|
-
bedrock_agentcore_starter_toolkit-0.1.
|
|
80
|
-
bedrock_agentcore_starter_toolkit-0.1.
|
|
76
|
+
bedrock_agentcore_starter_toolkit-0.1.22.dist-info/METADATA,sha256=4B6BcF1-rXyst3vfu9Wm7F8j8dbPZByY94_GbZjCoZQ,9999
|
|
77
|
+
bedrock_agentcore_starter_toolkit-0.1.22.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
78
|
+
bedrock_agentcore_starter_toolkit-0.1.22.dist-info/entry_points.txt,sha256=Tf94DkUf2Tp8P7p8MEXLxre7A7Pp_XNukteiz0wHnk8,77
|
|
79
|
+
bedrock_agentcore_starter_toolkit-0.1.22.dist-info/licenses/LICENSE.txt,sha256=nNPOMinitYdtfbhdQgsPgz1UowBznU6QVN3Xs0pSTKU,10768
|
|
80
|
+
bedrock_agentcore_starter_toolkit-0.1.22.dist-info/licenses/NOTICE.txt,sha256=rkBsg8DbKqfIoQbveqX9foR4uJPUVAokbkr02pRPilE,8674
|
|
81
|
+
bedrock_agentcore_starter_toolkit-0.1.22.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|