awslabs.cdk-mcp-server 0.0.10417__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.
- awslabs/__init__.py +2 -0
- awslabs/cdk_mcp_server/__init__.py +8 -0
- awslabs/cdk_mcp_server/core/__init__.py +1 -0
- awslabs/cdk_mcp_server/core/resources.py +271 -0
- awslabs/cdk_mcp_server/core/search_utils.py +182 -0
- awslabs/cdk_mcp_server/core/server.py +74 -0
- awslabs/cdk_mcp_server/core/tools.py +324 -0
- awslabs/cdk_mcp_server/data/__init__.py +1 -0
- awslabs/cdk_mcp_server/data/cdk_nag_parser.py +331 -0
- awslabs/cdk_mcp_server/data/construct_descriptions.py +32 -0
- awslabs/cdk_mcp_server/data/genai_cdk_loader.py +423 -0
- awslabs/cdk_mcp_server/data/lambda_powertools_loader.py +48 -0
- awslabs/cdk_mcp_server/data/schema_generator.py +666 -0
- awslabs/cdk_mcp_server/data/solutions_constructs_parser.py +782 -0
- awslabs/cdk_mcp_server/server.py +7 -0
- awslabs/cdk_mcp_server/static/CDK_GENERAL_GUIDANCE.md +232 -0
- awslabs/cdk_mcp_server/static/CDK_NAG_GUIDANCE.md +192 -0
- awslabs/cdk_mcp_server/static/__init__.py +5 -0
- awslabs/cdk_mcp_server/static/bedrock/agent/actiongroups.md +137 -0
- awslabs/cdk_mcp_server/static/bedrock/agent/alias.md +39 -0
- awslabs/cdk_mcp_server/static/bedrock/agent/collaboration.md +91 -0
- awslabs/cdk_mcp_server/static/bedrock/agent/creation.md +149 -0
- awslabs/cdk_mcp_server/static/bedrock/agent/custom_orchestration.md +74 -0
- awslabs/cdk_mcp_server/static/bedrock/agent/overview.md +78 -0
- awslabs/cdk_mcp_server/static/bedrock/agent/prompt_override.md +70 -0
- awslabs/cdk_mcp_server/static/bedrock/bedrockguardrails.md +188 -0
- awslabs/cdk_mcp_server/static/bedrock/knowledgebases/chunking.md +137 -0
- awslabs/cdk_mcp_server/static/bedrock/knowledgebases/datasources.md +225 -0
- awslabs/cdk_mcp_server/static/bedrock/knowledgebases/kendra.md +81 -0
- awslabs/cdk_mcp_server/static/bedrock/knowledgebases/overview.md +116 -0
- awslabs/cdk_mcp_server/static/bedrock/knowledgebases/parsing.md +36 -0
- awslabs/cdk_mcp_server/static/bedrock/knowledgebases/transformation.md +30 -0
- awslabs/cdk_mcp_server/static/bedrock/knowledgebases/vector/aurora.md +185 -0
- awslabs/cdk_mcp_server/static/bedrock/knowledgebases/vector/creation.md +80 -0
- awslabs/cdk_mcp_server/static/bedrock/knowledgebases/vector/opensearch.md +56 -0
- awslabs/cdk_mcp_server/static/bedrock/knowledgebases/vector/pinecone.md +66 -0
- awslabs/cdk_mcp_server/static/bedrock/profiles.md +153 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/actiongroups.md +137 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/alias.md +39 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/collaboration.md +91 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/creation.md +149 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/custom_orchestration.md +74 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/overview.md +78 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/prompt_override.md +70 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/bedrockguardrails.md +188 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/chunking.md +137 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/datasources.md +225 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/kendra.md +81 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/overview.md +116 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/parsing.md +36 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/transformation.md +30 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/vector/aurora.md +185 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/vector/creation.md +80 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/vector/opensearch.md +56 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/vector/pinecone.md +66 -0
- awslabs/cdk_mcp_server/static/genai_cdk/bedrock/profiles.md +153 -0
- awslabs/cdk_mcp_server/static/genai_cdk/opensearch-vectorindex/overview.md +135 -0
- awslabs/cdk_mcp_server/static/genai_cdk/opensearchserverless/overview.md +17 -0
- awslabs/cdk_mcp_server/static/lambda_powertools/bedrock.md +127 -0
- awslabs/cdk_mcp_server/static/lambda_powertools/cdk.md +99 -0
- awslabs/cdk_mcp_server/static/lambda_powertools/dependencies.md +45 -0
- awslabs/cdk_mcp_server/static/lambda_powertools/index.md +36 -0
- awslabs/cdk_mcp_server/static/lambda_powertools/insights.md +95 -0
- awslabs/cdk_mcp_server/static/lambda_powertools/logging.md +43 -0
- awslabs/cdk_mcp_server/static/lambda_powertools/metrics.md +93 -0
- awslabs/cdk_mcp_server/static/lambda_powertools/tracing.md +63 -0
- awslabs/cdk_mcp_server/static/opensearch-vectorindex/overview.md +135 -0
- awslabs/cdk_mcp_server/static/opensearchserverless/overview.md +17 -0
- awslabs_cdk_mcp_server-0.0.10417.dist-info/METADATA +14 -0
- awslabs_cdk_mcp_server-0.0.10417.dist-info/RECORD +72 -0
- awslabs_cdk_mcp_server-0.0.10417.dist-info/WHEEL +4 -0
- awslabs_cdk_mcp_server-0.0.10417.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
"""GenAI CDK constructs static content loader."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
from awslabs.cdk_mcp_server.data.construct_descriptions import get_construct_descriptions
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from typing import Any, Dict, List, Optional
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# Set up logging
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ConstructType(str, Enum):
|
|
15
|
+
"""GenAI CDK construct types."""
|
|
16
|
+
|
|
17
|
+
BEDROCK = 'bedrock'
|
|
18
|
+
OPENSEARCH_SERVERLESS = 'opensearchserverless'
|
|
19
|
+
OPENSEARCH_VECTOR_INDEX = 'opensearch-vectorindex'
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_construct_types() -> List[str]:
|
|
23
|
+
"""Get a list of available construct types."""
|
|
24
|
+
return [ct.value for ct in ConstructType]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_construct_map() -> Dict[str, str]:
|
|
28
|
+
"""Get a dictionary mapping construct types to their descriptions."""
|
|
29
|
+
return {
|
|
30
|
+
'bedrock': 'Amazon Bedrock constructs for agents, knowledge bases, and more',
|
|
31
|
+
'opensearchserverless': 'Amazon OpenSearch Serverless constructs for vector search',
|
|
32
|
+
'opensearch-vectorindex': 'Amazon OpenSearch vector index constructs',
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_genai_cdk_overview(construct_type: str = '') -> str:
|
|
37
|
+
"""Get an overview of GenAI CDK constructs.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
construct_type: Optional construct type to get overview for.
|
|
41
|
+
If empty, returns the best practices.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
The overview content as a string.
|
|
45
|
+
"""
|
|
46
|
+
# Normalize construct type
|
|
47
|
+
construct_type = construct_type.lower()
|
|
48
|
+
|
|
49
|
+
# Validate construct type
|
|
50
|
+
if construct_type not in get_construct_types():
|
|
51
|
+
construct_list = '\n'.join([f'- {t}: {desc}' for t, desc in get_construct_map().items()])
|
|
52
|
+
return f"# GenAI CDK Constructs\n\nConstruct type '{construct_type}' not found. Available types:\n\n{construct_list}"
|
|
53
|
+
|
|
54
|
+
# Get overview file
|
|
55
|
+
file_path = os.path.join(
|
|
56
|
+
os.path.dirname(os.path.dirname(__file__)), # Fix path to use parent directory
|
|
57
|
+
'static',
|
|
58
|
+
'genai_cdk',
|
|
59
|
+
construct_type,
|
|
60
|
+
'overview.md',
|
|
61
|
+
)
|
|
62
|
+
try:
|
|
63
|
+
with open(file_path, 'r') as f:
|
|
64
|
+
return f.read()
|
|
65
|
+
except FileNotFoundError:
|
|
66
|
+
return f"Error: Overview file for '{construct_type}' not found."
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def list_available_sections(construct_type: str, construct_name: str) -> List[str]:
|
|
70
|
+
"""List available sections for a specific construct.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
construct_type: The construct type (e.g., 'bedrock')
|
|
74
|
+
construct_name: The name of the construct (e.g., 'agent', 'knowledgebases')
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
List of available sections.
|
|
78
|
+
"""
|
|
79
|
+
sections = []
|
|
80
|
+
base_path = os.path.join(
|
|
81
|
+
os.path.dirname(os.path.dirname(__file__)), # Fix path to use parent directory
|
|
82
|
+
'static',
|
|
83
|
+
'genai_cdk',
|
|
84
|
+
construct_type,
|
|
85
|
+
construct_name,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
if not os.path.exists(base_path):
|
|
89
|
+
return sections
|
|
90
|
+
|
|
91
|
+
# Walk through the directory structure
|
|
92
|
+
for root, dirs, files in os.walk(base_path):
|
|
93
|
+
rel_path = os.path.relpath(root, base_path)
|
|
94
|
+
|
|
95
|
+
for file in files:
|
|
96
|
+
if file.endswith('.md') and file != 'overview.md':
|
|
97
|
+
section_name = file[:-3] # Remove .md extension
|
|
98
|
+
|
|
99
|
+
# For files in the base directory
|
|
100
|
+
if rel_path == '.':
|
|
101
|
+
sections.append(section_name)
|
|
102
|
+
else:
|
|
103
|
+
# For files in subdirectories
|
|
104
|
+
if rel_path != '.':
|
|
105
|
+
section_path = os.path.join(rel_path, section_name)
|
|
106
|
+
# Replace backslashes with forward slashes for consistency
|
|
107
|
+
section_path = section_path.replace('\\', '/')
|
|
108
|
+
sections.append(section_path)
|
|
109
|
+
|
|
110
|
+
return sections
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def get_genai_cdk_construct_section(construct_type: str, construct_name: str, section: str) -> str:
|
|
114
|
+
"""Get a specific section of documentation for a GenAI CDK construct.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
construct_type: The construct type (e.g., 'bedrock')
|
|
118
|
+
construct_name: The name of the construct (e.g., 'agent', 'knowledgebases')
|
|
119
|
+
section: The section name (e.g., 'actiongroups', 'vector/opensearch')
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
The section documentation as a string.
|
|
123
|
+
"""
|
|
124
|
+
# Normalize inputs
|
|
125
|
+
construct_type = construct_type.lower()
|
|
126
|
+
construct_name_lower = construct_name.lower()
|
|
127
|
+
|
|
128
|
+
# Special handling for Agent_* and Knowledgebases_* constructs
|
|
129
|
+
if construct_name_lower.startswith('agent_'):
|
|
130
|
+
# Convert Agent_actiongroups to agent/actiongroups
|
|
131
|
+
construct_name_lower = 'agent'
|
|
132
|
+
section = construct_name_lower.split('_', 1)[1]
|
|
133
|
+
elif construct_name_lower.startswith('knowledgebases_'):
|
|
134
|
+
# Convert Knowledgebases_vector_opensearch to knowledgebases/vector/opensearch
|
|
135
|
+
parts = construct_name_lower.split('_', 1)
|
|
136
|
+
if len(parts) > 1:
|
|
137
|
+
construct_name_lower = parts[0]
|
|
138
|
+
# Handle nested paths with underscores (e.g., vector_opensearch -> vector/opensearch)
|
|
139
|
+
section_parts = parts[1].split('_')
|
|
140
|
+
if len(section_parts) > 1 and section_parts[0] == 'vector':
|
|
141
|
+
# Special case for vector/* sections which are in a nested directory
|
|
142
|
+
section = f'vector/{section_parts[1]}'
|
|
143
|
+
else:
|
|
144
|
+
section = parts[1]
|
|
145
|
+
|
|
146
|
+
# Validate construct type
|
|
147
|
+
if construct_type not in get_construct_types():
|
|
148
|
+
return f"Error: Construct type '{construct_type}' not found."
|
|
149
|
+
|
|
150
|
+
# Handle nested sections (e.g., vector/opensearch)
|
|
151
|
+
if '/' in section:
|
|
152
|
+
section_parts = section.split('/')
|
|
153
|
+
file_path = (
|
|
154
|
+
os.path.join(
|
|
155
|
+
os.path.dirname(os.path.dirname(__file__)), # Fix path to use parent directory
|
|
156
|
+
'static',
|
|
157
|
+
'genai_cdk',
|
|
158
|
+
construct_type,
|
|
159
|
+
construct_name_lower,
|
|
160
|
+
*section_parts,
|
|
161
|
+
)
|
|
162
|
+
+ '.md'
|
|
163
|
+
)
|
|
164
|
+
else:
|
|
165
|
+
# Regular section
|
|
166
|
+
file_path = os.path.join(
|
|
167
|
+
os.path.dirname(os.path.dirname(__file__)), # Fix path to use parent directory
|
|
168
|
+
'static',
|
|
169
|
+
'genai_cdk',
|
|
170
|
+
construct_type,
|
|
171
|
+
construct_name_lower,
|
|
172
|
+
f'{section}.md',
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
try:
|
|
176
|
+
with open(file_path, 'r') as f:
|
|
177
|
+
return f.read()
|
|
178
|
+
except FileNotFoundError:
|
|
179
|
+
return (
|
|
180
|
+
f"Error: Section '{section}' for '{construct_name}' in '{construct_type}' not found."
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def get_genai_cdk_construct(construct_type: str, construct_name: str) -> str:
|
|
185
|
+
"""Get documentation for a specific GenAI CDK construct.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
construct_type: The construct type (e.g., 'bedrock')
|
|
189
|
+
construct_name: The name of the construct (e.g., 'Agent')
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
The construct documentation as a string.
|
|
193
|
+
"""
|
|
194
|
+
# Normalize inputs
|
|
195
|
+
construct_type = construct_type.lower()
|
|
196
|
+
construct_name_lower = construct_name.lower()
|
|
197
|
+
|
|
198
|
+
# Special handling for Agent_* and Knowledgebases_* constructs
|
|
199
|
+
if construct_name_lower.startswith('agent_'):
|
|
200
|
+
# For Agent_actiongroups, redirect to agent/actiongroups section
|
|
201
|
+
parent = 'agent'
|
|
202
|
+
child = construct_name_lower.split('_', 1)[1]
|
|
203
|
+
return get_genai_cdk_construct_section(construct_type, parent, child)
|
|
204
|
+
elif construct_name_lower.startswith('knowledgebases_'):
|
|
205
|
+
# For Knowledgebases_vector_opensearch, redirect to knowledgebases/vector/opensearch section
|
|
206
|
+
parts = construct_name_lower.split('_', 1)
|
|
207
|
+
if len(parts) > 1:
|
|
208
|
+
parent = parts[0]
|
|
209
|
+
# Handle nested paths with underscores (e.g., vector_opensearch -> vector/opensearch)
|
|
210
|
+
section_parts = parts[1].split('_')
|
|
211
|
+
if len(section_parts) > 1 and section_parts[0] == 'vector':
|
|
212
|
+
# Special case for vector/* sections which are in a nested directory
|
|
213
|
+
child = f'vector/{section_parts[1]}'
|
|
214
|
+
else:
|
|
215
|
+
child = parts[1]
|
|
216
|
+
return get_genai_cdk_construct_section(construct_type, parent, child)
|
|
217
|
+
|
|
218
|
+
# Special handling for agent and knowledgebases
|
|
219
|
+
if construct_name_lower in ['agent', 'knowledgebases']:
|
|
220
|
+
# For these special cases, return an overview or index of available sections
|
|
221
|
+
base_path = os.path.join(
|
|
222
|
+
os.path.dirname(os.path.dirname(__file__)), # Fix path to use parent directory
|
|
223
|
+
'static',
|
|
224
|
+
'genai_cdk',
|
|
225
|
+
construct_type,
|
|
226
|
+
construct_name_lower,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
# Check if directory exists
|
|
230
|
+
if not os.path.exists(base_path):
|
|
231
|
+
return f"Error: Documentation for '{construct_name}' in '{construct_type}' not found."
|
|
232
|
+
|
|
233
|
+
# List files in directory
|
|
234
|
+
sections = []
|
|
235
|
+
for file_name in os.listdir(base_path):
|
|
236
|
+
if file_name.endswith('.md') and file_name != 'overview.md':
|
|
237
|
+
sections.append(file_name[:-3]) # Remove .md extension
|
|
238
|
+
|
|
239
|
+
# Also check subdirectories
|
|
240
|
+
for root, dirs, files in os.walk(base_path):
|
|
241
|
+
if root != base_path: # Skip the base directory
|
|
242
|
+
rel_path = os.path.relpath(root, base_path)
|
|
243
|
+
for file_name in files:
|
|
244
|
+
if file_name.endswith('.md'):
|
|
245
|
+
section_path = os.path.join(rel_path, file_name[:-3])
|
|
246
|
+
section_path = section_path.replace('\\', '/')
|
|
247
|
+
sections.append(section_path)
|
|
248
|
+
|
|
249
|
+
result = f'# {construct_name.capitalize()} Documentation\n\n'
|
|
250
|
+
result += 'This documentation is split into sections for easier consumption.\n\n'
|
|
251
|
+
result += '## Available Sections\n\n'
|
|
252
|
+
|
|
253
|
+
for section in sorted(sections):
|
|
254
|
+
result += f'- [{section}](genai-cdk-constructs://{construct_type}/{construct_name_lower}/{section})\n'
|
|
255
|
+
|
|
256
|
+
return result
|
|
257
|
+
|
|
258
|
+
# Special handling for key constructs
|
|
259
|
+
key_construct_mapping = {
|
|
260
|
+
'agent': 'agent',
|
|
261
|
+
'agents': 'agent',
|
|
262
|
+
'knowledgebase': 'knowledgebases',
|
|
263
|
+
'knowledgebases': 'knowledgebases',
|
|
264
|
+
'knowledge-base': 'knowledgebases',
|
|
265
|
+
'knowledge-bases': 'knowledgebases',
|
|
266
|
+
'agentactiongroup': 'agent/actiongroups',
|
|
267
|
+
'action-group': 'agent/actiongroups',
|
|
268
|
+
'actiongroup': 'agent/actiongroups',
|
|
269
|
+
'agentalias': 'agent/alias',
|
|
270
|
+
'guardrail': 'bedrockguardrails',
|
|
271
|
+
'guardrails': 'bedrockguardrails',
|
|
272
|
+
'bedrock-guardrails': 'bedrockguardrails',
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
# Normalize construct name
|
|
276
|
+
if construct_name_lower in key_construct_mapping:
|
|
277
|
+
mapped_name = key_construct_mapping[construct_name_lower]
|
|
278
|
+
if '/' in mapped_name:
|
|
279
|
+
# Handle redirects to sections
|
|
280
|
+
parent, section = mapped_name.split('/', 1)
|
|
281
|
+
return get_genai_cdk_construct_section(construct_type, parent, section)
|
|
282
|
+
else:
|
|
283
|
+
construct_name_lower = mapped_name
|
|
284
|
+
|
|
285
|
+
# Validate construct type
|
|
286
|
+
if construct_type not in get_construct_types():
|
|
287
|
+
construct_list = '\n'.join([f'- {t}: {desc}' for t, desc in get_construct_map().items()])
|
|
288
|
+
return f"# GenAI CDK Constructs\n\nConstruct type '{construct_type}' not found. Available types:\n\n{construct_list}"
|
|
289
|
+
|
|
290
|
+
# Get construct file (flat structure)
|
|
291
|
+
file_path = os.path.join(
|
|
292
|
+
os.path.dirname(os.path.dirname(__file__)), # Fix path to use parent directory
|
|
293
|
+
'static',
|
|
294
|
+
'genai_cdk',
|
|
295
|
+
construct_type,
|
|
296
|
+
f'{construct_name_lower}.md',
|
|
297
|
+
)
|
|
298
|
+
try:
|
|
299
|
+
with open(file_path, 'r') as f:
|
|
300
|
+
return f.read()
|
|
301
|
+
except FileNotFoundError:
|
|
302
|
+
# Try to see if this is a directory with an overview.md file
|
|
303
|
+
overview_path = os.path.join(
|
|
304
|
+
os.path.dirname(os.path.dirname(__file__)),
|
|
305
|
+
'static',
|
|
306
|
+
'genai_cdk',
|
|
307
|
+
construct_type,
|
|
308
|
+
construct_name_lower,
|
|
309
|
+
'overview.md',
|
|
310
|
+
)
|
|
311
|
+
try:
|
|
312
|
+
with open(overview_path, 'r') as f:
|
|
313
|
+
return f.read()
|
|
314
|
+
except FileNotFoundError:
|
|
315
|
+
return f"Error: Documentation for '{construct_name}' in '{construct_type}' not found."
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def list_available_constructs(construct_type: Optional[str] = None) -> List[Dict[str, Any]]:
|
|
319
|
+
"""List available constructs.
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
construct_type: Optional construct type to filter by.
|
|
323
|
+
|
|
324
|
+
Returns:
|
|
325
|
+
List of constructs with name, type, and description.
|
|
326
|
+
"""
|
|
327
|
+
constructs = []
|
|
328
|
+
|
|
329
|
+
# Determine which construct types to search
|
|
330
|
+
if construct_type is not None:
|
|
331
|
+
construct_types = [construct_type.lower()]
|
|
332
|
+
else:
|
|
333
|
+
construct_types = get_construct_types()
|
|
334
|
+
|
|
335
|
+
# For each construct type, list files in the directory
|
|
336
|
+
for ct in construct_types:
|
|
337
|
+
if ct not in get_construct_types():
|
|
338
|
+
continue
|
|
339
|
+
|
|
340
|
+
# Get directory path - fix path to use parent directory
|
|
341
|
+
dir_path = os.path.join(
|
|
342
|
+
os.path.dirname(os.path.dirname(__file__)), 'static', 'genai_cdk', ct
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
# Skip if directory doesn't exist
|
|
346
|
+
if not os.path.exists(dir_path):
|
|
347
|
+
continue
|
|
348
|
+
|
|
349
|
+
# Process files in the main directory
|
|
350
|
+
process_directory_files(dir_path, ct, constructs)
|
|
351
|
+
|
|
352
|
+
# Process subdirectories recursively
|
|
353
|
+
for root, dirs, files in os.walk(dir_path):
|
|
354
|
+
# Skip the main directory as it's already processed
|
|
355
|
+
if root == dir_path:
|
|
356
|
+
continue
|
|
357
|
+
|
|
358
|
+
# Get the relative path from the main directory
|
|
359
|
+
rel_path = os.path.relpath(root, dir_path)
|
|
360
|
+
# Use the relative path as the parent
|
|
361
|
+
process_directory_files(root, ct, constructs, parent=rel_path.replace(os.sep, '_'))
|
|
362
|
+
|
|
363
|
+
return constructs
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def process_directory_files(
|
|
367
|
+
dir_path: str, construct_type: str, constructs: List[Dict[str, Any]], parent: Optional[str] = None
|
|
368
|
+
):
|
|
369
|
+
"""Process files in a directory and add them to the constructs list.
|
|
370
|
+
|
|
371
|
+
Args:
|
|
372
|
+
dir_path: Path to the directory
|
|
373
|
+
construct_type: Type of construct
|
|
374
|
+
constructs: List to add constructs to
|
|
375
|
+
parent: Optional parent directory name
|
|
376
|
+
"""
|
|
377
|
+
# List files in directory
|
|
378
|
+
for file_name in os.listdir(dir_path):
|
|
379
|
+
# Skip overview file, directories, and non-markdown files
|
|
380
|
+
if (
|
|
381
|
+
file_name == 'overview.md'
|
|
382
|
+
or not file_name.endswith('.md')
|
|
383
|
+
or os.path.isdir(os.path.join(dir_path, file_name))
|
|
384
|
+
):
|
|
385
|
+
continue
|
|
386
|
+
|
|
387
|
+
# Extract construct name from file name
|
|
388
|
+
base_name = file_name[:-3]
|
|
389
|
+
|
|
390
|
+
# Format the construct name
|
|
391
|
+
if parent:
|
|
392
|
+
construct_name = f'{parent}_{base_name}'
|
|
393
|
+
else:
|
|
394
|
+
construct_name = base_name
|
|
395
|
+
|
|
396
|
+
display_name = construct_name.capitalize()
|
|
397
|
+
|
|
398
|
+
# Define file_path here, before it's used
|
|
399
|
+
file_path = os.path.join(dir_path, file_name)
|
|
400
|
+
|
|
401
|
+
# Get description from fixed mapping or use default
|
|
402
|
+
descriptions = get_construct_descriptions()
|
|
403
|
+
description = descriptions.get(display_name, "")
|
|
404
|
+
|
|
405
|
+
# If no fixed description, fall back to current behavior
|
|
406
|
+
if not description:
|
|
407
|
+
try:
|
|
408
|
+
with open(file_path, 'r') as f:
|
|
409
|
+
first_line = f.readline().strip()
|
|
410
|
+
description = (
|
|
411
|
+
first_line[1:].strip() if first_line.startswith('#') else display_name
|
|
412
|
+
)
|
|
413
|
+
except Exception:
|
|
414
|
+
description = f'A {construct_type} construct.'
|
|
415
|
+
|
|
416
|
+
# Add to list
|
|
417
|
+
constructs.append(
|
|
418
|
+
{
|
|
419
|
+
'name': display_name,
|
|
420
|
+
'type': construct_type,
|
|
421
|
+
'description': description,
|
|
422
|
+
}
|
|
423
|
+
)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Lambda Powertools guidance loader module."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from typing import Dict
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_topic_map() -> Dict[str, str]:
|
|
8
|
+
"""Get a dictionary mapping topic names to their descriptions."""
|
|
9
|
+
return {
|
|
10
|
+
'index': 'Overview and table of contents',
|
|
11
|
+
'logging': 'Structured logging implementation',
|
|
12
|
+
'tracing': 'Tracing implementation',
|
|
13
|
+
'metrics': 'Metrics implementation',
|
|
14
|
+
'cdk': 'CDK integration patterns',
|
|
15
|
+
'dependencies': 'Dependencies management',
|
|
16
|
+
'insights': 'Lambda Insights integration',
|
|
17
|
+
'bedrock': 'Bedrock Agent integration',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_lambda_powertools_section(topic: str = '') -> str:
|
|
22
|
+
"""Get a specific section of the Lambda Powertools guidance.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
topic: The topic to get guidance on. If empty or "index", returns the index.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
The guidance for the specified topic
|
|
29
|
+
"""
|
|
30
|
+
topic_map = get_topic_map()
|
|
31
|
+
|
|
32
|
+
# Handle the index case
|
|
33
|
+
if not topic or topic.lower() == 'index':
|
|
34
|
+
topic = 'index'
|
|
35
|
+
|
|
36
|
+
if topic.lower() in topic_map:
|
|
37
|
+
file_path = os.path.join(
|
|
38
|
+
os.path.dirname(__file__), 'static', 'lambda_powertools', f'{topic.lower()}.md'
|
|
39
|
+
)
|
|
40
|
+
try:
|
|
41
|
+
with open(file_path, 'r') as f:
|
|
42
|
+
return f.read()
|
|
43
|
+
except FileNotFoundError:
|
|
44
|
+
return f"Error: File for topic '{topic}' not found."
|
|
45
|
+
else:
|
|
46
|
+
# Topic not found
|
|
47
|
+
topic_list = '\n'.join([f'- {t}: {desc}' for t, desc in topic_map.items() if t != 'index'])
|
|
48
|
+
return f"# Lambda Powertools Guidance\n\nTopic '{topic}' not found. Available topics:\n\n{topic_list}"
|