serverless-bedrock-agentcore-plugin 0.1.0
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.
- package/CHANGELOG.md +52 -0
- package/LICENSE +21 -0
- package/README.md +476 -0
- package/package.json +96 -0
- package/src/compilers/browser.js +110 -0
- package/src/compilers/codeInterpreter.js +64 -0
- package/src/compilers/gateway.js +98 -0
- package/src/compilers/gatewayTarget.js +285 -0
- package/src/compilers/index.js +15 -0
- package/src/compilers/memory.js +168 -0
- package/src/compilers/runtime.js +234 -0
- package/src/compilers/runtimeEndpoint.js +37 -0
- package/src/compilers/workloadIdentity.js +36 -0
- package/src/docker/builder.js +236 -0
- package/src/iam/policies.js +591 -0
- package/src/index.js +1354 -0
- package/src/utils/index.js +9 -0
- package/src/utils/naming.js +79 -0
- package/src/utils/tags.js +56 -0
- package/src/validators/schema.js +250 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generate a resource name following the pattern: {service}-{name}-{stage}
|
|
5
|
+
*
|
|
6
|
+
* @param {string} serviceName - The Serverless service name
|
|
7
|
+
* @param {string} name - The agent/resource name
|
|
8
|
+
* @param {string} stage - The deployment stage
|
|
9
|
+
* @returns {string} The generated resource name
|
|
10
|
+
*/
|
|
11
|
+
function getResourceName(serviceName, name, stage) {
|
|
12
|
+
// AgentCore names have pattern: [a-zA-Z][a-zA-Z0-9_]{0,47}
|
|
13
|
+
// Replace hyphens with underscores and ensure it starts with a letter
|
|
14
|
+
const baseName = `${serviceName}_${name}_${stage}`
|
|
15
|
+
.replace(/-/g, '_')
|
|
16
|
+
.replace(/[^a-zA-Z0-9_]/g, '');
|
|
17
|
+
|
|
18
|
+
// Ensure it starts with a letter
|
|
19
|
+
const safeName = /^[a-zA-Z]/.test(baseName) ? baseName : `A${baseName}`;
|
|
20
|
+
|
|
21
|
+
// Truncate to max 48 characters
|
|
22
|
+
return safeName.substring(0, 48);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Generate a CloudFormation logical ID from the agent name and resource type
|
|
27
|
+
*
|
|
28
|
+
* @param {string} name - The agent name
|
|
29
|
+
* @param {string} resourceType - The resource type (e.g., 'Runtime', 'Memory')
|
|
30
|
+
* @returns {string} The CloudFormation logical ID
|
|
31
|
+
*/
|
|
32
|
+
function getLogicalId(name, resourceType) {
|
|
33
|
+
// Convert to PascalCase and remove invalid characters
|
|
34
|
+
const pascalName = name
|
|
35
|
+
.split(/[-_]/)
|
|
36
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
|
37
|
+
.join('');
|
|
38
|
+
|
|
39
|
+
return `${pascalName}${resourceType}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Generate a CloudFormation logical ID for nested resources
|
|
44
|
+
*
|
|
45
|
+
* @param {string} parentName - The parent resource name
|
|
46
|
+
* @param {string} childName - The child resource name
|
|
47
|
+
* @param {string} resourceType - The resource type
|
|
48
|
+
* @returns {string} The CloudFormation logical ID
|
|
49
|
+
*/
|
|
50
|
+
function getNestedLogicalId(parentName, childName, resourceType) {
|
|
51
|
+
const pascalParent = parentName
|
|
52
|
+
.split(/[-_]/)
|
|
53
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
|
54
|
+
.join('');
|
|
55
|
+
|
|
56
|
+
const pascalChild = childName
|
|
57
|
+
.split(/[-_]/)
|
|
58
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
|
59
|
+
.join('');
|
|
60
|
+
|
|
61
|
+
return `${pascalParent}${pascalChild}${resourceType}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Sanitize a name for use in CloudFormation
|
|
66
|
+
*
|
|
67
|
+
* @param {string} name - The name to sanitize
|
|
68
|
+
* @returns {string} The sanitized name
|
|
69
|
+
*/
|
|
70
|
+
function sanitizeName(name) {
|
|
71
|
+
return name.replace(/[^a-zA-Z0-9]/g, '');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = {
|
|
75
|
+
getResourceName,
|
|
76
|
+
getLogicalId,
|
|
77
|
+
getNestedLogicalId,
|
|
78
|
+
sanitizeName,
|
|
79
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Merge tags from multiple sources with proper precedence
|
|
5
|
+
*
|
|
6
|
+
* @param {Object} defaultTags - Default tags from custom.agentCore.defaultTags
|
|
7
|
+
* @param {Object} resourceTags - Tags specific to the resource
|
|
8
|
+
* @param {string} serviceName - The Serverless service name
|
|
9
|
+
* @param {string} stage - The deployment stage
|
|
10
|
+
* @param {string} resourceName - The resource name
|
|
11
|
+
* @returns {Object} Merged tags object for CloudFormation
|
|
12
|
+
*/
|
|
13
|
+
function mergeTags(defaultTags = {}, resourceTags = {}, serviceName, stage, resourceName) {
|
|
14
|
+
const tags = {
|
|
15
|
+
...defaultTags,
|
|
16
|
+
...resourceTags,
|
|
17
|
+
'serverless:service': serviceName,
|
|
18
|
+
'serverless:stage': stage,
|
|
19
|
+
'agentcore:resource': resourceName,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return tags;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Convert tags object to CloudFormation Tags array format
|
|
27
|
+
*
|
|
28
|
+
* @param {Object} tags - Tags object with key-value pairs
|
|
29
|
+
* @returns {Array} Array of {Key, Value} objects for CloudFormation
|
|
30
|
+
*/
|
|
31
|
+
function tagsToCloudFormationArray(tags) {
|
|
32
|
+
return Object.entries(tags).map(([Key, Value]) => ({
|
|
33
|
+
Key,
|
|
34
|
+
Value: String(Value),
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Convert CloudFormation Tags array to object format
|
|
40
|
+
*
|
|
41
|
+
* @param {Array} tagsArray - Array of {Key, Value} objects
|
|
42
|
+
* @returns {Object} Tags object with key-value pairs
|
|
43
|
+
*/
|
|
44
|
+
function cloudFormationArrayToTags(tagsArray) {
|
|
45
|
+
return tagsArray.reduce((acc, { Key, Value }) => {
|
|
46
|
+
acc[Key] = Value;
|
|
47
|
+
|
|
48
|
+
return acc;
|
|
49
|
+
}, {});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = {
|
|
53
|
+
mergeTags,
|
|
54
|
+
tagsToCloudFormationArray,
|
|
55
|
+
cloudFormationArrayToTags,
|
|
56
|
+
};
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Define JSON Schema validation for the 'agents' top-level configuration
|
|
5
|
+
*
|
|
6
|
+
* @param {Object} serverless - The Serverless instance
|
|
7
|
+
*/
|
|
8
|
+
function defineAgentsSchema(serverless) {
|
|
9
|
+
// Define the 'agents' top-level property
|
|
10
|
+
serverless.configSchemaHandler.defineTopLevelProperty('agents', {
|
|
11
|
+
type: 'object',
|
|
12
|
+
additionalProperties: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
type: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
enum: ['runtime', 'memory', 'gateway', 'browser', 'codeInterpreter', 'workloadIdentity'],
|
|
18
|
+
},
|
|
19
|
+
description: {
|
|
20
|
+
type: 'string',
|
|
21
|
+
minLength: 1,
|
|
22
|
+
maxLength: 1200,
|
|
23
|
+
},
|
|
24
|
+
tags: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
additionalProperties: { type: 'string' },
|
|
27
|
+
},
|
|
28
|
+
roleArn: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
pattern: '^arn:aws(-[^:]+)?:iam::([0-9]{12})?:role/.+$',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
// Runtime-specific properties
|
|
34
|
+
artifact: {
|
|
35
|
+
type: 'object',
|
|
36
|
+
properties: {
|
|
37
|
+
containerImage: { type: 'string' },
|
|
38
|
+
s3: {
|
|
39
|
+
type: 'object',
|
|
40
|
+
properties: {
|
|
41
|
+
bucket: { type: 'string' },
|
|
42
|
+
key: { type: 'string' },
|
|
43
|
+
},
|
|
44
|
+
required: ['bucket', 'key'],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
protocol: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
enum: ['HTTP', 'MCP', 'A2A'],
|
|
51
|
+
},
|
|
52
|
+
environment: {
|
|
53
|
+
type: 'object',
|
|
54
|
+
additionalProperties: { type: 'string' },
|
|
55
|
+
},
|
|
56
|
+
network: {
|
|
57
|
+
type: 'object',
|
|
58
|
+
properties: {
|
|
59
|
+
networkMode: {
|
|
60
|
+
type: 'string',
|
|
61
|
+
enum: ['PUBLIC', 'VPC'],
|
|
62
|
+
},
|
|
63
|
+
vpcConfig: {
|
|
64
|
+
type: 'object',
|
|
65
|
+
properties: {
|
|
66
|
+
subnetIds: {
|
|
67
|
+
type: 'array',
|
|
68
|
+
items: { type: 'string' },
|
|
69
|
+
},
|
|
70
|
+
securityGroupIds: {
|
|
71
|
+
type: 'array',
|
|
72
|
+
items: { type: 'string' },
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
authorizer: {
|
|
79
|
+
type: 'object',
|
|
80
|
+
properties: {
|
|
81
|
+
type: {
|
|
82
|
+
type: 'string',
|
|
83
|
+
enum: ['CUSTOM_JWT', 'AWS_IAM', 'NONE'],
|
|
84
|
+
},
|
|
85
|
+
jwtConfiguration: {
|
|
86
|
+
type: 'object',
|
|
87
|
+
properties: {
|
|
88
|
+
issuer: { type: 'string' },
|
|
89
|
+
audience: {
|
|
90
|
+
type: 'array',
|
|
91
|
+
items: { type: 'string' },
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
lifecycle: {
|
|
98
|
+
type: 'object',
|
|
99
|
+
properties: {
|
|
100
|
+
idleTimeout: { type: 'number' },
|
|
101
|
+
maxConcurrency: { type: 'number' },
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
endpoints: {
|
|
105
|
+
type: 'array',
|
|
106
|
+
items: {
|
|
107
|
+
type: 'object',
|
|
108
|
+
properties: {
|
|
109
|
+
name: { type: 'string' },
|
|
110
|
+
version: { type: 'string' },
|
|
111
|
+
description: { type: 'string' },
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
// Memory-specific properties
|
|
117
|
+
eventExpiryDuration: {
|
|
118
|
+
type: 'number',
|
|
119
|
+
minimum: 7,
|
|
120
|
+
maximum: 365,
|
|
121
|
+
},
|
|
122
|
+
encryptionKeyArn: {
|
|
123
|
+
type: 'string',
|
|
124
|
+
},
|
|
125
|
+
strategies: {
|
|
126
|
+
type: 'array',
|
|
127
|
+
items: {
|
|
128
|
+
type: 'object',
|
|
129
|
+
properties: {
|
|
130
|
+
type: {
|
|
131
|
+
type: 'string',
|
|
132
|
+
enum: ['semantic', 'userPreference', 'summary', 'custom'],
|
|
133
|
+
},
|
|
134
|
+
name: { type: 'string' },
|
|
135
|
+
namespaces: {
|
|
136
|
+
type: 'array',
|
|
137
|
+
items: { type: 'string' },
|
|
138
|
+
},
|
|
139
|
+
configuration: {
|
|
140
|
+
type: 'object',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
required: ['type', 'name'],
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
// Gateway-specific properties
|
|
148
|
+
authorizerType: {
|
|
149
|
+
type: 'string',
|
|
150
|
+
enum: ['AWS_IAM', 'CUSTOM_JWT'],
|
|
151
|
+
},
|
|
152
|
+
protocolType: {
|
|
153
|
+
type: 'string',
|
|
154
|
+
enum: ['MCP'],
|
|
155
|
+
},
|
|
156
|
+
authorizerConfiguration: {
|
|
157
|
+
type: 'object',
|
|
158
|
+
properties: {
|
|
159
|
+
allowedAudiences: {
|
|
160
|
+
type: 'array',
|
|
161
|
+
items: { type: 'string' },
|
|
162
|
+
},
|
|
163
|
+
allowedClients: {
|
|
164
|
+
type: 'array',
|
|
165
|
+
items: { type: 'string' },
|
|
166
|
+
},
|
|
167
|
+
allowedIssuers: {
|
|
168
|
+
type: 'array',
|
|
169
|
+
items: { type: 'string' },
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
kmsKeyArn: {
|
|
174
|
+
type: 'string',
|
|
175
|
+
},
|
|
176
|
+
targets: {
|
|
177
|
+
type: 'array',
|
|
178
|
+
items: {
|
|
179
|
+
type: 'object',
|
|
180
|
+
properties: {
|
|
181
|
+
name: { type: 'string' },
|
|
182
|
+
type: {
|
|
183
|
+
type: 'string',
|
|
184
|
+
enum: ['openapi', 'lambda', 'smithy'],
|
|
185
|
+
},
|
|
186
|
+
description: { type: 'string' },
|
|
187
|
+
functionArn: { type: 'string' },
|
|
188
|
+
functionName: { type: 'string' },
|
|
189
|
+
s3: {
|
|
190
|
+
type: 'object',
|
|
191
|
+
properties: {
|
|
192
|
+
bucket: { type: 'string' },
|
|
193
|
+
key: { type: 'string' },
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
credentialProvider: {
|
|
197
|
+
type: 'object',
|
|
198
|
+
properties: {
|
|
199
|
+
type: {
|
|
200
|
+
type: 'string',
|
|
201
|
+
enum: ['GATEWAY_IAM_ROLE', 'OAUTH', 'API_KEY'],
|
|
202
|
+
},
|
|
203
|
+
oauthConfig: {
|
|
204
|
+
type: 'object',
|
|
205
|
+
properties: {
|
|
206
|
+
secretArn: { type: 'string' },
|
|
207
|
+
tokenUrl: { type: 'string' },
|
|
208
|
+
scopes: {
|
|
209
|
+
type: 'array',
|
|
210
|
+
items: { type: 'string' },
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
apiKeyConfig: {
|
|
215
|
+
type: 'object',
|
|
216
|
+
properties: {
|
|
217
|
+
secretArn: { type: 'string' },
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
required: ['name'],
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
required: ['type'],
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Define custom.agentCore configuration
|
|
232
|
+
serverless.configSchemaHandler.defineCustomProperties({
|
|
233
|
+
type: 'object',
|
|
234
|
+
properties: {
|
|
235
|
+
agentCore: {
|
|
236
|
+
type: 'object',
|
|
237
|
+
properties: {
|
|
238
|
+
defaultTags: {
|
|
239
|
+
type: 'object',
|
|
240
|
+
additionalProperties: { type: 'string' },
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
module.exports = {
|
|
249
|
+
defineAgentsSchema,
|
|
250
|
+
};
|