diff --git a/.oxlintrc.json b/.oxlintrc.json index 9e4fb5c8b3..0514430039 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -13,7 +13,7 @@ } ] }, - "ignorePatterns": ["dist/", "node_modules/", "src/assets/"], + "ignorePatterns": ["dist/", "node_modules/", "src/assets/", "src/projectSchemas/v0/"], "overrides": [ { "files": ["scripts/**", "src/testing/**", "**/*.test.*", "**/*-test-support.ts"], diff --git a/.prettierignore b/.prettierignore index d328428463..20cc24571b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -13,3 +13,6 @@ __fixtures__ *.snap src/assets + +# Frozen copy of the v0 0.31.1 schemas; kept byte-identical to upstream. +src/projectSchemas/v0 diff --git a/src/core/project/backends/cdk.test.ts b/src/core/project/backends/cdk.test.ts index 695d856c28..385e21bd19 100644 --- a/src/core/project/backends/cdk.test.ts +++ b/src/core/project/backends/cdk.test.ts @@ -21,6 +21,8 @@ import type { DeployBackendInput } from "./types"; import type { ResolvedProjectResource } from "../../../handlers/project/types"; import type { BootstrapState } from "./cdk/environment"; import type { CdkCredentialProvider, CdkOperation, CdkOutputs, CdkRunOptions } from "./cdk/toolkit"; +import { v0Fixture } from "../legacy/fixtures-test-support"; +import { translateV0Spec } from "../legacy/translate"; const TARGET = { name: "default", @@ -1329,4 +1331,75 @@ describe("CdkBackend.resolveProjectResources", () => { ]), ).toEqual([["gateway", "gw", ["owned", "second"]]]); }); + + test("resolves v0-only resources from legacy extras and deployed state", async () => { + const input = await project(); + const v0Spec = v0Fixture("baseline.json"); + v0Spec.datasets = v0Fixture("top-datasets-nonempty.json").datasets; + v0Spec.abTests = v0Fixture("top-abTests-nonempty.json").abTests; + v0Spec.capacityProviders = v0Fixture("runtime-capacityProvider.json").capacityProviders; + v0Spec.unassignedTargets = v0Fixture("top-unassignedTargets.json").unassignedTargets; + const translated = translateV0Spec(v0Spec); + input.spec = translated.spec; + input.legacy = { format: "v0", v0Spec, extras: translated.extras }; + await updateTargetState(json, input.rootPath, TARGET.name, { + stackArn: STACK_ARN, + resources: { + datasets: { + ds1: { datasetId: "dataset-1", datasetArn: "arn:dataset/dataset-1" }, + }, + abTests: { + ab1: { abTestId: "ab-test-1", abTestArn: "arn:ab-test/ab-test-1" }, + }, + capacityProviders: { + cp1: { + capacityProviderId: "cp1-AbCdEf1234", + capacityProviderArn: "arn:capacity-provider/cp1-AbCdEf1234", + }, + }, + }, + }); + const subject = harness({ + describedStack: { + StackName: S, + CreationTime: new Date(0), + StackStatus: "CREATE_COMPLETE", + Outputs: [out(`${S}-GatewayTarget-u1-Id`, "must-not-match-an-unassigned-target")], + }, + }); + + const resources = await subject.backend.resolveProjectResources(input, { target: TARGET }); + + expect( + resources.filter(({ resourceType, name }) => + ["dataset:ds1", "ab-test:ab1", "capacity-provider:cp1", "gateway-target:u1"].includes( + `${resourceType}:${name}`, + ), + ), + ).toEqual([ + { + resourceType: "dataset", + name: "ds1", + deploymentState: "deployed", + arn: "arn:dataset/dataset-1", + }, + { + resourceType: "ab-test", + name: "ab1", + deploymentState: "deployed", + arn: "arn:ab-test/ab-test-1", + }, + { + resourceType: "capacity-provider", + name: "cp1", + deploymentState: "deployed", + arn: "arn:capacity-provider/cp1-AbCdEf1234", + }, + { + resourceType: "gateway-target", + name: "u1", + deploymentState: "local-only", + }, + ]); + }); }); diff --git a/src/core/project/backends/cdk.ts b/src/core/project/backends/cdk.ts index 28f4636751..92d751552a 100644 --- a/src/core/project/backends/cdk.ts +++ b/src/core/project/backends/cdk.ts @@ -102,6 +102,15 @@ function cdkId(name: string): string { return name.replace(/_/g, ""); } +function stringAt(value: unknown, ...path: string[]): string | undefined { + let current = value; + for (const part of path) { + if (typeof current !== "object" || current === null || !(part in current)) return undefined; + current = (current as Record)[part]; + } + return typeof current === "string" ? current : undefined; +} + function findDeployedResourceId( stack: Stack, input: Pick, @@ -584,6 +593,14 @@ export class CdkBackend implements ProjectBackend { return asArn(byExportName("PolicyEngine", name, "Arn")); case "config-bundle": return asArn(byExportName("ConfigBundle", name, "Arn")); + case "dataset": + return asArn(stringAt(recorded?.resources, "datasets", name, "datasetArn")); + case "ab-test": + return asArn(stringAt(recorded?.resources, "abTests", name, "abTestArn")); + case "capacity-provider": + return asArn( + stringAt(recorded?.resources, "capacityProviders", name, "capacityProviderArn"), + ); case "payment-manager": // @aws/agentcore-cdk's AgentCorePayments construct writes the payment // outputs at stack scope without an exportName, under keys built from @@ -615,9 +632,15 @@ export class CdkBackend implements ProjectBackend { const resolve = ( resourceType: DeployableResource, name: string, - options: { owner?: string; children?: ResolvedProjectResource[] } = {}, + options: { + owner?: string; + children?: ResolvedProjectResource[]; + forceLocalOnly?: boolean; + } = {}, ): ResolvedProjectResource => { - const identifier = identifierOf(resourceType, name, options.owner); + const identifier = options.forceLocalOnly + ? undefined + : identifierOf(resourceType, name, options.owner); return { resourceType, name, @@ -657,6 +680,14 @@ export class CdkBackend implements ProjectBackend { }), ), ...spec.configBundles.map(({ name }) => resolve("config-bundle", name)), + ...(project.legacy?.extras.datasets ?? []).map(({ name }) => resolve("dataset", name)), + ...(project.legacy?.extras.abTests ?? []).map(({ name }) => resolve("ab-test", name)), + ...(project.legacy?.extras.capacityProviders ?? []).map(({ name }) => + resolve("capacity-provider", name), + ), + ...(project.legacy?.extras.unassignedTargets ?? []).map(({ name }) => + resolve("gateway-target", name, { forceLocalOnly: true }), + ), ...(spec.payments ?? []).map((manager) => resolve("payment-manager", manager.name, { children: (manager.connectors ?? []).map(({ name }) => diff --git a/src/core/project/legacy/__fixtures__/aws-targets_case-dup.json b/src/core/project/legacy/__fixtures__/aws-targets_case-dup.json new file mode 100644 index 0000000000..83af4cad77 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/aws-targets_case-dup.json @@ -0,0 +1,12 @@ +[ + { + "name": "Prod", + "account": "123456789012", + "region": "us-east-1" + }, + { + "name": "prod", + "account": "123456789012", + "region": "us-west-2" + } +] \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/aws-targets_cn-region.json b/src/core/project/legacy/__fixtures__/aws-targets_cn-region.json new file mode 100644 index 0000000000..a8484df9b5 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/aws-targets_cn-region.json @@ -0,0 +1,7 @@ +[ + { + "name": "cn", + "account": "123456789012", + "region": "cn-north-1" + } +] \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/aws-targets_default.json b/src/core/project/legacy/__fixtures__/aws-targets_default.json new file mode 100644 index 0000000000..e390b91170 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/aws-targets_default.json @@ -0,0 +1,7 @@ +[ + { + "name": "default", + "account": "123456789012", + "region": "us-east-1" + } +] \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/aws-targets_extra-key.json b/src/core/project/legacy/__fixtures__/aws-targets_extra-key.json new file mode 100644 index 0000000000..e0d79039f6 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/aws-targets_extra-key.json @@ -0,0 +1,8 @@ +[ + { + "name": "default", + "account": "123456789012", + "region": "us-east-1", + "profile": "x" + } +] \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/aws-targets_hyphen-name.json b/src/core/project/legacy/__fixtures__/aws-targets_hyphen-name.json new file mode 100644 index 0000000000..ed8cc4766d --- /dev/null +++ b/src/core/project/legacy/__fixtures__/aws-targets_hyphen-name.json @@ -0,0 +1,8 @@ +[ + { + "name": "prod-us", + "account": "123456789012", + "region": "us-east-1", + "description": "d" + } +] \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/baseline.json b/src/core/project/legacy/__fixtures__/baseline.json new file mode 100644 index 0000000000..83d3b68440 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/baseline.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/configbundle-branch-leading-digit.json b/src/core/project/legacy/__fixtures__/configbundle-branch-leading-digit.json new file mode 100644 index 0000000000..3826f886eb --- /dev/null +++ b/src/core/project/legacy/__fixtures__/configbundle-branch-leading-digit.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "2024-q1", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/configbundle-branch-with-dot.json b/src/core/project/legacy/__fixtures__/configbundle-branch-with-dot.json new file mode 100644 index 0000000000..b4f94b1cbc --- /dev/null +++ b/src/core/project/legacy/__fixtures__/configbundle-branch-with-dot.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "release-1.0", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/credential-env-collision.json b/src/core/project/legacy/__fixtures__/credential-env-collision.json new file mode 100644 index 0000000000..ae51fd79cf --- /dev/null +++ b/src/core/project/legacy/__fixtures__/credential-env-collision.json @@ -0,0 +1,822 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "svc", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration" + }, + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "svc_client_secret" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/credential-hyphen-underscore-collision.json b/src/core/project/legacy/__fixtures__/credential-hyphen-underscore-collision.json new file mode 100644 index 0000000000..b737ffa18e --- /dev/null +++ b/src/core/project/legacy/__fixtures__/credential-hyphen-underscore-collision.json @@ -0,0 +1,821 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + }, + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "my-key" + }, + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "my_key" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/credential-name-1-char.json b/src/core/project/legacy/__fixtures__/credential-name-1-char.json new file mode 100644 index 0000000000..f1796d0001 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/credential-name-1-char.json @@ -0,0 +1,817 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + }, + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "k" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/credential-name-2-chars.json b/src/core/project/legacy/__fixtures__/credential-name-2-chars.json new file mode 100644 index 0000000000..902f812211 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/credential-name-2-chars.json @@ -0,0 +1,817 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + }, + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "ab" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/credential-oauth-no-discoveryUrl_import_.json b/src/core/project/legacy/__fixtures__/credential-oauth-no-discoveryUrl_import_.json new file mode 100644 index 0000000000..eeeef6734a --- /dev/null +++ b/src/core/project/legacy/__fixtures__/credential-oauth-no-discoveryUrl_import_.json @@ -0,0 +1,818 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "imported-oauth", + "vendor": "CustomOauth2" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/credential-oauth-vendor-non-custom-no-url.json b/src/core/project/legacy/__fixtures__/credential-oauth-vendor-non-custom-no-url.json new file mode 100644 index 0000000000..ebd39db019 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/credential-oauth-vendor-non-custom-no-url.json @@ -0,0 +1,818 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "github", + "vendor": "GithubOauth2" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/credential-oauth-vendor-non-custom.json b/src/core/project/legacy/__fixtures__/credential-oauth-vendor-non-custom.json new file mode 100644 index 0000000000..9d1b82cc61 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/credential-oauth-vendor-non-custom.json @@ -0,0 +1,819 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "google", + "vendor": "GoogleOauth2", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/evaluator-model-whitespace.json b/src/core/project/legacy/__fixtures__/evaluator-model-whitespace.json new file mode 100644 index 0000000000..8c11ea1ffa --- /dev/null +++ b/src/core/project/legacy/__fixtures__/evaluator-model-whitespace.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": " us.anthropic.claude-x-v1:0 ", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/gateway-target-apigw-empty-toolDefinitions.json b/src/core/project/legacy/__fixtures__/gateway-target-apigw-empty-toolDefinitions.json new file mode 100644 index 0000000000..0ff97f2d42 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/gateway-target-apigw-empty-toolDefinitions.json @@ -0,0 +1,814 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + }, + "toolDefinitions": [] + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/gateway-target-connector-outboundAuth-NONE.json b/src/core/project/legacy/__fixtures__/gateway-target-connector-outboundAuth-NONE.json new file mode 100644 index 0000000000..576f25af59 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/gateway-target-connector-outboundAuth-NONE.json @@ -0,0 +1,816 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search", + "outboundAuth": { + "type": "NONE" + } + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/gateway-target-httpRuntime-with-schemaSource.json b/src/core/project/legacy/__fixtures__/gateway-target-httpRuntime-with-schemaSource.json new file mode 100644 index 0000000000..896a070b46 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/gateway-target-httpRuntime-with-schemaSource.json @@ -0,0 +1,818 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + }, + "schemaSource": { + "inline": { + "path": "x.json" + } + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/gateway-target-lambda-with-endpoint.json b/src/core/project/legacy/__fixtures__/gateway-target-lambda-with-endpoint.json new file mode 100644 index 0000000000..7a845fc826 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/gateway-target-lambda-with-endpoint.json @@ -0,0 +1,814 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + }, + "endpoint": "https://x.example.com" + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/gateway-target-mcpServer-agentcoreRuntime-compute-no-runtime.json b/src/core/project/legacy/__fixtures__/gateway-target-mcpServer-agentcoreRuntime-compute-no-runtime.json new file mode 100644 index 0000000000..af2649910c --- /dev/null +++ b/src/core/project/legacy/__fixtures__/gateway-target-mcpServer-agentcoreRuntime-compute-no-runtime.json @@ -0,0 +1,825 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + }, + { + "name": "mcpRt2", + "targetType": "mcpServer", + "compute": { + "host": "AgentCoreRuntime", + "implementation": { + "language": "Python", + "path": "tools/rt", + "handler": "server.py:app" + } + } + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/gateway-target-mcpServer-agentcoreRuntime-compute.json b/src/core/project/legacy/__fixtures__/gateway-target-mcpServer-agentcoreRuntime-compute.json new file mode 100644 index 0000000000..02a5d95196 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/gateway-target-mcpServer-agentcoreRuntime-compute.json @@ -0,0 +1,841 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + }, + { + "name": "mcpRt", + "targetType": "mcpServer", + "toolDefinitions": [ + { + "name": "t3", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "AgentCoreRuntime", + "implementation": { + "language": "Python", + "path": "tools/rt", + "handler": "server.py:app" + }, + "runtime": { + "artifact": "CodeZip", + "pythonVersion": "PYTHON_3_12", + "name": "rtToolRuntime", + "entrypoint": "server.py:app", + "codeLocation": "tools/rt" + } + } + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/gateway-target-mcpServer-empty-configurations.json b/src/core/project/legacy/__fixtures__/gateway-target-mcpServer-empty-configurations.json new file mode 100644 index 0000000000..8bf2f59784 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/gateway-target-mcpServer-empty-configurations.json @@ -0,0 +1,814 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + }, + "configurations": [] + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/gateway-target-mcpServer-with-passthrough.json b/src/core/project/legacy/__fixtures__/gateway-target-mcpServer-with-passthrough.json new file mode 100644 index 0000000000..d4123ff7c0 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/gateway-target-mcpServer-with-passthrough.json @@ -0,0 +1,816 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + }, + "passthrough": { + "endpoint": "https://a.example.com" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/gateway-target-openapi-with-httpRuntime.json b/src/core/project/legacy/__fixtures__/gateway-target-openapi-with-httpRuntime.json new file mode 100644 index 0000000000..14f1631873 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/gateway-target-openapi-with-httpRuntime.json @@ -0,0 +1,816 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + }, + "httpRuntime": { + "runtime": "agentA" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/gateway-target-smithy-outboundAuth-NONE.json b/src/core/project/legacy/__fixtures__/gateway-target-smithy-outboundAuth-NONE.json new file mode 100644 index 0000000000..4e59b2baef --- /dev/null +++ b/src/core/project/legacy/__fixtures__/gateway-target-smithy-outboundAuth-NONE.json @@ -0,0 +1,816 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + }, + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/invalid_evaluator-model-3000-chars.json b/src/core/project/legacy/__fixtures__/invalid_evaluator-model-3000-chars.json new file mode 100644 index 0000000000..11f901a8a4 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/invalid_evaluator-model-3000-chars.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/invalid_memory-namespaces-and-templates-both.json b/src/core/project/legacy/__fixtures__/invalid_memory-namespaces-and-templates-both.json new file mode 100644 index 0000000000..5fd86eeff0 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/invalid_memory-namespaces-and-templates-both.json @@ -0,0 +1,816 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ], + "namespaceTemplates": [ + "/s/{actorId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/invalid_top-mcpRuntimeTools-renamed-to-toolRuntimes.json b/src/core/project/legacy/__fixtures__/invalid_top-mcpRuntimeTools-renamed-to-toolRuntimes.json new file mode 100644 index 0000000000..2d8282c544 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/invalid_top-mcpRuntimeTools-renamed-to-toolRuntimes.json @@ -0,0 +1,846 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [], + "toolRuntimes": [ + { + "name": "rtTool", + "toolDefinition": { + "name": "rt-tool", + "description": "d", + "inputSchema": { + "type": "object" + } + }, + "compute": { + "host": "AgentCoreRuntime", + "implementation": { + "language": "Python", + "path": "tools/rt", + "handler": "server.py:app" + }, + "runtime": { + "artifact": "CodeZip", + "pythonVersion": "PYTHON_3_12", + "name": "rtToolRuntime", + "entrypoint": "server.py:app", + "codeLocation": "tools/rt" + } + }, + "bindings": [ + { + "runtimeName": "agentA", + "envVarName": "RT_TOOL_URL" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/kb-gateway-unknown.json b/src/core/project/legacy/__fixtures__/kb-gateway-unknown.json new file mode 100644 index 0000000000..e5984c6546 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/kb-gateway-unknown.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "nope" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/memory-unknown-key.json b/src/core/project/legacy/__fixtures__/memory-unknown-key.json new file mode 100644 index 0000000000..d13c14b94c --- /dev/null +++ b/src/core/project/legacy/__fixtures__/memory-unknown-key.json @@ -0,0 +1,814 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + }, + "foo": 1 + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/online-eval-11-evaluators.json b/src/core/project/legacy/__fixtures__/online-eval-11-evaluators.json new file mode 100644 index 0000000000..7bd7187401 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/online-eval-11-evaluators.json @@ -0,0 +1,821 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "Builtin.E0", + "Builtin.E1", + "Builtin.E2", + "Builtin.E3", + "Builtin.E4", + "Builtin.E5", + "Builtin.E6", + "Builtin.E7", + "Builtin.E8", + "Builtin.E9", + "Builtin.E10" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/payment-connector-provider-mismatch.json b/src/core/project/legacy/__fixtures__/payment-connector-provider-mismatch.json new file mode 100644 index 0000000000..a815aa2ae4 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/payment-connector-provider-mismatch.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "coinbaseCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/payment-description-punctuation.json b/src/core/project/legacy/__fixtures__/payment-description-punctuation.json new file mode 100644 index 0000000000..7ad5a03c24 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/payment-description-punctuation.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payments for prod - v2.", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/payment-duplicate-connector-names.json b/src/core/project/legacy/__fixtures__/payment-duplicate-connector-names.json new file mode 100644 index 0000000000..6c87b936cf --- /dev/null +++ b/src/core/project/legacy/__fixtures__/payment-duplicate-connector-names.json @@ -0,0 +1,818 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + }, + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "credentialName": "coinbaseCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/payment-jwt-discovery-not-wellknown.json b/src/core/project/legacy/__fixtures__/payment-jwt-discovery-not-wellknown.json new file mode 100644 index 0000000000..0c8f214e56 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/payment-jwt-discovery-not-wellknown.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/oauth2", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/payment-jwt-empty-arrays.json b/src/core/project/legacy/__fixtures__/payment-jwt-empty-arrays.json new file mode 100644 index 0000000000..98e10b6b9e --- /dev/null +++ b/src/core/project/legacy/__fixtures__/payment-jwt-empty-arrays.json @@ -0,0 +1,811 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/payment-jwt-scope-with-space.json b/src/core/project/legacy/__fixtures__/payment-jwt-scope-with-space.json new file mode 100644 index 0000000000..3d45ac1fdf --- /dev/null +++ b/src/core/project/legacy/__fixtures__/payment-jwt-scope-with-space.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "read write" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/payment-manager-case-collision.json b/src/core/project/legacy/__fixtures__/payment-manager-case-collision.json new file mode 100644 index 0000000000..7e02131fdb --- /dev/null +++ b/src/core/project/legacy/__fixtures__/payment-manager-case-collision.json @@ -0,0 +1,816 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + }, + { + "name": "PM1" + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/payment-spendlimit-empty.json b/src/core/project/legacy/__fixtures__/payment-spendlimit-empty.json new file mode 100644 index 0000000000..c59e3431cc --- /dev/null +++ b/src/core/project/legacy/__fixtures__/payment-spendlimit-empty.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/payment-spendlimit-nonnumeric.json b/src/core/project/legacy/__fixtures__/payment-spendlimit-nonnumeric.json new file mode 100644 index 0000000000..b7cb0a6103 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/payment-spendlimit-nonnumeric.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "ten dollars", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/payments-absent.json b/src/core/project/legacy/__fixtures__/payments-absent.json new file mode 100644 index 0000000000..22dcf811c6 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/payments-absent.json @@ -0,0 +1,762 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/project-name-crewai.json b/src/core/project/legacy/__fixtures__/project-name-crewai.json new file mode 100644 index 0000000000..c65c6d5ee4 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/project-name-crewai.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "crewai", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/project-name-tiktoken.json b/src/core/project/legacy/__fixtures__/project-name-tiktoken.json new file mode 100644 index 0000000000..bb6b92a483 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/project-name-tiktoken.json @@ -0,0 +1,813 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "tiktoken", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/runtime-capacityProvider.json b/src/core/project/legacy/__fixtures__/runtime-capacityProvider.json new file mode 100644 index 0000000000..3f4627da60 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/runtime-capacityProvider.json @@ -0,0 +1,850 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM", + "capacityProviderConfiguration": { + "capacityProviderName": "cp1" + } + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [ + { + "name": "cp1", + "computeConfiguration": { + "ec2Configuration": { + "launchTemplateSource": { + "launchParameters": { + "operatingSystem": "LINUX_X86_64", + "instanceRequirements": { + "allowedInstanceTypes": [ + "m5.large" + ] + } + } + }, + "vpcConfiguration": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ] + }, + "volumes": [ + { + "ebsConfiguration": { + "name": "vol1", + "sizeGiB": 20 + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/runtime-capacityProviderArn-only.json b/src/core/project/legacy/__fixtures__/runtime-capacityProviderArn-only.json new file mode 100644 index 0000000000..d1bc6cebc2 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/runtime-capacityProviderArn-only.json @@ -0,0 +1,816 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM", + "capacityProviderConfiguration": { + "capacityProviderArn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:capacity-provider/cp1-abcdefghij" + } + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/runtime-capacityProviderVolume-mount.json b/src/core/project/legacy/__fixtures__/runtime-capacityProviderVolume-mount.json new file mode 100644 index 0000000000..4af537fd98 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/runtime-capacityProviderVolume-mount.json @@ -0,0 +1,858 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM", + "capacityProviderConfiguration": { + "capacityProviderName": "cp1" + }, + "filesystemConfigurations": [ + { + "capacityProviderVolume": { + "volumeName": "vol1", + "mountPath": "/mnt/models" + } + } + ] + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [ + { + "name": "cp1", + "computeConfiguration": { + "ec2Configuration": { + "launchTemplateSource": { + "launchParameters": { + "operatingSystem": "LINUX_X86_64", + "instanceRequirements": { + "allowedInstanceTypes": [ + "m5.large" + ] + } + } + }, + "vpcConfiguration": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ] + }, + "volumes": [ + { + "ebsConfiguration": { + "name": "vol1", + "sizeGiB": 20 + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/runtime-codezip-no-runtimeVersion.json b/src/core/project/legacy/__fixtures__/runtime-codezip-no-runtimeVersion.json new file mode 100644 index 0000000000..6f5c5561ef --- /dev/null +++ b/src/core/project/legacy/__fixtures__/runtime-codezip-no-runtimeVersion.json @@ -0,0 +1,812 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/runtime-codezip-vpc-no-vpcId.json b/src/core/project/legacy/__fixtures__/runtime-codezip-vpc-no-vpcId.json new file mode 100644 index 0000000000..ab9e54644b --- /dev/null +++ b/src/core/project/legacy/__fixtures__/runtime-codezip-vpc-no-vpcId.json @@ -0,0 +1,812 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ] + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/runtime-container-vpc-no-vpcId.json b/src/core/project/legacy/__fixtures__/runtime-container-vpc-no-vpcId.json new file mode 100644 index 0000000000..efb71cb6c2 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/runtime-container-vpc-no-vpcId.json @@ -0,0 +1,822 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM", + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ] + } + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/runtime-unknown-key.json b/src/core/project/legacy/__fixtures__/runtime-unknown-key.json new file mode 100644 index 0000000000..4d08f4f7ea --- /dev/null +++ b/src/core/project/legacy/__fixtures__/runtime-unknown-key.json @@ -0,0 +1,814 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ], + "someFutureField": 1 + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/top-abTests-nonempty.json b/src/core/project/legacy/__fixtures__/top-abTests-nonempty.json new file mode 100644 index 0000000000..0e9cc1eb19 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/top-abTests-nonempty.json @@ -0,0 +1,843 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [ + { + "name": "ab1", + "gatewayRef": "{{gateway:gw1}}", + "variants": [ + { + "name": "C", + "weight": 50, + "variantConfiguration": { + "configurationBundle": { + "bundleArn": "arn:b", + "bundleVersion": "1" + } + } + }, + { + "name": "T1", + "weight": 50, + "variantConfiguration": { + "configurationBundle": { + "bundleArn": "arn:b", + "bundleVersion": "2" + } + } + } + ], + "evaluationConfig": { + "onlineEvaluationConfigArn": "arn:oe" + } + } + ], + "datasets": [], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/top-datasets-nonempty.json b/src/core/project/legacy/__fixtures__/top-datasets-nonempty.json new file mode 100644 index 0000000000..03b9ec6eaf --- /dev/null +++ b/src/core/project/legacy/__fixtures__/top-datasets-nonempty.json @@ -0,0 +1,823 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [ + { + "name": "ds1", + "schemaType": "AGENTCORE_EVALUATION_PREDEFINED_V1", + "config": { + "managed": { + "location": "d/x.jsonl" + } + } + } + ], + "capacityProviders": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/top-httpGateways-empty.json b/src/core/project/legacy/__fixtures__/top-httpGateways-empty.json new file mode 100644 index 0000000000..af4d387812 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/top-httpGateways-empty.json @@ -0,0 +1,814 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [], + "httpGateways": [] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/top-mcpRuntimeTools.json b/src/core/project/legacy/__fixtures__/top-mcpRuntimeTools.json new file mode 100644 index 0000000000..3f15514a5e --- /dev/null +++ b/src/core/project/legacy/__fixtures__/top-mcpRuntimeTools.json @@ -0,0 +1,846 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [], + "mcpRuntimeTools": [ + { + "name": "rtTool", + "toolDefinition": { + "name": "rt-tool", + "description": "d", + "inputSchema": { + "type": "object" + } + }, + "compute": { + "host": "AgentCoreRuntime", + "implementation": { + "language": "Python", + "path": "tools/rt", + "handler": "server.py:app" + }, + "runtime": { + "artifact": "CodeZip", + "pythonVersion": "PYTHON_3_12", + "name": "rtToolRuntime", + "entrypoint": "server.py:app", + "codeLocation": "tools/rt" + } + }, + "bindings": [ + { + "runtimeName": "agentA", + "envVarName": "RT_TOOL_URL" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/core/project/legacy/__fixtures__/top-unassignedTargets.json b/src/core/project/legacy/__fixtures__/top-unassignedTargets.json new file mode 100644 index 0000000000..4950f56ad5 --- /dev/null +++ b/src/core/project/legacy/__fixtures__/top-unassignedTargets.json @@ -0,0 +1,820 @@ +{ + "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json", + "name": "maxproj", + "version": 1, + "managedBy": "CDK", + "tags": { + "agentcore:created-by": "agentcore-cli", + "team": "x" + }, + "runtimes": [ + { + "name": "agentA", + "description": "A", + "build": "CodeZip", + "entrypoint": "main.py:app", + "codeLocation": "app/agentA", + "runtimeVersion": "PYTHON_3_13", + "envVars": [ + { + "name": "FOO", + "value": "bar" + } + ], + "networkMode": "VPC", + "networkConfig": { + "subnets": [ + "subnet-0123456789abcdef0" + ], + "securityGroups": [ + "sg-0123456789abcdef0" + ], + "vpcId": "vpc-0123456789abcdef0" + }, + "instrumentation": { + "enableOtel": false + }, + "protocol": "HTTP", + "requestHeaderAllowlist": [ + "X-Amzn-Bedrock-AgentCore-Runtime-Custom-Foo", + "Authorization" + ], + "executionRoleArn": "arn:aws:iam::123456789012:role/r", + "additionalPolicies": [ + "policies/extra.json" + ], + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": [ + "aud" + ], + "allowedClients": [ + "cli" + ], + "allowedScopes": [ + "read" + ], + "customClaims": [ + { + "inboundTokenClaimName": "groups", + "inboundTokenClaimValueType": "STRING_ARRAY", + "authorizingClaimMatchValue": { + "claimMatchOperator": "CONTAINS_ANY", + "claimMatchValue": { + "matchValueStringList": [ + "admin" + ] + } + } + } + ], + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV4", + "securityGroupIds": [ + "sg-0123456789abcdef0" + ], + "tags": { + "a": "b" + }, + "routingDomain": "idp.example.com" + } + }, + "privateEndpointOverrides": [ + { + "domain": "other.example.com", + "privateEndpoint": { + "managedVpcResource": { + "vpcIdentifier": "vpc-0123456789abcdef0", + "subnetIds": [ + "subnet-0123456789abcdef0" + ], + "endpointIpAddressType": "IPV6" + } + } + } + ] + } + }, + "tags": { + "r": "1" + }, + "lifecycleConfiguration": { + "idleRuntimeSessionTimeout": 900, + "maxLifetime": 28800 + }, + "filesystemConfigurations": [ + { + "sessionStorage": { + "mountPath": "/mnt/data" + } + }, + { + "efsAccessPoint": { + "accessPointArn": "arn:aws:elasticfilesystem:us-east-1:123456789012:access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/efs" + } + }, + { + "s3FilesAccessPoint": { + "accessPointArn": "arn:aws:s3files:us-east-1:123456789012:file-system/fs-0123456789abcdef0/access-point/fsap-0123456789abcdef0", + "mountPath": "/mnt/s3" + } + } + ], + "endpoints": { + "prod": { + "version": 1, + "description": "p" + } + }, + "connections": [ + { + "id": "mem1", + "to": { + "type": "memory", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:memory/m-1", + "namespaces": [ + "/x" + ] + }, + "access": "read", + "description": "d" + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-1", + "outboundAuth": { + "oauth": { + "providerArn": "arn:p", + "scopes": [ + "s" + ], + "grantType": "CLIENT_CREDENTIALS", + "customParameters": { + "k": "v" + } + } + } + } + }, + { + "to": { + "type": "gateway", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/g-2", + "outboundAuth": { + "awsIam": {} + } + } + }, + { + "to": { + "type": "runtime", + "arn": "arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/r-1", + "exec": true + }, + "access": "readwrite" + }, + { + "to": { + "type": "browser", + "arn": "arn:aws:bedrock-agentcore:us-east-1:aws:browser/aws.browser.v1" + } + }, + { + "to": { + "type": "codeInterpreter" + } + } + ] + }, + { + "name": "agentB", + "build": "Container", + "entrypoint": "main.py", + "codeLocation": "app/agentB", + "dockerfile": "docker/Dockerfile", + "buildContextPath": "app", + "customDockerBuildArgs": { + "PIP_INDEX": "x" + }, + "protocol": "MCP", + "authorizerType": "AWS_IAM" + }, + { + "name": "agentC", + "build": "CodeZip", + "entrypoint": "index.ts", + "codeLocation": "app/agentC", + "runtimeVersion": "NODE_22", + "protocol": "A2A", + "networkMode": "PUBLIC" + }, + { + "name": "agentD", + "build": "CodeZip", + "entrypoint": "main.py", + "codeLocation": "app/agentD", + "runtimeVersion": "PYTHON_3_14", + "protocol": "AGUI" + } + ], + "memories": [ + { + "name": "mem1", + "eventExpiryDuration": 30, + "strategies": [ + { + "type": "SEMANTIC", + "name": "sem", + "description": "d", + "namespaceTemplates": [ + "/users/{actorId}/facts" + ] + }, + { + "type": "SUMMARIZATION", + "namespaces": [ + "/summaries/{actorId}/{sessionId}" + ] + }, + { + "type": "USER_PREFERENCE" + }, + { + "type": "EPISODIC", + "namespaces": [ + "/episodes/{actorId}/{sessionId}" + ], + "reflectionNamespaces": [ + "/episodes/{actorId}" + ] + } + ], + "indexedKeys": [ + { + "key": "topic", + "type": "STRING" + } + ], + "tags": { + "m": "1" + }, + "encryptionKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "executionRoleArn": "arn:aws:iam::123456789012:role/m", + "streamDeliveryResources": { + "resources": [ + { + "kinesis": { + "dataStreamArn": "arn:aws:kinesis:us-east-1:1:stream/s", + "contentConfigurations": [ + { + "type": "MEMORY_RECORDS", + "level": "FULL_CONTENT" + } + ] + } + } + ] + } + }, + { + "name": "mem2", + "eventExpiryDuration": 7 + } + ], + "knowledgeBases": [ + { + "type": "AgentCoreKnowledgeBase", + "name": "kb-docs", + "description": "kb", + "dataSources": [ + { + "type": "S3", + "uri": "s3://my-bucket/docs" + }, + { + "type": "CONFLUENCE", + "connectorConfigFile": "kb/confluence.json" + } + ], + "gateway": "gw1" + } + ], + "credentials": [ + { + "authorizerType": "ApiKeyCredentialProvider", + "name": "openaiKey" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "my-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": [ + "read" + ], + "vendor": "CustomOauth2", + "usage": "outbound" + }, + { + "authorizerType": "OAuthCredentialProvider", + "name": "gw1-oauth", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "vendor": "CustomOauth2", + "managed": true, + "usage": "inbound" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "coinbaseCred", + "provider": "CoinbaseCDP" + }, + { + "authorizerType": "PaymentCredentialProvider", + "name": "stripeCred", + "provider": "StripePrivy" + } + ], + "evaluators": [ + { + "name": "evalNum", + "level": "SESSION", + "description": "d", + "config": { + "llmAsAJudge": { + "modelProvider": "Bedrock", + "model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0", + "instructions": "Rate {context}", + "ratingScale": { + "numerical": [ + { + "value": 1, + "label": "bad", + "definition": "b" + }, + { + "value": 5, + "label": "good", + "definition": "g" + } + ] + } + } + }, + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012", + "tags": { + "e": "1" + } + }, + { + "name": "evalCat", + "level": "TRACE", + "config": { + "llmAsAJudge": { + "modelProvider": "OpenResponses", + "model": "gpt-4o", + "instructions": "Rate {context}", + "ratingScale": { + "categorical": [ + { + "label": "yes", + "definition": "y" + }, + { + "label": "no", + "definition": "n" + } + ] + } + } + } + }, + { + "name": "evalCode", + "level": "TOOL_CALL", + "config": { + "codeBased": { + "managed": { + "codeLocation": "evals/code" + } + } + } + }, + { + "name": "evalExt", + "level": "SESSION", + "config": { + "codeBased": { + "external": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f" + } + } + } + } + ], + "onlineEvalConfigs": [ + { + "name": "oe1", + "agent": "agentA", + "endpoint": "prod", + "evaluators": [ + "evalNum", + "Builtin.Helpfulness", + "arn:aws:x" + ], + "samplingRate": 10, + "description": "d", + "enableOnCreate": true, + "tags": { + "o": "1" + } + }, + { + "name": "oe2", + "logGroupNames": [ + "/aws/x" + ], + "serviceNames": [ + "svc" + ], + "insights": [ + "i1" + ], + "clusteringConfig": { + "frequencies": [ + "DAILY" + ] + }, + "samplingRate": 0.5 + } + ], + "agentCoreGateways": [ + { + "name": "gw1", + "resourceName": "gw1-res", + "protocolType": "MCP", + "description": "g", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ] + } + }, + "enableSemanticSearch": false, + "exceptionLevel": "DEBUG", + "policyEngineConfiguration": { + "policyEngineName": "pe1", + "mode": "ENFORCE" + }, + "executionRoleArn": "arn:aws:iam::123456789012:role/gw", + "tags": { + "g": "1" + }, + "targets": [ + { + "name": "lambdaPy", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t1", + "description": "d", + "inputSchema": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ] + }, + "outputSchema": { + "type": "string" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "Python", + "path": "tools/t1", + "handler": "handler.main" + }, + "pythonVersion": "PYTHON_3_12", + "timeout": 30, + "memorySize": 512, + "iamPolicy": { + "Version": "2012-10-17", + "Statement": [], + "Id": "x" + } + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth", + "scopes": [ + "read" + ] + } + }, + { + "name": "lambdaTs", + "targetType": "lambda", + "toolDefinitions": [ + { + "name": "t2", + "description": "d", + "inputSchema": { + "type": "object" + } + } + ], + "compute": { + "host": "Lambda", + "implementation": { + "language": "TypeScript", + "path": "tools/t2", + "handler": "index.handler" + }, + "nodeVersion": "NODE_20" + } + }, + { + "name": "mcpExt", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp", + "outboundAuth": { + "type": "NONE" + } + }, + { + "name": "openapi", + "targetType": "openApiSchema", + "schemaSource": { + "inline": { + "path": "schemas/api.json" + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "smithy", + "targetType": "smithyModel", + "schemaSource": { + "s3": { + "uri": "s3://b/model.json", + "bucketOwnerAccountId": "123456789012" + } + } + }, + { + "name": "apigw", + "targetType": "apiGateway", + "apiGateway": { + "restApiId": "abc123", + "stage": "prod", + "apiGatewayToolConfiguration": { + "toolFilters": [ + { + "filterPath": "/pets", + "methods": [ + "GET" + ] + } + ], + "toolOverrides": [ + { + "name": "listPets", + "path": "/pets", + "method": "GET", + "description": "d" + } + ] + } + }, + "outboundAuth": { + "type": "API_KEY", + "credentialName": "openaiKey" + } + }, + { + "name": "lfa", + "targetType": "lambdaFunctionArn", + "lambdaFunctionArn": { + "lambdaArn": "arn:aws:lambda:us-east-1:123456789012:function:f", + "toolSchemaFile": "tools/schema.json" + } + }, + { + "name": "kbconn", + "targetType": "connector", + "connectorId": "bedrock-knowledge-bases", + "configurations": [ + { + "name": "Retrieve", + "description": "d", + "parameterValues": { + "knowledgeBaseId": "kb-docs" + }, + "parameterOverrides": [ + { + "path": "/x", + "description": "d", + "visible": false + } + ] + }, + { + "name": "AgenticRetrieveStream", + "parameterValues": { + "retrievers": [ + { + "configuration": { + "knowledgeBase": { + "knowledgeBaseId": "ABCDEFGHIJ" + } + } + } + ] + } + } + ] + }, + { + "name": "websearch", + "targetType": "connector", + "connectorId": "web-search" + } + ] + }, + { + "name": "gw2", + "protocolType": "None", + "authorizerType": "AWS_IAM", + "targets": [ + { + "name": "httprt", + "targetType": "httpRuntime", + "httpRuntime": { + "runtime": "agentA", + "runtimeEndpoint": "prod" + }, + "outboundAuth": { + "type": "OAUTH", + "credentialName": "my-oauth" + } + }, + { + "name": "pt-iam", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com:443/v1", + "protocolType": "INFERENCE", + "stickinessConfiguration": { + "identifier": "x-session", + "timeout": 3600 + } + }, + "outboundAuth": { + "type": "GATEWAY_IAM_ROLE", + "service": "bedrock", + "region": "us-east-1" + } + }, + { + "name": "pt-jwt", + "targetType": "passthrough", + "passthrough": { + "endpoint": "https://api.example.com" + }, + "outboundAuth": { + "type": "JWT_PASSTHROUGH" + } + } + ] + } + ], + "policyEngines": [ + { + "name": "pe1", + "description": "d", + "encryptionKeyArn": "arn:k", + "tags": { + "p": "1" + }, + "policies": [ + { + "name": "pol1", + "description": "d", + "statement": "permit(principal, action, resource);", + "sourceFile": "policies/p.cedar", + "validationMode": "IGNORE_ALL_FINDINGS", + "enforcementMode": "LOG_ONLY", + "authorizationPhase": "RETURN_OUTPUT" + }, + { + "name": "pol2", + "statement": "forbid(principal, action, resource);" + } + ] + } + ], + "configBundles": [ + { + "name": "cb1", + "type": "ConfigurationBundle", + "description": "d", + "components": { + "{{runtime:agentA}}": { + "configuration": { + "systemPrompt": "hi" + } + } + }, + "branchName": "main", + "commitMessage": "init", + "kmsKeyArn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012" + } + ], + "harnesses": [ + { + "name": "h1", + "path": "app/h1" + } + ], + "payments": [ + { + "name": "pm1", + "authorizerType": "AWS_IAM", + "connectors": [ + { + "name": "cb_manual", + "provider": "CoinbaseCDP", + "provisionMode": "MANUAL", + "credentialName": "coinbaseCred" + }, + { + "name": "cb_quick", + "provider": "CoinbaseCDP", + "provisionMode": "QUICK_CREATE" + }, + { + "name": "stripe1", + "provider": "StripePrivy", + "credentialName": "stripeCred" + } + ], + "description": "Payment manager one", + "autoPayment": false, + "defaultSpendLimit": "25.00", + "paymentToolAllowlist": [ + "pay" + ], + "networkPreferences": [ + "base" + ] + }, + { + "name": "pm2", + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJWTAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedClients": [ + "c" + ], + "allowedAudience": [ + "a" + ], + "allowedScopes": [ + "s" + ] + } + } + } + ], + "abTests": [], + "datasets": [], + "capacityProviders": [], + "unassignedTargets": [ + { + "name": "u1", + "targetType": "mcpServer", + "endpoint": "https://x.example.com/mcp" + } + ] +} \ No newline at end of file diff --git a/src/core/project/legacy/deploy.test.ts b/src/core/project/legacy/deploy.test.ts new file mode 100644 index 0000000000..2fd271ddc2 --- /dev/null +++ b/src/core/project/legacy/deploy.test.ts @@ -0,0 +1,64 @@ +import { describe, expect, test } from "bun:test"; +import type { InheritedProcessOptions, InheritedProcessRunner } from "../../../io"; +import { executeV0Deploy, V0_CLI_PACKAGE } from "./deploy"; + +describe("executeV0Deploy", () => { + test("pins the final v0 CLI and forwards deploy flags from the project root", async () => { + const calls: Array<{ command: string[]; options: InheritedProcessOptions }> = []; + const runner: InheritedProcessRunner = async (command, options) => { + calls.push({ command, options }); + return 7; + }; + + const exitCode = await executeV0Deploy( + { + projectRoot: "/workspace/project", + target: "staging", + yes: true, + json: true, + }, + runner, + ); + + expect(exitCode).toBe(7); + expect(calls).toEqual([ + { + command: [ + "npx", + "--yes", + V0_CLI_PACKAGE, + "deploy", + "--target", + "staging", + "--yes", + "--json", + ], + options: { + cwd: "/workspace/project", + env: { + ...process.env, + AGENTCORE_SKIP_CONFLICT_CHECK: "1", + }, + }, + }, + ]); + }); + + test("omits optional flags when they were not requested", async () => { + const commands: string[][] = []; + await executeV0Deploy( + { + projectRoot: "/workspace/project", + target: "default", + yes: false, + json: false, + }, + async (command) => { + commands.push(command); + return 0; + }, + ); + + expect(commands).toEqual([["npx", "--yes", V0_CLI_PACKAGE, "deploy", "--target", "default"]]); + }); +}); diff --git a/src/core/project/legacy/deploy.ts b/src/core/project/legacy/deploy.ts new file mode 100644 index 0000000000..7e1f619652 --- /dev/null +++ b/src/core/project/legacy/deploy.ts @@ -0,0 +1,40 @@ +import { runInheritedProcess, type InheritedProcessRunner } from "../../../io"; + +export const V0_CLI_VERSION = "0.31.1"; +export const V0_CLI_PACKAGE = `@aws/agentcore@${V0_CLI_VERSION}`; + +export type V0DeployInput = { + projectRoot: string; + target: string; + yes: boolean; + json: boolean; +}; + +/** Injectable boundary used by direct deploy and harness dev. */ +export type V0DeployRunner = (input: V0DeployInput) => Promise; + +/** Run the final v0 deploy implementation with full ownership of the terminal. */ +export async function executeV0Deploy( + input: V0DeployInput, + runner: InheritedProcessRunner = runInheritedProcess, +): Promise { + const args = [ + "npx", + "--yes", + V0_CLI_PACKAGE, + "deploy", + "--target", + input.target, + ...(input.yes ? ["--yes"] : []), + ...(input.json ? ["--json"] : []), + ]; + return runner(args, { + cwd: input.projectRoot, + env: { + ...process.env, + AGENTCORE_SKIP_CONFLICT_CHECK: "1", + }, + }); +} + +export const runV0Deploy: V0DeployRunner = (input) => executeV0Deploy(input); diff --git a/src/core/project/legacy/detect.test.ts b/src/core/project/legacy/detect.test.ts new file mode 100644 index 0000000000..c0189cf407 --- /dev/null +++ b/src/core/project/legacy/detect.test.ts @@ -0,0 +1,13 @@ +import { expect, test } from "bun:test"; +import { projectFormat } from "./detect"; + +test("version 1 is v0", () => expect(projectFormat({ version: 1 })).toBe("v0")); + +test("version 2 is v1", () => expect(projectFormat({ version: 2 })).toBe("v1")); + +test("missing or odd versions fall through to v1 so v1 validation reports them", () => { + expect(projectFormat({})).toBe("v1"); + expect(projectFormat(null)).toBe("v1"); + expect(projectFormat("version: 1")).toBe("v1"); + expect(projectFormat({ version: "1" })).toBe("v1"); +}); diff --git a/src/core/project/legacy/detect.ts b/src/core/project/legacy/detect.ts new file mode 100644 index 0000000000..7d83b72a28 --- /dev/null +++ b/src/core/project/legacy/detect.ts @@ -0,0 +1,8 @@ +export type ProjectFormat = "v0" | "v1"; + +/** v0 CLIs write `version: 1`; anything else is validated as a v1 spec. */ +export function projectFormat(raw: unknown): ProjectFormat { + return typeof raw === "object" && raw !== null && (raw as { version?: unknown }).version === 1 + ? "v0" + : "v1"; +} diff --git a/src/core/project/legacy/fixtures-test-support.ts b/src/core/project/legacy/fixtures-test-support.ts new file mode 100644 index 0000000000..972ea48e16 --- /dev/null +++ b/src/core/project/legacy/fixtures-test-support.ts @@ -0,0 +1,29 @@ +import { readdirSync, readFileSync } from "node:fs"; +import { join } from "node:path"; +import { V0AgentCoreProjectSpecSchema, type V0ProjectSpec } from "../../../projectSchemas/v0"; + +/** + * v0 `agentcore.json` files from the v0→v1 schema audit, one per edge case v0 0.31.1 + * accepted. `invalid_*` files are ones v0 itself rejects; `aws-targets_*` files are + * deployment target lists rather than project specs. + */ +export const FIXTURES_DIR = join(import.meta.dir, "__fixtures__"); + +/** The raw JSON of a fixture. */ +export function rawFixture(name: string): Record { + return JSON.parse(readFileSync(join(FIXTURES_DIR, name), "utf8")) as Record; +} + +/** A fixture parsed with the vendored v0 schema. */ +export function v0Fixture(name: string): V0ProjectSpec { + return V0AgentCoreProjectSpecSchema.parse(rawFixture(name)); +} + +/** Every project-spec fixture v0 0.31.1 accepts. */ +export function validV0FixtureNames(): string[] { + return readdirSync(FIXTURES_DIR) + .filter( + (f) => f.endsWith(".json") && !f.startsWith("aws-targets_") && !f.startsWith("invalid_"), + ) + .sort(); +} diff --git a/src/core/project/legacy/load.ts b/src/core/project/legacy/load.ts new file mode 100644 index 0000000000..511ad74755 --- /dev/null +++ b/src/core/project/legacy/load.ts @@ -0,0 +1,17 @@ +import type { Project } from "../../../handlers/project/types"; +import type { ReadWriteJson } from "../../../io"; +import { V0AgentCoreProjectSpecSchema } from "../../../projectSchemas/v0"; +import { projectSpecPath } from "../fsUtils"; +import { translateV0Spec } from "./translate"; + +/** Parse a v0 project with v0's schema and expose a translated, read-only in-memory view. */ +export async function loadLegacyProject(rootPath: string, json: ReadWriteJson): Promise { + const v0Spec = await json.read(projectSpecPath(rootPath), V0AgentCoreProjectSpecSchema); + const { spec, extras } = translateV0Spec(v0Spec); + return { + name: v0Spec.name, + rootPath, + spec, + legacy: { format: "v0", v0Spec, extras }, + }; +} diff --git a/src/core/project/legacy/translate.test.ts b/src/core/project/legacy/translate.test.ts new file mode 100644 index 0000000000..812e15643e --- /dev/null +++ b/src/core/project/legacy/translate.test.ts @@ -0,0 +1,78 @@ +import { describe, expect, test } from "bun:test"; +import { v0Fixture, validV0FixtureNames, rawFixture } from "./fixtures-test-support"; +import { translateV0Spec } from "./translate"; + +type Json = Record; + +describe("translateV0Spec", () => { + test("sets version 2 and drops $schema", () => { + const { spec } = translateV0Spec(v0Fixture("baseline.json")); + expect(spec.version).toBe(2); + expect("$schema" in spec).toBe(false); + }); + + test("moves v0-only collections into extras and drops httpGateways", () => { + const { spec, extras } = translateV0Spec(v0Fixture("top-abTests-nonempty.json")); + for (const key of ["abTests", "datasets", "capacityProviders", "httpGateways"]) { + expect(key in spec).toBe(false); + } + expect(extras.abTests?.length).toBeGreaterThan(0); + + const unassigned = translateV0Spec(v0Fixture("top-unassignedTargets.json")); + expect("unassignedTargets" in unassigned.spec).toBe(false); + expect(unassigned.extras.unassignedTargets?.length).toBeGreaterThan(0); + }); + + test("renames mcpRuntimeTools to toolRuntimes and artifact to build", () => { + const { spec } = translateV0Spec(v0Fixture("top-mcpRuntimeTools.json")); + expect("mcpRuntimeTools" in spec).toBe(false); + const runtime = spec.toolRuntimes?.[0]?.compute.runtime as Json | undefined; + expect(runtime?.build).toBe("CodeZip"); + expect(runtime?.artifact).toBeUndefined(); + }); + + test("omits toolRuntimes when v0 had no mcpRuntimeTools", () => { + const { spec } = translateV0Spec(v0Fixture("baseline.json")); + expect("toolRuntimes" in spec).toBe(false); + }); + + test("renames artifact to build on gateway target compute", () => { + const { spec } = translateV0Spec( + v0Fixture("gateway-target-mcpServer-agentcoreRuntime-compute.json"), + ); + const runtime = spec.agentCoreGateways + .flatMap((gateway) => gateway.targets) + .map((t) => t.compute) + .flatMap((compute) => (compute?.host === "AgentCoreRuntime" ? [compute.runtime] : [])) + .find(Boolean) as Json | undefined; + expect(runtime?.build).toBe("CodeZip"); + expect(runtime?.artifact).toBeUndefined(); + }); + + test("drops capacityProviderVolume mounts but keeps the others", () => { + const v0 = v0Fixture("runtime-capacityProviderVolume-mount.json"); + const before = v0.runtimes.flatMap((r) => r.filesystemConfigurations ?? []); + const { spec } = translateV0Spec(v0); + const after = spec.runtimes.flatMap((r) => r.filesystemConfigurations ?? []); + expect(before.some((m) => "capacityProviderVolume" in m)).toBe(true); + expect(after.some((m) => "capacityProviderVolume" in m)).toBe(false); + expect(after.length).toBe(before.filter((m) => !("capacityProviderVolume" in m)).length); + }); + + test("is pure: does not mutate the input", () => { + const v0 = v0Fixture("baseline.json"); + const before = JSON.stringify(v0); + translateV0Spec(v0); + expect(JSON.stringify(v0)).toBe(before); + }); + + test("translates every v0-valid fixture, keeping the project name", () => { + for (const name of validV0FixtureNames()) { + const { spec } = translateV0Spec(v0Fixture(name)); + expect({ name, project: spec.name }).toEqual({ + name, + project: String(rawFixture(name).name), + }); + } + }); +}); diff --git a/src/core/project/legacy/translate.ts b/src/core/project/legacy/translate.ts new file mode 100644 index 0000000000..f82d988b66 --- /dev/null +++ b/src/core/project/legacy/translate.ts @@ -0,0 +1,75 @@ +import type { ProjectSpec } from "../../../projectSchemas/project"; +import type { V0ProjectSpec } from "../../../projectSchemas/v0"; +import type { LegacyExtras } from "./types"; + +type Json = Record; + +/** v0 named a tool runtime's build type `artifact`; v1 calls it `build`. */ +function renameArtifact(compute: unknown): unknown { + if (typeof compute !== "object" || compute === null) return compute; + const runtime = (compute as Json).runtime as Json | undefined; + if (!runtime || !("artifact" in runtime)) return compute; + const { artifact, ...rest } = runtime; + return { ...compute, runtime: { ...rest, build: artifact } }; +} + +/** + * Maps a v0 spec (already validated by the v0 schema) onto v1's shape. + * + * Deliberately not re-validated against v1's schema: compatibility mode accepts + * whatever v0 accepted, so this only renames and reshapes what v1 reads under + * another name. Callers that need a valid v1 spec (migrate) validate the result. + * + * - `version` becomes 2 and `$schema` is dropped. + * - `abTests`, `datasets`, `capacityProviders`, and `unassignedTargets` move into + * the returned extras; `httpGateways` (always empty in v0) is dropped. + * - `mcpRuntimeTools` becomes `toolRuntimes`, and every tool runtime's and gateway + * target's `compute.runtime.artifact` becomes `build`. + * - Runtime `capacityProviderVolume` mounts are dropped: v1 has no capacity + * providers, and its code switches over the mount kinds it knows. + */ +export function translateV0Spec(v0: V0ProjectSpec): { spec: ProjectSpec; extras: LegacyExtras } { + const { + $schema: _schema, + abTests, + datasets, + capacityProviders, + unassignedTargets, + httpGateways: _httpGateways, + mcpRuntimeTools, + ...rest + } = structuredClone(v0) as V0ProjectSpec & Json; + + const runtimes = (rest.runtimes as Json[]).map((runtime) => { + const mounts = runtime.filesystemConfigurations as Json[] | undefined; + if (!mounts) return runtime; + return { + ...runtime, + filesystemConfigurations: mounts.filter((mount) => !("capacityProviderVolume" in mount)), + }; + }); + const agentCoreGateways = (rest.agentCoreGateways as Json[]).map((gateway) => ({ + ...gateway, + targets: (gateway.targets as Json[]).map((target) => + "compute" in target ? { ...target, compute: renameArtifact(target.compute) } : target, + ), + })); + + const spec = { + ...rest, + version: 2, + runtimes, + agentCoreGateways, + ...(mcpRuntimeTools && { + toolRuntimes: (mcpRuntimeTools as Json[]).map((tool) => ({ + ...tool, + compute: renameArtifact(tool.compute), + })), + }), + } as unknown as ProjectSpec; + + return { + spec, + extras: { abTests, datasets, capacityProviders, unassignedTargets } as LegacyExtras, + }; +} diff --git a/src/core/project/legacy/types.ts b/src/core/project/legacy/types.ts new file mode 100644 index 0000000000..188fa23f30 --- /dev/null +++ b/src/core/project/legacy/types.ts @@ -0,0 +1,14 @@ +import type { V0ProjectSpec } from "../../../projectSchemas/v0"; + +/** The v0 collections that have no place in v1's spec, kept aside by the translator. */ +export type LegacyExtras = Pick< + V0ProjectSpec, + "abTests" | "datasets" | "capacityProviders" | "unassignedTargets" +>; + +export type LegacyProjectInfo = { + format: "v0"; + /** The v0 spec as parsed by the v0 schema; the source of truth for v0-only reads. */ + v0Spec: V0ProjectSpec; + extras: LegacyExtras; +}; diff --git a/src/core/project/legacy/v0schema.test.ts b/src/core/project/legacy/v0schema.test.ts new file mode 100644 index 0000000000..5b9f9174f2 --- /dev/null +++ b/src/core/project/legacy/v0schema.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, test } from "bun:test"; +import { + V0AgentCoreProjectSpecSchema, + V0AwsDeploymentTargetsSchema, +} from "../../../projectSchemas/v0"; +import { rawFixture, validV0FixtureNames } from "./fixtures-test-support"; + +describe("vendored v0 0.31.1 schema", () => { + test("parses every v0-valid audit fixture", () => { + const names = validV0FixtureNames(); + expect(names.length).toBeGreaterThan(40); + for (const name of names) { + const result = V0AgentCoreProjectSpecSchema.safeParse(rawFixture(name)); + expect({ name, ok: result.success }).toEqual({ name, ok: true }); + } + }); + + test.each([ + "invalid_top-mcpRuntimeTools-renamed-to-toolRuntimes.json", + "invalid_evaluator-model-3000-chars.json", + "invalid_memory-namespaces-and-templates-both.json", + ])("rejects %s, as v0 did", (name) => { + expect(V0AgentCoreProjectSpecSchema.safeParse(rawFixture(name)).success).toBe(false); + }); + + test("accepts the hyphenated and case-duplicate target names v1 rejects", () => { + for (const name of ["aws-targets_hyphen-name.json", "aws-targets_case-dup.json"]) { + expect(V0AwsDeploymentTargetsSchema.safeParse(rawFixture(name)).success).toBe(true); + } + }); +}); diff --git a/src/core/project/legacy/writeGate.ts b/src/core/project/legacy/writeGate.ts new file mode 100644 index 0000000000..fbe82311fe --- /dev/null +++ b/src/core/project/legacy/writeGate.ts @@ -0,0 +1,23 @@ +import { ProjectStateError } from "../../../errors"; +import type { Project } from "../../../handlers/project/types"; + +/** Guard operations whose implementation rewrites files using the v1 project shape. */ +export function assertV1Project(project: Project, command: string): void { + if (!project.legacy) return; + if (command === "build") { + throw new ProjectStateError( + "'build' isn't available for v0 projects because v0 did not expose a standalone build " + + "command. Run `agentcore migrate` to use the v1 build command.", + ); + } + if (command === "deploy") { + throw new ProjectStateError( + "v0 projects must be deployed by the v0 compatibility runner. " + + "Run `agentcore deploy` instead of calling the v1 project manager directly.", + ); + } + throw new ProjectStateError( + `'${command}' isn't available for v0 projects yet. ` + + `Use the v0 CLI for now: npx @aws/agentcore@0 ${command} …`, + ); +} diff --git a/src/core/project/manager.test.ts b/src/core/project/manager.test.ts index 62489c496f..9a6e324149 100644 --- a/src/core/project/manager.test.ts +++ b/src/core/project/manager.test.ts @@ -2104,20 +2104,18 @@ describe("FsProjectManager.resolve", () => { "latest", "*", ">=0.1.0-alpha.19", - ])( - "preserves v0 schema validation for an updated or unknown dependency %s", - async (dependency) => { - const { root, configPath } = await legacyProject(dependency, 1); + ])("loads a valid v0 project with updated or custom dependency %s", async (dependency) => { + const { root } = await legacyProject(dependency, 1); - const error = await manager() - .manager.resolve({ filePath: root }) - .catch((caught: unknown) => caught); + const project = await manager().manager.resolve({ filePath: root }); - expect(error).toBeInstanceOf(DeserializationError); - expect(error).toHaveProperty("message", expect.stringContaining(configPath)); - expect(error).toHaveProperty("message", expect.not.stringContaining("npx @aws/agentcore@0")); - }, - ); + expect(project).toMatchObject({ + name: "example", + rootPath: root, + spec: { name: "example", version: 2, managedBy: "CDK" }, + legacy: { format: "v0", v0Spec: { name: "example", version: 1 } }, + }); + }); test.each([undefined, 0, 2, 3, "1"])( "does not apply v0 dependency guidance to project version %s", @@ -2134,18 +2132,118 @@ describe("FsProjectManager.resolve", () => { ); test.each(["missing", "malformed", "invalid-shape"] as const)( - "preserves the original schema error when the v0 CDK manifest is %s", + "loads a valid v0 project when its CDK manifest is %s", async (state) => { const { root, manifestPath } = await legacyProject("^0.1.0-alpha.19", 1); if (state === "missing") await rm(manifestPath); else await writeFile(manifestPath, state === "malformed" ? "{ not valid json" : "null"); - await expect(manager().manager.resolve({ filePath: root })).rejects.toBeInstanceOf( - DeserializationError, - ); + expect(await manager().manager.resolve({ filePath: root })).toMatchObject({ + legacy: { format: "v0" }, + }); }, ); + test("reports v0 schema errors after the dependency gate passes", async () => { + const { root, configPath } = await legacyProject("0.1.0-alpha.45", 1); + await writeFile(configPath, JSON.stringify({ name: "not-valid!", version: 1 })); + + await expect(manager().manager.resolve({ filePath: root })).rejects.toThrow( + "Project name must start with a letter and contain only alphanumeric characters", + ); + }); + + test("reads v0 deployment target names with v0 rules", async () => { + const { root } = await legacyProject("0.1.0-alpha.45", 1); + const subject = manager().manager; + const project = await subject.resolve({ filePath: root }); + if (!project) throw new Error("expected project"); + await writeFile( + join(root, "agentcore", "aws-targets.json"), + JSON.stringify([ + { name: "prod-us", account: "111122223333", region: "us-east-1" }, + { name: "PROD-US", account: "111122223333", region: "us-west-2" }, + ]), + ); + + expect(await subject.listTargets(project)).toEqual([ + { name: "prod-us", account: "111122223333", region: "us-east-1" }, + { name: "PROD-US", account: "111122223333", region: "us-west-2" }, + ]); + }); + + test("blocks v0 builds and direct manager deploys before reaching the v1 backend", async () => { + const { root } = await legacyProject("0.1.0-alpha.45", 1); + const builds: Project[] = []; + const deploys: { project: Project; input: DeployBackendInput }[] = []; + const backend: ProjectBackend = { + async *build(project) { + builds.push(project); + yield { type: "step", message: "Building" }; + }, + async *deploy(project, input) { + deploys.push({ project, input }); + yield { type: "step", message: "Deploying" }; + return { outputs: {} }; + }, + async resolveDeployedResources() { + return []; + }, + async resolveProjectResources() { + return []; + }, + }; + const subject = new FsProjectManager({ + logger: createSilentLogger(), + identity: new TestIdentityClient(), + enableTransactionSearch: async () => {}, + backends: { CDK: backend }, + }); + const project = await subject.resolve({ filePath: root }); + if (!project) throw new Error("expected project"); + await writeFile( + join(root, "agentcore", "aws-targets.json"), + JSON.stringify([{ name: "default", account: "111122223333", region: "us-east-1" }]), + ); + + const build = subject.build(project); + await expect(build.next()).rejects.toThrow("v0 did not expose a standalone build command"); + const deploy = subject.deploy(project, { + target: "default", + region: "us-east-1", + confirmTeardown: async () => false, + transactionSearch: false, + }); + await expect(deploy.next()).rejects.toThrow( + "v0 projects must be deployed by the v0 compatibility runner", + ); + expect(builds).toEqual([]); + expect(deploys).toEqual([]); + }); + + test("blocks v0 operations that rewrite files using the v1 shape", async () => { + const { root } = await legacyProject("0.1.0-alpha.45", 1); + const subject = manager().manager; + const project = await subject.resolve({ filePath: root }); + if (!project) throw new Error("expected project"); + + await expect( + runAdd(subject, project, { + resourceType: "memory", + resourceConfig: getDefaultMemorySpec("memory"), + }), + ).rejects.toThrow("'add' isn't available for v0 projects yet"); + await expect( + subject.removeResource(project, { resourceType: "memory", name: "memory" }), + ).rejects.toThrow("'remove' isn't available for v0 projects yet"); + await expect(subject.removeAllResources(project)).rejects.toThrow( + "'remove all' isn't available for v0 projects yet", + ); + await expect( + subject.exportHarness(project, { harnessName: "harness", targetAgentName: "agent" }).next(), + ).rejects.toThrow("'export harness' isn't available for v0 projects yet"); + }); + test("loads a v1 project with an old CDK declaration without legacy guidance", async () => { const { root, configPath } = await legacyProject("^0.1.0-alpha.19", 2); await writeFile(configPath, JSON.stringify({ name: "example", version: 2 })); diff --git a/src/core/project/manager.tsx b/src/core/project/manager.tsx index b50a8a2c38..b8f2c251c7 100644 --- a/src/core/project/manager.tsx +++ b/src/core/project/manager.tsx @@ -72,12 +72,7 @@ import { OnlineEvalConfigSchema } from "../../projectSchemas/online-eval-config" import { PaymentConnectorSchema, PaymentManagerSchema } from "../../projectSchemas/payment"; import { PolicyEngineSchema, PolicySchema } from "../../projectSchemas/policy"; import { RuntimeEndpointSchema } from "../../projectSchemas/runtime"; -import { - defaultExportProjectName, - enclosingProjectRoot, - isV0Project, - projectSpecPath, -} from "./fsUtils"; +import { defaultExportProjectName, enclosingProjectRoot, projectSpecPath } from "./fsUtils"; import { parseArn } from "../arn"; import { AgentCoreCLIError, @@ -102,6 +97,7 @@ import { DEFAULT_TARGET_NAME, type AwsDeploymentTarget, } from "../../projectSchemas/aws-targets"; +import { V0AwsDeploymentTargetsSchema } from "../../projectSchemas/v0"; import type { RuntimeResourceConfig } from "../../handlers/project/add/runtime/types"; import type { TemplateRenderer } from "./templates/types"; import { HandlebarsTemplateRenderer } from "./templates/renderer"; @@ -110,6 +106,9 @@ import type { CoreIdentityClient } from "../../handlers/identity/types"; import { templateManagesDependencies } from "../../handlers/project/templateProfile"; import { resolveRuntimeTemplateProfile } from "../../handlers/project/runtimeTemplateProfile"; import { isBmaRuntime } from "../../handlers/project/bma"; +import { projectFormat } from "./legacy/detect"; +import { loadLegacyProject } from "./legacy/load"; +import { assertV1Project } from "./legacy/writeGate"; const TARGETS_EXAMPLE = '[{ "name": "default", "account": "111122223333", "region": "us-east-1" }]'; @@ -403,27 +402,29 @@ export class FsProjectManager implements ProjectManager { if (!rootPath) return undefined; const configPath = projectSpecPath(rootPath); - let spec: Project["spec"]; try { - spec = await this.json.read(configPath, ProjectSpecSchema); + const spec = await this.json.read(configPath, ProjectSpecSchema); + return { + name: spec.name, + rootPath, + spec, + }; } catch (error) { - // Version-1 projects fail the v1 schema before reaching deploy preflight. if (error instanceof DeserializationError) { - const warning = await this.v0DependencyWarning(rootPath); - if (warning) throw new ProjectStateError(warning, { cause: error }); + const header = await this.json + .read(configPath, z.object({ version: z.unknown().optional() })) + .catch(() => undefined); + if (projectFormat(header) === "v0") { + const warning = await this.v0DependencyWarning(rootPath); + if (warning) throw new ProjectStateError(warning, { cause: error }); + return loadLegacyProject(rootPath, this.json); + } } throw error; } - return { - name: spec.name, - rootPath, - spec, - }; } private async v0DependencyWarning(rootPath: string): Promise { - if (!(await isV0Project(rootPath))) return undefined; - const manifest = await this.json .read( join(rootPath, "agentcore", "cdk", "package.json"), @@ -544,6 +545,7 @@ export class FsProjectManager implements ProjectManager { input: AddResourceInput, options: AddResourceOptions = {}, ): AsyncGenerator { + assertV1Project(project, "add"); const agentCoreSpecPath = this.getProjectSpecPath(project); const projectSpecKey = toProjectSpecKey(input.resourceType); @@ -934,6 +936,7 @@ export class FsProjectManager implements ProjectManager { project: Project, input: RemoveResourceInput, ): Promise { + assertV1Project(project, "remove"); const agentCoreSpecPath = this.getProjectSpecPath(project); const existingProjectSpec = await this.json.read(agentCoreSpecPath, ProjectSpecSchema); @@ -1059,6 +1062,7 @@ export class FsProjectManager implements ProjectManager { } public async removeAllResources(project: Project): Promise { + assertV1Project(project, "remove all"); const agentCoreSpecPath = this.getProjectSpecPath(project); const existingProjectSpec = await this.json.read(agentCoreSpecPath, ProjectSpecSchema); @@ -1129,6 +1133,7 @@ export class FsProjectManager implements ProjectManager { project: Project | undefined, input: ExportHarnessInput, ): AsyncGenerator { + if (project) assertV1Project(project, "export harness"); if (!project) { if (!input.prefetched) { throw new ProjectStateError( @@ -1369,6 +1374,7 @@ export class FsProjectManager implements ProjectManager { } public async *build(project: Project): AsyncGenerator { + assertV1Project(project, "build"); yield* this.backendFor(project).build(project); } @@ -1379,6 +1385,7 @@ export class FsProjectManager implements ProjectManager { project: Project, input: DeployProjectInput, ): AsyncGenerator { + assertV1Project(project, "deploy"); const targetsPath = join(project.rootPath, "agentcore", "aws-targets.json"); const fileExists = existsSync(targetsPath); const targets = await this.listTargets(project); @@ -1524,7 +1531,10 @@ export class FsProjectManager implements ProjectManager { public async listTargets(project: Project): Promise { const targetsPath = join(project.rootPath, "agentcore", "aws-targets.json"); if (!existsSync(targetsPath)) return []; - return this.json.read(targetsPath, AwsDeploymentTargetsSchema); + return this.json.read( + targetsPath, + project.legacy ? V0AwsDeploymentTargetsSchema : AwsDeploymentTargetsSchema, + ); } public async resolveTarget( @@ -1580,7 +1590,10 @@ export class FsProjectManager implements ProjectManager { ): Promise { const targetsPath = join(project.rootPath, "agentcore", "aws-targets.json"); const targets = existsSync(targetsPath) - ? await this.json.read(targetsPath, AwsDeploymentTargetsSchema) + ? await this.json.read( + targetsPath, + project.legacy ? V0AwsDeploymentTargetsSchema : AwsDeploymentTargetsSchema, + ) : []; if (targets.length === 0) { throw new ProjectStateError( diff --git a/src/handlers/index.tsx b/src/handlers/index.tsx index 1d59f6c914..e8d64afcae 100644 --- a/src/handlers/index.tsx +++ b/src/handlers/index.tsx @@ -20,6 +20,7 @@ import { withPlatform, } from "../middleware"; import type { AppIO } from "../io"; +import type { V0DeployRunner } from "../core/project/legacy/deploy"; import type { Core } from "./types.tsx"; import type { Logger } from "../logging"; import type { GlobalConfigAccessor } from "../globalConfig"; @@ -31,6 +32,8 @@ export interface RootHandlerConfig { globalConfigAccessor: GlobalConfigAccessor; /** Host platform, defaults to `process.platform`. Tests pass "win32" to exercise Windows paths. */ platform?: NodeJS.Platform; + /** Overrides the v0 deploy subprocess boundary in tests. */ + runV0Deploy?: V0DeployRunner; } export function createRootHandler(core: Core, config: RootHandlerConfig): Router { @@ -85,7 +88,7 @@ export function createRootHandler(core: Core, config: RootHandlerConfig): Router // Install sub handlers. Registration order is menu/help order; project is // the primary workflow, so it goes first. - createProjectHandlers(core, io).forEach((handler) => { + createProjectHandlers(core, io, { runV0Deploy: config.runV0Deploy }).forEach((handler) => { root.handler(handler); }); diff --git a/src/handlers/project/buildDeploy.screen.test.tsx b/src/handlers/project/buildDeploy.screen.test.tsx index 95294e839a..3b0a06e8ba 100644 --- a/src/handlers/project/buildDeploy.screen.test.tsx +++ b/src/handlers/project/buildDeploy.screen.test.tsx @@ -11,10 +11,13 @@ import { inTempDirectory, renderScreen, TestCoreClient, + waitFor, waitForFlatText, waitForText, } from "../../testing"; import type { DeployResult, Project, ProjectEvent } from "./types"; +import { ProjectKey } from "../../router"; +import { TuiHandoffKey } from "../../tui/handoff"; // The build and deploy screens run the same ProjectManager generators the // commands run, so these tests stub the backend exactly as the handler tests @@ -187,6 +190,56 @@ describe("project build screen", () => { }); describe("project deploy screen", () => { + test("a translated v0 project hands the selected target to the deploy command", async () => { + const core = new TestCoreClient(); + const project = { + name: "orders", + rootPath: "/workspace/orders", + spec: { + name: "orders", + version: 2, + managedBy: "CDK", + runtimes: [], + memories: [], + knowledgeBases: [], + credentials: [], + evaluators: [], + onlineEvalConfigs: [], + agentCoreGateways: [], + policyEngines: [], + configBundles: [], + harnesses: [], + }, + legacy: { + format: "v0", + v0Spec: {} as never, + extras: { + abTests: [], + datasets: [], + capacityProviders: [], + unassignedTargets: [], + }, + }, + } as Project; + core.projectManager.listTargets = async () => [ + { name: "default", account: "111122223333", region: "us-east-1" }, + ]; + let handoff: string[] | undefined; + const r = renderScreen("/agentcore/deploy", { + core, + withContext: (ctx) => + ctx.withValue(ProjectKey, project).withValue(TuiHandoffKey, (args) => { + handoff = args; + }), + }); + + await waitFor(() => handoff !== undefined); + + expect(handoff).toEqual(["deploy", "--target", "default"]); + expect(core.projectCommands).toEqual([]); + r.unmount(); + }); + test("one target: deploys to it at once, then the CLI's own success line", async () => { const { backend, deploys } = fakeBackend(); const core = new TestCoreClient({ backends: { CDK: backend } }); diff --git a/src/handlers/project/deploy/index.test.ts b/src/handlers/project/deploy/index.test.ts index 5cd7d7c98c..3ef24d507b 100644 --- a/src/handlers/project/deploy/index.test.ts +++ b/src/handlers/project/deploy/index.test.ts @@ -12,6 +12,7 @@ import { testIO, } from "../../../testing"; import type { DeployBackendInput, ProjectBackend } from "../../../core/project"; +import type { V0DeployInput, V0DeployRunner } from "../../../core/project/legacy/deploy"; import type { AwsDeploymentTarget } from "../../../projectSchemas/aws-targets"; import type { DeployResult, Project, ProjectEvent, TeardownConfirmationRequest } from "../types"; @@ -85,6 +86,7 @@ type TestDeployOptions = { resolveAccount?: (region: string) => Promise; /** Seeds the global config's transactionSearch flag (defaults to on). */ transactionSearch?: boolean; + runV0Deploy?: V0DeployRunner; }; function testDeployCommand( @@ -111,6 +113,7 @@ function testDeployCommand( }, ), logger: createSilentLogger(), + runV0Deploy: options.runV0Deploy, }); return { @@ -147,7 +150,7 @@ async function emptyProjectSpec(projectRoot: string): Promise { describe("project deploy handler", () => { test.each(["--yes", "--json"])( - "gives legacy dependency guidance with %s before resolving an account or deploying", + "delegates a legacy deploy with %s before resolving an account or using v1 CDK", async (flag) => { const projectRoot = await inProjectWithTargets(); const specPath = join(projectRoot, "agentcore", "agentcore.json"); @@ -162,26 +165,54 @@ describe("project deploy handler", () => { readFile(manifestPath, "utf8"), ]); const accountCalls: string[] = []; + const legacyDeploys: V0DeployInput[] = []; const subject = testDeployCommand({ outputs: {} }, [], { resolveAccount: async (region) => { accountCalls.push(region); return DEFAULT_TARGET.account; }, + runV0Deploy: async (input) => { + legacyDeploys.push(input); + return 0; + }, }); - await expect(subject.run([flag])).rejects.toThrow( - "Run `npx @aws/agentcore@0 deploy` once to update them, then try again.", - ); + await subject.run([flag]); expect(subject.calls).toEqual([]); expect(accountCalls).toEqual([]); + expect(legacyDeploys).toEqual([ + { + projectRoot, + target: "default", + yes: flag === "--yes", + json: flag === "--json", + }, + ]); expect(subject.io.stdout()).toBe(""); + expect(subject.io.stderr()).toBe( + flag === "--json" + ? "" + : "This is a v0 project; running AgentCore CLI 0.31.1 deploy in compatibility mode.", + ); expect( await Promise.all([readFile(specPath, "utf8"), readFile(manifestPath, "utf8")]), ).toEqual(before); }, ); + test("preserves the v0 deployer's non-zero exit code", async () => { + await inProjectWithTargets(); + await writeFile( + join(process.cwd(), "agentcore", "agentcore.json"), + JSON.stringify({ name: "orders", version: 1 }), + ); + const subject = testDeployCommand({ outputs: {} }, [], { runV0Deploy: async () => 7 }); + + await expect(subject.run(["--yes"])).rejects.toMatchObject({ exitCode: 7 }); + expect(subject.calls).toEqual([]); + }); + test("defaults to the default target and keeps progress off stdout", async () => { const subject = testDeployCommand( { outputs: { ZetaUrl: "https://zeta.example", AlphaArn: "arn:alpha" } }, diff --git a/src/handlers/project/deploy/index.ts b/src/handlers/project/deploy/index.ts index 44f71227e0..62a0cd6461 100644 --- a/src/handlers/project/deploy/index.ts +++ b/src/handlers/project/deploy/index.ts @@ -1,6 +1,12 @@ import { createInterface } from "node:readline/promises"; import z from "zod"; -import { UserCancellationError } from "../../../errors/errors"; +import { enclosingProjectRoot, isV0Project } from "../../../core/project/fsUtils"; +import { + runV0Deploy, + V0_CLI_VERSION, + type V0DeployRunner, +} from "../../../core/project/legacy/deploy"; +import { SilentCLIError, UserCancellationError } from "../../../errors"; import type { AppIO } from "../../../io"; import { DEFAULT_TARGET_NAME } from "../../../projectSchemas/aws-targets"; import { @@ -16,10 +22,11 @@ import { JsonKey, RegionKey } from "../../keys"; import { renderJsonError } from "../../utils"; import type { DeployResult, Project, ProjectManager, TeardownConfirmationHandler } from "../types"; -type DeployProjectHandlerConfig = { +export type DeployProjectHandlerConfig = { projectManager: ProjectManager; io: AppIO; middlewares?: Middleware[]; + runV0Deploy?: V0DeployRunner; }; /** The command both entry points suggest once a deploy succeeds. */ @@ -55,7 +62,7 @@ export const createDeployProjectHandler = (config: DeployProjectHandlerConfig) = createHandler({ name: "deploy", description: "deploy the project to AWS", - middlewares: config.middlewares, + middlewares: [withV0Deploy(config), ...(config.middlewares ?? [])], flags: [ flag( "target", @@ -73,6 +80,15 @@ export const createDeployProjectHandler = (config: DeployProjectHandlerConfig) = // withProject has already resolved the enclosing project. const project = ctx.require(ProjectKey); const jsonOutput = ctx.require(JsonKey); + if (project.legacy) { + await delegateV0Deploy(config, { + projectRoot: project.rootPath, + target: flags.target, + yes: flags.yes, + json: jsonOutput, + }); + return; + } const canPrompt = !flags.yes && !jsonOutput && @@ -121,6 +137,49 @@ export const createDeployProjectHandler = (config: DeployProjectHandlerConfig) = }, }); +/** + * Direct deploy must detect v0 before withProject parses it. This lets the v0 + * deployer repair projects whose CDK dependency predates the translated view. + */ +function withV0Deploy(config: DeployProjectHandlerConfig): Middleware { + return (handler) => ({ + name: () => handler.name(), + description: () => handler.description(), + flags: () => handler.flags(), + arguments: () => handler.arguments(), + doesSupportTui: () => handler.doesSupportTui(), + children: () => handler.children(), + handle: async (ctx, flags, args) => { + const projectRoot = enclosingProjectRoot(process.cwd()); + if (projectRoot && (await isV0Project(projectRoot))) { + await delegateV0Deploy(config, { + projectRoot, + target: flags.target as string, + yes: flags.yes as boolean, + json: ctx.require(JsonKey), + }); + return; + } + await handler.handle(ctx, flags, args); + }, + }); +} + +async function delegateV0Deploy( + config: DeployProjectHandlerConfig, + input: Parameters[0], +): Promise { + if (!input.json) { + config.io.stderr.write( + `This is a v0 project; running AgentCore CLI ${V0_CLI_VERSION} deploy in compatibility mode.\n`, + ); + } + const exitCode = await (config.runV0Deploy ?? runV0Deploy)(input); + if (exitCode !== 0) { + throw new SilentCLIError("v0 deploy exited unsuccessfully", { exitCode }); + } +} + /** * True when the spec declares none of the resources `removeAllResources` * clears, i.e. what an emptied project looks like. This is the up-front proxy diff --git a/src/handlers/project/deploy/screen.tsx b/src/handlers/project/deploy/screen.tsx index fcda1aa652..930b10f193 100644 --- a/src/handlers/project/deploy/screen.tsx +++ b/src/handlers/project/deploy/screen.tsx @@ -1,8 +1,11 @@ +import { useEffect } from "react"; +import { useApp } from "ink"; import { useNavigate } from "react-router"; import { ConfirmAction } from "../../../components/ConfirmAction"; import { DeploymentTargetPicker } from "../../../components/DeploymentTargetPicker"; import type { AwsDeploymentTarget } from "../../../projectSchemas/aws-targets"; import { GlobalConfigAccessorKey, ProjectKey, type Context } from "../../../router"; +import { TuiHandoffKey } from "../../../tui/handoff"; import { RegionKey } from "../../keys"; import type { ScreenProps } from "../../types"; import { ProjectGate } from "../ProjectGate"; @@ -40,22 +43,35 @@ export function DeployProjectScreen({ ctx, core }: ScreenProps) { description={DESCRIPTION} onBack={goBack} > - {({ targetName, target, back }) => ( - - )} + {({ targetName, target, back }) => + project.legacy ? ( + + ) : ( + + ) + } )} ); } +function LegacyDeployHandoff({ ctx, targetName }: { ctx: Context; targetName: string }) { + const { exit } = useApp(); + useEffect(() => { + ctx.value(TuiHandoffKey)?.(["deploy", "--target", targetName]); + exit(); + }, [ctx, exit, targetName]); + return null; +} + function DeployConfirm({ project, ctx, diff --git a/src/handlers/project/dev/index.test.ts b/src/handlers/project/dev/index.test.ts index ddaa996eae..ccca68cb30 100644 --- a/src/handlers/project/dev/index.test.ts +++ b/src/handlers/project/dev/index.test.ts @@ -19,6 +19,7 @@ import { TestCoreClient, TestGlobalConfigAccessor, testIO } from "../../../testi import { JsonRendererKey } from "../../../tui"; import { JsonKey, RegionKey } from "../../keys"; import type { DeployProjectInput, Project } from "../types"; +import type { V0DeployInput } from "../../../core/project/legacy/deploy"; import { ProjectSpecSchema } from "../../../projectSchemas/project"; import { BMA_POLICY_FILE, @@ -129,6 +130,7 @@ function harness(options: HarnessOptions = {}) { const collector = fakeCollector(); const environmentInputs: DevEnvironmentInput[] = []; const deployments: { project: Project; input: DeployProjectInput }[] = []; + const legacyDeployments: V0DeployInput[] = []; const resolutions: Parameters< DevProjectHandlerConfig["projectManager"]["resolveDeployedResource"] >[1][] = []; @@ -186,6 +188,10 @@ function harness(options: HarnessOptions = {}) { watchers.push({ path, onChange }); }, projectManager, + runV0Deploy: async (input) => { + legacyDeployments.push(input); + return 0; + }, waitReady: async () => { await Bun.sleep(5); }, @@ -206,6 +212,7 @@ function harness(options: HarnessOptions = {}) { collector, environmentInputs, deployments, + legacyDeployments, resolutions, harnessClient, io, @@ -244,6 +251,27 @@ async function inspectorStatus(subject: ReturnType): Promise<{ n } describe("project dev selection and dispatch", () => { + test("loads the environment and dispatches a translated v0 runtime", async () => { + const configuredProject = project(runtime()); + configuredProject.legacy = { + format: "v0", + v0Spec: {} as never, + extras: {} as never, + }; + const subject = harness({ project: configuredProject }); + + await subject.run({ agent: "orders" }); + + expect(subject.environmentInputs).toEqual([ + { + projectRoot: "/workspace/project", + runtime: expect.objectContaining({ name: "orders" }), + region: "us-west-2", + }, + ]); + expect(subject.codeZip.inputs).toHaveLength(1); + }); + test.each([ ["headless", undefined, project(bmaRuntime({ additionalPolicies: undefined }))], ["browser", undefined, project(bmaRuntime({ tags: undefined }))], @@ -662,6 +690,34 @@ async function inspectorRequest({ } describe("project dev harnesses", () => { + test("a v0 harness project uses the v0 deployer before continuing in v1 dev", async () => { + const configuredProject = harnessProject(); + configuredProject.legacy = { + format: "v0", + v0Spec: {} as never, + extras: { + abTests: [], + datasets: [], + capacityProviders: [], + unassignedTargets: [], + }, + }; + const subject = harness({ project: configuredProject }); + + await subject.route(["--target", "staging", "--yes"]); + + expect(subject.legacyDeployments).toEqual([ + { + projectRoot: configuredProject.rootPath, + target: "staging", + yes: true, + json: false, + }, + ]); + expect(subject.deployments).toEqual([]); + expect(subject.io.stderr()).toContain("running AgentCore CLI 0.31.1 deploy"); + }); + test.each([ { names: ["support"], args: [], json: false }, { names: ["orders", "support"], args: ["--mode", "headless"], json: true }, diff --git a/src/handlers/project/dev/index.ts b/src/handlers/project/dev/index.ts index 836123bd17..2b69458192 100644 --- a/src/handlers/project/dev/index.ts +++ b/src/handlers/project/dev/index.ts @@ -5,6 +5,7 @@ import type { InspectorDeps } from "../../../core/dev/inspector/types"; import { rewriteOtelEndpointForContainer } from "../../../core/dev/otel/collector"; import { findFreePort, resolveDevPort, resolveDevPorts } from "../../../core/dev/port"; import { projectSpecPath } from "../../../core/project/fsUtils"; +import type { V0DeployRunner } from "../../../core/project/legacy/deploy"; import { DevSupervisor, type SupervisorConfig } from "../../../core/dev/supervisor"; import type { ProjectRuntime } from "../../../projectSchemas/runtime"; import { @@ -53,6 +54,8 @@ export type DevProjectHandlerConfig = { harness: Pick; /** Overrides how the supervisor decides an agent is ready (defaults to a real TCP poll). */ waitReady?: SupervisorConfig["waitReady"]; + /** Runs the final v0 deployer when harness dev is opened from a v0 project. */ + runV0Deploy?: V0DeployRunner; }; /** Env for a spawned agent so its OTEL SDK reports to the collector as this runtime. */ diff --git a/src/handlers/project/index.ts b/src/handlers/project/index.ts index aa5abc71aa..06922d6a2c 100644 --- a/src/handlers/project/index.ts +++ b/src/handlers/project/index.ts @@ -2,6 +2,7 @@ import { type Handler } from "../../router"; import { checkPort, openBrowser, + runInheritedProcess, runProcess, startHttpServer, watchFile, @@ -27,9 +28,20 @@ import { createExportProjectResourceHandler } from "./export"; import { createProjectInvokeHandler } from "./invoke"; import { createProjectLogsHandler } from "./logs"; import { createProjectTracesHandler } from "./traces"; +import { executeV0Deploy, type V0DeployRunner } from "../../core/project/legacy/deploy"; -export function createProjectHandlers(core: Core, io: AppIO): Handler[] { +export type ProjectHandlerOptions = { + runV0Deploy?: V0DeployRunner; +}; + +export function createProjectHandlers( + core: Core, + io: AppIO, + options: ProjectHandlerOptions = {}, +): Handler[] { const projectManager: ProjectManager = core.projectManager; + const runLegacyDeploy = + options.runV0Deploy ?? ((input) => executeV0Deploy(input, runInheritedProcess)); const createHandler = createCreateProjectHandler({ projectManager, @@ -42,11 +54,13 @@ export function createProjectHandlers(core: Core, io: AppIO): Handler[] { // Returned in workflow order, which is the order `--help` and the TUI menu list them in: // the inner loop (dev, deploy, invoke), then observing it, then changing the project. // build is a step deploy already runs, so it goes last and the TUI menu hides it. - // migrate is a one-off upgrade from a v0 project, so it follows build; it - // finds the project itself because withProject can't parse a v0 project. + // migrate is a one-off upgrade from a v0 project, so it follows build. It + // locates the raw project itself because migration validates the source files + // before the compatibility loader translates them into the current shape. const projectBoundHandlers = [ createDevProjectHandler({ projectManager, + runV0Deploy: runLegacyDeploy, harness: core.harness, io, middlewares: [withProjectMiddleware], @@ -66,6 +80,7 @@ export function createProjectHandlers(core: Core, io: AppIO): Handler[] { createDeployProjectHandler({ projectManager, io, + runV0Deploy: runLegacyDeploy, middlewares: [withProjectMiddleware], }), createProjectInvokeHandler(core, io), diff --git a/src/handlers/project/status/screen.tsx b/src/handlers/project/status/screen.tsx index 6d6ad4a8fe..8ccab30a84 100644 --- a/src/handlers/project/status/screen.tsx +++ b/src/handlers/project/status/screen.tsx @@ -30,6 +30,8 @@ const DETAIL_ROUTES: Partial string>> harness: (id) => `/agentcore/harness/get/${encodeURIComponent(id)}`, memory: (id) => `/agentcore/memory/get/${encodeURIComponent(id)}`, gateway: (id) => `/agentcore/gateway/get/${encodeURIComponent(id)}`, + dataset: (id) => `/agentcore/eval/dataset/get/${encodeURIComponent(id)}`, + "ab-test": (id) => `/agentcore/eval/ab-test/get/${encodeURIComponent(id)}`, }; type StatusNode = LinkedResourceNode; diff --git a/src/handlers/project/status/status.screen.test.tsx b/src/handlers/project/status/status.screen.test.tsx index 5ffb92b7e1..ba28881487 100644 --- a/src/handlers/project/status/status.screen.test.tsx +++ b/src/handlers/project/status/status.screen.test.tsx @@ -18,6 +18,7 @@ import { waitForText, } from "../../../testing"; import type { Project, ResolvedProjectResource } from "../types"; +import { buildStatusNodes } from "./screen"; const cleanups: Array<() => Promise> = []; afterEach(cleanupScreens); @@ -122,6 +123,23 @@ function focusedLine(frame: string | undefined): string { } describe("project status screen", () => { + test("links deployed v0 datasets and A/B tests to their v1 detail screens", () => { + const nodes = buildStatusNodes(project({}).spec, [ + deployed("dataset", "orders", { arn: `${ARN}:dataset/dataset-orders` }), + deployed("ab-test", "checkout", { arn: `${ARN}:ab-test/ab-test-checkout` }), + deployed("capacity-provider", "workers", { + arn: `${ARN}:capacity-provider/workers-AbCdEf1234`, + }), + ]); + const children = nodes.find(({ id }) => id === "project")?.children; + + expect(children?.map(({ data }) => data)).toEqual([ + { route: "/agentcore/eval/dataset/get/dataset-orders" }, + { route: "/agentcore/eval/ab-test/get/ab-test-checkout" }, + { hint: "capacity-provider workers has no detail view." }, + ]); + }); + test("groups the runtime agent's Runtime and Memory beneath it", async () => { const screen = renderStatus(core()); diff --git a/src/handlers/project/types.ts b/src/handlers/project/types.ts index e0424d0780..be2e9bdc90 100644 --- a/src/handlers/project/types.ts +++ b/src/handlers/project/types.ts @@ -16,6 +16,7 @@ import type { PolicyEngineSchema, PolicySchema } from "../../projectSchemas/poli import type { AwsDeploymentTarget } from "../../projectSchemas/aws-targets"; import type { ProgressEvent } from "../../tui/progress"; import type { AwsCredentialProvider } from "../../core/types"; +import type { LegacyProjectInfo } from "../../core/project/legacy/types"; import { RuntimeTemplateProfileSchema } from "./templateProfile"; type CreateProjectInputBase = { @@ -292,6 +293,9 @@ export type DeployableResource = | "policy-engine" | "policy" | "config-bundle" + | "dataset" + | "ab-test" + | "capacity-provider" | "payment-manager" | "payment-connector" | "runtime-endpoint"; @@ -327,6 +331,8 @@ export type Project = { rootPath: string; /** The spec of the project (agentcore.json loaded into memory) */ spec: z.infer; + /** Present when a v0 project was translated into the current in-memory shape. */ + legacy?: LegacyProjectInfo; }; /** A line to add to agentcore/.env.local. Secret values travel here, never in the spec. */ diff --git a/src/io/exec.test.ts b/src/io/exec.test.ts index 787f96473c..7cfa109948 100644 --- a/src/io/exec.test.ts +++ b/src/io/exec.test.ts @@ -9,6 +9,7 @@ import { MissingToolError, ProcessFailedError, requireTool, + runInheritedProcess, runProcess, streamProcess, toolAvailable, @@ -99,6 +100,20 @@ describe("runProcess", () => { }); }); +describe("runInheritedProcess", () => { + test("returns the child exit code", async () => { + const failing = await script("inherit-fail.js", "process.exit(7)"); + + await expect(runInheritedProcess(["node", failing], { cwd: process.cwd() })).resolves.toBe(7); + }); + + test("rejects with ProcessFailedError when the executable cannot spawn", async () => { + await expect( + runInheritedProcess(["definitely-not-a-real-tool-xyz"], { cwd: process.cwd() }), + ).rejects.toBeInstanceOf(ProcessFailedError); + }); +}); + async function collect(events: AsyncIterable): Promise { const collected: ProcessEvent[] = []; for await (const event of events) collected.push(event); diff --git a/src/io/exec.ts b/src/io/exec.ts index d43bd3ca9e..23c0a64ad4 100644 --- a/src/io/exec.ts +++ b/src/io/exec.ts @@ -2,6 +2,7 @@ // because the npm bundle targets Node — Bun APIs are unavailable there. import { type ChildProcess, execFileSync, spawn, type SpawnOptions } from "node:child_process"; import { existsSync } from "node:fs"; +import { constants as osConstants } from "node:os"; import { delimiter, join } from "node:path"; import { createInterface } from "node:readline"; import { AgentCoreCLIError, ERROR_SOURCE } from "../errors"; @@ -71,7 +72,9 @@ export function cmdSpawnArgs(script: string, args: string[]): { file: string; ar } function spawnCommand(executable: string, args: string[], options: SpawnOptions): ChildProcess { - const script = isWindows ? windowsCommandScript(executable, process.env) : undefined; + const script = isWindows + ? windowsCommandScript(executable, options.env ?? process.env) + : undefined; if (!script) return spawn(executable, args, options); const resolved = cmdSpawnArgs(script, args); return spawn(resolved.file, resolved.args, { ...options, windowsVerbatimArguments: true }); @@ -108,6 +111,18 @@ export type RunProcessOptions = { /** Runs a subprocess to completion. Injectable so tests never spawn real processes. */ export type ProcessRunner = (command: string[], options: RunProcessOptions) => Promise; +export type InheritedProcessOptions = { + /** Working directory the process runs in. */ + cwd: string; + env?: NodeJS.ProcessEnv; +}; + +/** Runs an interactive subprocess with the current terminal attached. */ +export type InheritedProcessRunner = ( + command: string[], + options: InheritedProcessOptions, +) => Promise; + export type ProcessEvent = { type: "stdout"; line: string } | { type: "stderr"; line: string }; export type StreamProcessOptions = { @@ -167,6 +182,43 @@ export const runProcess: ProcessRunner = ( }); }; +/** + * Runs a subprocess with stdin/stdout/stderr inherited from the CLI and returns + * its exit code. This is intended for commands that fully own the terminal, + * including prompts and TUIs. + */ +export const runInheritedProcess: InheritedProcessRunner = ( + [executable, ...args], + { cwd, env }, +) => { + if (!executable) { + return Promise.reject(new ProcessFailedError([], cwd, null, "command is empty")); + } + + return new Promise((resolve, reject) => { + let child: ChildProcess; + try { + child = spawnCommand(executable, args, { cwd, env, stdio: "inherit" }); + } catch (error) { + reject(new ProcessFailedError([executable, ...args], cwd, null, String(error))); + return; + } + + child.once("error", (error) => { + reject(new ProcessFailedError([executable, ...args], cwd, null, String(error))); + }); + child.once("close", (exitCode, signal) => { + if (exitCode !== null) { + resolve(exitCode); + return; + } + + const signalNumber = signal ? osConstants.signals[signal] : undefined; + resolve(signalNumber === undefined ? 1 : 128 + signalNumber); + }); + }); +}; + /** * Runs a subprocess until it exits or is aborted, yielding complete output * lines while preserving their source stream. diff --git a/src/io/index.ts b/src/io/index.ts index c834a5492b..65211d8374 100644 --- a/src/io/index.ts +++ b/src/io/index.ts @@ -9,9 +9,12 @@ export { MissingToolError, ProcessFailedError, requireTool, + runInheritedProcess, runProcess, streamProcess, toolAvailable, + type InheritedProcessOptions, + type InheritedProcessRunner, type ProcessEvent, type ProcessRunner, type ProcessStreamer, diff --git a/src/projectSchemas/v0/README.md b/src/projectSchemas/v0/README.md new file mode 100644 index 0000000000..4d52e6e90e --- /dev/null +++ b/src/projectSchemas/v0/README.md @@ -0,0 +1,9 @@ +# Vendored v0 project schemas + +Frozen copy of `src/schema` from [aws/agentcore-cli@v0.31.1](https://github.com/aws/agentcore-cli/tree/v0.31.1/src/schema) +(tests and `llm-compacted/` omitted; `index.ts` replaced with a narrow, renamed export surface). + +These schemas read unmigrated v0 projects (`agentcore.json` with `version: 1`) for +compatibility mode and `agentcore migrate`. Do not edit or reformat them: the contract is +"anything v0 0.31.1 accepted is accepted here", and keeping the files byte-identical keeps +them diffable against upstream. Lint and Prettier ignore this directory. diff --git a/src/projectSchemas/v0/constants.ts b/src/projectSchemas/v0/constants.ts new file mode 100644 index 0000000000..ba56d0f069 --- /dev/null +++ b/src/projectSchemas/v0/constants.ts @@ -0,0 +1,296 @@ +import { z } from 'zod'; + +// ============================================================================ +// Feature Constants (shared across all schemas) +// ============================================================================ + +export const SDKFrameworkSchema = z.enum([ + 'Strands', + 'LangChain_LangGraph', + 'GoogleADK', + 'OpenAIAgents', + 'VercelAI', + 'BedrockManagedAgents', +]); +export type SDKFramework = z.infer; + +export const TargetLanguageSchema = z.enum(['Python', 'TypeScript', 'Other']); +export type TargetLanguage = z.infer; + +export const ModelProviderSchema = z.enum(['Bedrock', 'Gemini', 'OpenAI', 'Anthropic', 'LiteLLM']); +export type ModelProvider = z.infer; + +/** Providers that use credentials (Bedrock uses IAM, no credential needed). LiteLLM's API key is optional. */ +export const CREDENTIAL_PROVIDERS = ['Gemini', 'OpenAI', 'Anthropic', 'LiteLLM'] as const; + +/** + * Case-insensitively match a user-provided value against a Zod enum's options. + * Returns the canonical (correctly-cased) value, or undefined if no match. + */ +export function matchEnumValue(schema: { options: readonly string[] }, input: string): string | undefined { + const lower = input.toLowerCase(); + return schema.options.find(v => v.toLowerCase() === lower); +} + +/** Short names that --framework also accepts. */ +const SDK_FRAMEWORK_ALIASES: Readonly> = { bma: 'BedrockManagedAgents' }; + +/** Case-insensitively match a --framework value, including its short names. */ +export function matchSdkFramework(input: string): SDKFramework | undefined { + const lower = input.toLowerCase(); + if (Object.hasOwn(SDK_FRAMEWORK_ALIASES, lower)) return SDK_FRAMEWORK_ALIASES[lower]; + return matchEnumValue(SDKFrameworkSchema, input) as SDKFramework | undefined; +} + +/** + * Default model IDs used for each provider. + * These are the models generated in agent templates. + */ +export const DEFAULT_MODEL_IDS: Record = { + Bedrock: 'us.anthropic.claude-sonnet-4-5-20250514-v1:0', + Anthropic: 'claude-sonnet-4-5-20250514', + OpenAI: 'gpt-4.1', + Gemini: 'gemini-2.5-flash', + // LiteLLM model ids are provider-prefixed (e.g. "bedrock/...", "openai/gpt-4o"); no single default. + LiteLLM: 'bedrock/us.anthropic.claude-sonnet-4-5-20250514-v1:0', +}; + +/** + * Matrix defining which model providers are supported for each SDK framework. + * - Most SDKs support all 4 providers (Bedrock, Anthropic, OpenAI, Gemini) + * - GoogleADK only supports Gemini (uses Google's native API) + * - OpenAIAgents only supports OpenAI (uses OpenAI's native API) + */ +export const SDK_MODEL_PROVIDER_MATRIX: Record = { + // LiteLLM is supported for Strands (used by harness export) — it proxies to any provider. + Strands: ['Bedrock', 'Anthropic', 'OpenAI', 'Gemini', 'LiteLLM'] as const, + LangChain_LangGraph: ['Bedrock', 'Anthropic', 'OpenAI', 'Gemini'] as const, + GoogleADK: ['Gemini'] as const, + OpenAIAgents: ['OpenAI'] as const, + VercelAI: ['Bedrock', 'Anthropic', 'OpenAI', 'Gemini'] as const, + // BMA runs no model in the runtime: Bedrock Managed Agents (Mantle) runs Codex and calls in. + BedrockManagedAgents: ['Bedrock'] as const, +}; + +/** + * Returns the supported model providers for a given SDK framework. + */ +export function getSupportedModelProviders(sdk: SDKFramework): readonly ModelProvider[] { + return SDK_MODEL_PROVIDER_MATRIX[sdk]; +} + +/** + * Checks if a model provider is supported for a given SDK framework. + */ +export function isModelProviderSupported(sdk: SDKFramework, provider: ModelProvider): boolean { + return SDK_MODEL_PROVIDER_MATRIX[sdk].includes(provider); +} + +// ============================================================================ +// Reserved Project Names (Python package conflicts) +// ============================================================================ + +/** + * Project/agent names that would conflict with Python package names when + * creating a virtual environment. If the project directory name matches + * a dependency name, uv/pip will fail to resolve dependencies correctly. + * + * This list includes all dependencies used across SDK templates, normalized + * to valid project name format (lowercase, underscores replaced with nothing + * since project names are alphanumeric only). + */ +export const RESERVED_PROJECT_NAMES: readonly string[] = [ + // Core SDK packages + 'anthropic', + 'autogen', + 'autogenagentchat', + 'autogenext', + 'bedrock', + 'bedrockagentcore', + 'googleadk', + 'googlegenerativeai', + 'langchain', + 'langchainanthropic', + 'langchainaws', + 'langchaingooglegenai', + 'langchainmcpadapters', + 'langchainopenai', + 'langgraph', + 'mcp', + 'openai', + 'openaiagents', + 'strands', + 'strandsagents', + 'strandsagentstools', + // AG-UI adapter packages + 'agui', + 'aguistrands', + 'aguilanggraph', + 'aguiadk', + 'aguiprotocol', + 'vercelai', + 'aisdk', + // Common utilities + 'httpx', + 'pytest', + 'pytestasyncio', + 'pythondotenv', + // Build tools + 'hatchling', + 'setuptools', + 'wheel', + // AWS packages + 'awsopentelemetrydistro', + 'boto3', + 'botocore', + // Common Python stdlib/package names that could cause issues + 'test', + 'tests', + 'src', + 'lib', + 'dist', + 'build', + 'env', + 'venv', + 'site', + 'pip', + 'uv', +] as const; + +/** + * Check if a project name is reserved (case-insensitive). + */ +export function isReservedProjectName(name: string): boolean { + return RESERVED_PROJECT_NAMES.includes(name.toLowerCase()); +} + +// ============================================================================ +// Infrastructure Constants (shared between agent-env and mcp schemas) +// ============================================================================ + +export const PythonRuntimeSchema = z.enum(['PYTHON_3_10', 'PYTHON_3_11', 'PYTHON_3_12', 'PYTHON_3_13', 'PYTHON_3_14']); +export type PythonRuntime = z.infer; + +/** Default Python runtime version for new agents and MCP tools */ +export const DEFAULT_PYTHON_VERSION: PythonRuntime = 'PYTHON_3_14'; + +export const NodeRuntimeSchema = z.enum(['NODE_18', 'NODE_20', 'NODE_22']); +export type NodeRuntime = z.infer; + +/** Default Node.js runtime version for new TypeScript agents */ +export const DEFAULT_NODE_VERSION: NodeRuntime = 'NODE_22'; + +/** Combined runtime version schema supporting both Python and Node/TypeScript runtimes */ +export const RuntimeVersionSchema = z.union([PythonRuntimeSchema, NodeRuntimeSchema]); +export type RuntimeVersion = z.infer; + +/** Default entrypoint filename for each target language (create path). */ +export const DEFAULT_ENTRYPOINT_BY_LANGUAGE: Record<'Python' | 'TypeScript', string> = { + Python: 'main.py', + TypeScript: 'main.js', +}; + +/** Default runtime version for each target language (create path). */ +export const DEFAULT_RUNTIME_BY_LANGUAGE: Record<'Python' | 'TypeScript', RuntimeVersion> = { + Python: DEFAULT_PYTHON_VERSION, + TypeScript: DEFAULT_NODE_VERSION, +}; + +export const NetworkModeSchema = z.enum(['PUBLIC', 'VPC']); +export type NetworkMode = z.infer; + +// ============================================================================ +// AWS Network Resource ID Patterns (single source of truth) +// +// Canonical AWS resource ID format: lowercase hex, exactly 8 chars (legacy) or +// 17 chars (current). These are shared by NetworkConfigSchema (agent VPC config) +// and the auth/PrivateLink schema (ManagedVpcResource). All consumers must import +// from here rather than defining their own copies. +// ============================================================================ + +/** Matches a VPC ID: vpc- followed by 8 or 17 lowercase hex digits. */ +export const VPC_ID_PATTERN = /^vpc-(?:[0-9a-f]{8}|[0-9a-f]{17})$/; +/** Matches a subnet ID: subnet- followed by 8 or 17 lowercase hex digits. */ +export const SUBNET_ID_PATTERN = /^subnet-(?:[0-9a-f]{8}|[0-9a-f]{17})$/; +/** Matches a security group ID: sg- followed by 8 or 17 lowercase hex digits. */ +export const SECURITY_GROUP_ID_PATTERN = /^sg-(?:[0-9a-f]{8}|[0-9a-f]{17})$/; + +/** CodeBuild caps a project's VPC config at 5 security groups (vs 16 for the runtime). */ +export const MAX_CONTAINER_BUILD_SECURITY_GROUPS = 5; + +/** + * Whether a build runs the container-image pipeline (CodeBuild) and therefore requires an explicit + * `networkConfig.vpcId` in VPC mode — CodeBuild's CreateProject cannot infer the VPC from subnets + * alone. This is the single source of truth for "is this a container build?", shared by the schema + * refinements (agent-env + harness), the CLI validators, and the import/export vpcId-resolution + * guards so the decision cannot drift between them. + * + * A build is a container build when ANY of these hold: + * - `build === 'Container'` (agent specs, and harnesses whose build type resolved to Container), + * - it carries a `dockerfile` (from-source container harness), or + * - it carries a `containerUri` (prebuilt image harness — export still emits a `FROM ` + * Dockerfile stub that CodeBuild builds, so it needs a vpcId too). + */ +export function isContainerBuild(spec: { build?: string; containerUri?: string; dockerfile?: string }): boolean { + return spec.build === 'Container' || !!spec.containerUri || !!spec.dockerfile; +} + +// ============================================================================ +// Protocol Mode +// ============================================================================ + +export const ProtocolModeSchema = z.enum(['HTTP', 'MCP', 'A2A', 'AGUI']); +export type ProtocolMode = z.infer; + +/** + * Matrix defining which SDK frameworks are supported for each protocol mode. + * MCP is a standalone tool server with no framework. + */ +export const PROTOCOL_FRAMEWORK_MATRIX: Record = { + HTTP: ['Strands', 'LangChain_LangGraph', 'GoogleADK', 'OpenAIAgents', 'VercelAI', 'BedrockManagedAgents'] as const, + MCP: [] as const, + A2A: ['Strands', 'GoogleADK', 'LangChain_LangGraph'] as const, + AGUI: ['Strands', 'LangChain_LangGraph', 'GoogleADK'] as const, +}; + +/** + * Returns the supported SDK frameworks for a given protocol mode. + */ +export function getSupportedFrameworksForProtocol(protocol: ProtocolMode): readonly SDKFramework[] { + return PROTOCOL_FRAMEWORK_MATRIX[protocol]; +} + +/** + * Checks if a framework is supported for a given protocol mode. + */ +export function isFrameworkSupportedForProtocol(protocol: ProtocolMode, framework: SDKFramework): boolean { + return PROTOCOL_FRAMEWORK_MATRIX[protocol].includes(framework); +} + +/** + * Matrix defining which SDK frameworks ship templates for each target language. + * Vercel AI is TypeScript-only; the remaining frameworks are Python-only today. + * Used to keep framework pickers and validation in sync with the templates that + * actually exist under `assets//...`. + */ +export const LANGUAGE_FRAMEWORK_MATRIX = { + Python: ['Strands', 'LangChain_LangGraph', 'GoogleADK', 'OpenAIAgents', 'BedrockManagedAgents'], + TypeScript: ['Strands', 'VercelAI'], +} as const satisfies Record; + +/** Languages that scaffold from templates (excludes 'Other', which is BYO-only). */ +export type TemplateLanguage = keyof typeof LANGUAGE_FRAMEWORK_MATRIX; + +/** + * Returns the SDK frameworks that have templates for a given target language. + */ +export function getFrameworksForLanguage(language: TemplateLanguage): readonly SDKFramework[] { + return LANGUAGE_FRAMEWORK_MATRIX[language]; +} + +/** + * Checks if a framework has a template for a given target language. + */ +export function isFrameworkSupportedForLanguage(language: TemplateLanguage, framework: SDKFramework): boolean { + return getFrameworksForLanguage(language).includes(framework); +} diff --git a/src/projectSchemas/v0/index.ts b/src/projectSchemas/v0/index.ts new file mode 100644 index 0000000000..e57dd0c0d9 --- /dev/null +++ b/src/projectSchemas/v0/index.ts @@ -0,0 +1,21 @@ +/** + * Frozen copy of the v0 (0.31.1) project schemas, used only to read unmigrated + * v0 projects. Do not edit: the contract is "anything v0 0.31.1 accepted is + * accepted here". See README.md for provenance. + */ +export { + AgentCoreProjectSpecSchema as V0AgentCoreProjectSpecSchema, + type AgentCoreProjectSpec as V0ProjectSpec, +} from "./schemas/agentcore-project"; +export { + AwsDeploymentTargetsSchema as V0AwsDeploymentTargetsSchema, + type AwsDeploymentTarget as V0AwsDeploymentTarget, +} from "./schemas/aws-targets"; +export { + HarnessSpecSchema as V0HarnessSpecSchema, + type HarnessSpec as V0HarnessSpec, +} from "./schemas/primitives/harness"; +export { + DeployedStateSchema as V0DeployedStateSchema, + type DeployedState as V0DeployedState, +} from "./schemas/deployed-state"; diff --git a/src/projectSchemas/v0/schemas/agent-env.ts b/src/projectSchemas/v0/schemas/agent-env.ts new file mode 100644 index 0000000000..4f4f116d46 --- /dev/null +++ b/src/projectSchemas/v0/schemas/agent-env.ts @@ -0,0 +1,638 @@ +/** + * Agent Schema v2 - Clean, simplified model + * + * @module agent-env + */ +import { + MAX_CONTAINER_BUILD_SECURITY_GROUPS, + NetworkModeSchema, + ProtocolModeSchema, + RuntimeVersionSchema as RuntimeVersionSchemaFromConstants, + SECURITY_GROUP_ID_PATTERN, + SUBNET_ID_PATTERN, + VPC_ID_PATTERN, + isContainerBuild, +} from '../constants'; +import type { DirectoryPath, FilePath } from '../types'; +import { AuthorizerConfigSchema, RuntimeAuthorizerTypeSchema } from './auth'; +import { ConnectionSchema } from './connections'; +import { CapacityProviderConfigurationSchema, CapacityProviderVolumeNameSchema } from './primitives/capacity-provider'; +import { TagsSchema } from './primitives/tags'; +import { z } from 'zod'; + +// Re-export path types +export type { DirectoryPath, FilePath, PathType } from '../types'; +export type { PythonRuntime, NodeRuntime, RuntimeVersion, NetworkMode, ProtocolMode } from '../constants'; + +// ============================================================================ +// Name Schemas +// ============================================================================ + +// https://docs.aws.amazon.com/bedrock-agentcore-control/latest/APIReference/API_CreateAgentRuntime.html +export const AgentNameSchema = z + .string() + .min(1, 'Name is required') + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +export const EnvVarNameSchema = z + .string() + .min(1) + .max(255) + .regex( + /^[A-Za-z_][A-Za-z0-9_]*$/, + 'Must start with a letter or underscore, contain only letters, digits, and underscores' + ); + +// https://docs.aws.amazon.com/bedrock-agentcore-control/latest/APIReference/API_CreateGateway.html +export const GatewayNameSchema = z + .string() + .min(1) + .max(100) + .regex( + // eslint-disable-next-line security/detect-unsafe-regex -- input bounded to 100 chars by .max(100) above + /^[0-9a-zA-Z](?:[0-9a-zA-Z-]*[0-9a-zA-Z])?$/, + 'Gateway name must be alphanumeric with optional hyphens (max 100 chars)' + ); + +// ============================================================================ +// Common Types +// ============================================================================ + +/** Access level for resource sharing */ +export const AccessSchema = z.enum(['read', 'readwrite']); +export type Access = z.infer; + +// ============================================================================ +// Agent Schema +// ============================================================================ + +export const AgentTypeSchema = z.literal('AgentCoreRuntime'); +export type AgentType = z.infer; + +export const BuildTypeSchema = z.enum(['CodeZip', 'Container']); +export type BuildType = z.infer; + +// Use RuntimeVersionSchema from constants (supports both Python and Node/TypeScript) +// Not re-exported here to avoid duplicate export conflicts + +/** + * Entrypoint schema - supports both Python (.py) and TypeScript (.ts/.js) files. + * Python: main.py or main.py:handler + * TypeScript: main.ts, main.js, or index.ts + */ +export const EntrypointSchema = z + .string() + .min(1) + .regex( + // eslint-disable-next-line security/detect-unsafe-regex -- character class quantifiers don't cause backtracking + /^[a-zA-Z0-9_][a-zA-Z0-9_/.-]*\.(py|ts|js)(:[a-zA-Z_][a-zA-Z0-9_]*)?$/, + 'Must be a Python (.py) or TypeScript (.ts/.js) file path with optional handler (e.g., "main.py:handler" or "index.ts")' + ) as unknown as z.ZodType; + +const DirectoryPathSchema = z.string().min(1) as unknown as z.ZodType; + +// Char-safe set only (no backslash, spaces, or shell metacharacters): on deploy the buildspec +// interpolates this unquoted as `docker build -f $DOCKERFILE_PATH`. A leading '.' is allowed so +// conventional paths like '.docker/Dockerfile' pass. +const DOCKERFILE_PATH_ALLOWED_CHARS = /^[A-Za-z0-9._/-]+$/; + +/** + * True when `p` is a safe relative Dockerfile path within the build context: allowed chars only, no + * leading slash (absolute), and no empty ('' from a leading/trailing/double slash) or '..' segments. + * + * The single source of truth shared by `DockerfilePathSchema` (config-validation time) and the runtime + * `getDockerfilePath` guard, so the two can never diverge — e.g. one accepting '.docker/Dockerfile' + * while the other rejects it, or one accepting a trailing-slash directory value like 'docker/'. + */ +export function isValidDockerfilePath(p: string): boolean { + if (!DOCKERFILE_PATH_ALLOWED_CHARS.test(p)) return false; + if (p.startsWith('/')) return false; + return !p.split('/').some(segment => segment === '' || segment === '..'); +} + +/** + * Dockerfile location for Container builds, resolved relative to the Docker build context + * (`buildContextPath` when set, otherwise `codeLocation`). Accepts a filename ('Dockerfile', + * 'Dockerfile.gpu') or a forward-slash relative subpath ('docker/Dockerfile'). Absolute paths, + * trailing/double slashes, and '..' traversal are rejected so the Dockerfile can never escape or + * name the build context directory itself. + */ +const DockerfilePathSchema = z + .string() + .min(1) + .max(255) + .refine( + isValidDockerfilePath, + 'Must be a relative path within the build context: a filename or forward-slash subpath using only letters, digits, dot, dash, underscore, and slash; no leading slash, no ".." traversal, and no empty segments (no trailing or double slash)' + ); + +/** + * Build-arg names reserved by the CodeBuild build environment. On deploy each build arg becomes a + * CodeBuild environment-variable override alongside the buildspec's own control vars, so a colliding + * name would break the deploy build — a wrong image tag / ECR region, a rejected StartBuild, or a + * clobbered build-container shell. We reject the buildspec control vars, the process-critical shell + * vars, and CodeBuild's own `AWS_*` / `CODEBUILD_*` namespaces. This is a best-effort denylist (the + * shell has other sensitive vars), but it covers the realistic footguns and keeps a config that + * builds locally from failing only on deploy. + */ +export const RESERVED_BUILD_ARG_KEYS = [ + // Buildspec control vars (mirrored in @aws/agentcore-cdk's ContainerBuildProject / build handler). + 'ECR_REGISTRY', + 'IMAGE_URI', + 'DOCKERFILE_PATH', + 'BUILD_ARG_FLAGS', + // Overriding these in the build shell would break the buildspec's own commands (command lookup, + // word-splitting, dynamic linking) or redirect the docker client off the build daemon. Kept + // deliberately narrow to the genuinely-dangerous names so common ARGs (e.g. USER, LANG) stay usable. + 'PATH', + 'HOME', + 'IFS', + 'LD_PRELOAD', + 'LD_LIBRARY_PATH', + 'DOCKER_HOST', + 'DOCKER_CONFIG', + 'DOCKER_TLS_VERIFY', + 'DOCKER_CERT_PATH', +]; + +export function isReservedBuildArgKey(key: string): boolean { + return RESERVED_BUILD_ARG_KEYS.includes(key) || key.startsWith('CODEBUILD_') || key.startsWith('AWS_'); +} + +/** + * Build-arg value. Bounded and control-char-free because on deploy each value becomes a CodeBuild + * `environmentVariablesOverride` PLAINTEXT entry; newlines/control chars or an over-long value can be + * rejected by StartBuild, so we reject them at schema time rather than let a local-only-valid config + * fail on deploy. + */ +const BuildArgValueSchema = z + .string() + .max(4096, 'Build arg values must be at most 4096 characters') + .refine( + v => ![...v].some(ch => ch.charCodeAt(0) < 0x20 || ch.charCodeAt(0) === 0x7f), + 'Build arg values must not contain control characters (including newlines)' + ); + +export const EnvVarSchema = z.object({ + name: EnvVarNameSchema, + value: z.string(), +}); +export type EnvVar = z.infer; + +/** + * Instrumentation configuration for runtime observability. + */ +export const InstrumentationSchema = z.object({ + /** + * Enable OpenTelemetry instrumentation using aws-opentelemetry-distro. + * When enabled, the runtime entrypoint is wrapped with opentelemetry-instrument. + * Defaults to true for new runtimes. + */ + enableOtel: z.boolean().default(true), +}); +export type Instrumentation = z.infer; + +/** + * Network configuration for VPC mode. + * Required when networkMode is 'VPC'. + */ +export const NetworkConfigSchema = z.object({ + subnets: z.array(z.string().regex(SUBNET_ID_PATTERN, 'Must be a subnet id (subnet-...)')).min(1).max(16), + securityGroups: z + .array(z.string().regex(SECURITY_GROUP_ID_PATTERN, 'Must be a security group id (sg-...)')) + .min(1) + .max(16), + /** + * VPC ID. Required for Container builds in VPC mode because CodeBuild needs an explicit VPC ID; + * it cannot infer the VPC from subnets alone. Runtime/Lambda builds can omit this. + */ + vpcId: z.string().regex(VPC_ID_PATTERN, 'Must be a VPC id (vpc-...)').optional(), +}); +export type NetworkConfig = z.infer; + +/** + * Allowed request headers for the runtime. + * Per https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-header-allowlist.html + * any valid HTTP header name (alphanumeric, hyphens, underscores) may be allow-listed, + * provided it is not structurally reserved (x-amz-*, x-amzn-* except Runtime-Custom-*). + * Maximum 20 headers. + */ +export const HEADER_ALLOWLIST_PREFIX = 'X-Amzn-Bedrock-AgentCore-Runtime-Custom-'; +export const HEADER_NAME_PATTERN = /^[A-Za-z0-9\-_]+$/; +export const MAX_HEADER_ALLOWLIST_SIZE = 20; + +/** + * Validate a single allowlist header name. Returns null if valid, or a specific + * error message describing which rule the input violated. + * + * Note: 'x-amz-' and 'x-amzn-' are disjoint prefixes (position 5 differs: '-' vs 'n'), + * so the two checks below are independent. + */ +export function checkAllowlistHeader(val: string): string | null { + if (!HEADER_NAME_PATTERN.test(val)) { + return `Header name "${val}" must contain only alphanumeric characters, hyphens, and underscores.`; + } + const lower = val.toLowerCase(); + if (lower.startsWith('x-amz-')) { + return `Header "${val}" is not allowed. Headers starting with "x-amz-" are reserved for AWS request signing.`; + } + if (lower.startsWith('x-amzn-') && !lower.startsWith('x-amzn-bedrock-agentcore-runtime-custom-')) { + return `Header "${val}" is not allowed. Headers starting with "x-amzn-" are reserved, except for "X-Amzn-Bedrock-AgentCore-Runtime-Custom-*".`; + } + return null; +} + +export const RequestHeaderAllowlistSchema = z + .array( + z.string().superRefine((val, ctx) => { + const error = checkAllowlistHeader(val); + if (error) { + ctx.addIssue({ code: z.ZodIssueCode.custom, message: error }); + } + }) + ) + .max(MAX_HEADER_ALLOWLIST_SIZE, `Maximum ${MAX_HEADER_ALLOWLIST_SIZE} headers allowed`); + +/** + * Session storage configuration for filesystem persistence. + * Files written to mountPath persist across session stop/resume cycles. + */ +export const SessionStorageSchema = z.object({ + /** Absolute mount path under /mnt with exactly one subdirectory level (e.g. /mnt/data). */ + mountPath: z + .string() + .min(6) + .max(200) + .regex(/^\/mnt\/[a-zA-Z0-9._-]+\/?$/, 'Must be a path under /mnt with exactly one subdirectory (e.g. /mnt/data)'), +}); +export type SessionStorage = z.infer; + +export const EFS_ACCESS_POINT_ARN_PATTERN = + /^arn:aws[-a-z]*:elasticfilesystem:[a-z][a-z0-9-]*:[0-9]{12}:access-point\/fsap-[0-9a-f]{8,40}$/; + +export const S3_FILES_ACCESS_POINT_ARN_PATTERN = + /^arn:aws[-a-z]*:s3files:[a-z][a-z0-9-]*:[0-9]{12}:file-system\/fs-[0-9a-f]{17,40}\/access-point\/fsap-[0-9a-f]{17,40}$/; + +/** EFS access point mount configuration. Requires VPC network mode. */ +export const EfsAccessPointConfigSchema = z.object({ + /** ARN of an EFS access point. */ + accessPointArn: z + .string() + .regex( + EFS_ACCESS_POINT_ARN_PATTERN, + 'Must be an EFS access point ARN (arn:aws[-a-z]*:elasticfilesystem:{region}:{account}:access-point/fsap-{id})' + ), + /** Absolute mount path under /mnt (e.g. /mnt/tools). */ + mountPath: z + .string() + .min(6) + .max(200) + .regex(/^\/mnt\/[a-zA-Z0-9._-]+\/?$/, 'Must be a path under /mnt with exactly one subdirectory (e.g. /mnt/tools)'), +}); +export type EfsAccessPointConfig = z.infer; + +/** S3 Files access point mount configuration. Requires VPC network mode. */ +export const S3FilesAccessPointConfigSchema = z.object({ + /** ARN of an S3 Files access point. */ + accessPointArn: z + .string() + .regex( + S3_FILES_ACCESS_POINT_ARN_PATTERN, + 'Must be an S3 Files access point ARN (arn:aws[-a-z]*:s3files:{region}:{account}:file-system/fs-{id}/access-point/fsap-{id})' + ), + /** Absolute mount path under /mnt (e.g. /mnt/datasets). */ + mountPath: z + .string() + .min(6) + .max(200) + .regex( + /^\/mnt\/[a-zA-Z0-9._-]+\/?$/, + 'Must be a path under /mnt with exactly one subdirectory (e.g. /mnt/datasets)' + ), +}); +export type S3FilesAccessPointConfig = z.infer; + +/** Capacity provider volume mount — references a named volume on the attached CP. */ +export const CapacityProviderVolumeConfigSchema = z.object({ + /** Logical name of a volume defined on the attached capacity provider (CP's volumes[]). */ + volumeName: CapacityProviderVolumeNameSchema, + /** Absolute mount path under /mnt (e.g. /mnt/models). */ + mountPath: z + .string() + .min(6) + .max(200) + .regex(/^\/mnt\/[a-zA-Z0-9._-]+\/?$/, 'Must be a path under /mnt with exactly one subdirectory (e.g. /mnt/models)'), +}); +export type CapacityProviderVolumeConfig = z.infer; + +/** Maximum number of EFS access point mounts per runtime. */ +export const MAX_EFS_MOUNTS = 2; +/** Maximum number of S3 Files access point mounts per runtime. */ +export const MAX_S3_MOUNTS = 2; + +/** + * Filesystem configuration — union of four mount types. + * Exactly one key must be present per entry. + * + * Service limits per runtime: max 5 total, max 1 sessionStorage, + * max MAX_EFS_MOUNTS efsAccessPoint, max MAX_S3_MOUNTS s3FilesAccessPoint. + * efsAccessPoint and s3FilesAccessPoint require networkMode: VPC. + * capacityProviderVolume requires the runtime to be attached to a capacity provider. + */ +export const FilesystemConfigurationSchema = z.union([ + z.strictObject({ sessionStorage: SessionStorageSchema }), + z.strictObject({ efsAccessPoint: EfsAccessPointConfigSchema }), + z.strictObject({ s3FilesAccessPoint: S3FilesAccessPointConfigSchema }), + z.strictObject({ capacityProviderVolume: CapacityProviderVolumeConfigSchema }), +]); +export type FilesystemConfiguration = z.infer; + +/** Minimum allowed value for lifecycle timeout fields (seconds). */ +export const LIFECYCLE_TIMEOUT_MIN = 60; +/** Maximum allowed value for lifecycle timeout fields (seconds). */ +export const LIFECYCLE_TIMEOUT_MAX = 28800; + +/** + * Lifecycle configuration for runtime sessions. + * Controls idle timeout and max lifetime of runtime instances. + */ +export const LifecycleConfigurationSchema = z + .object({ + /** Idle session timeout in seconds. API default: 900s. */ + idleRuntimeSessionTimeout: z.number().int().min(LIFECYCLE_TIMEOUT_MIN).max(LIFECYCLE_TIMEOUT_MAX).optional(), + /** Max instance lifetime in seconds. API default: 28800s. */ + maxLifetime: z.number().int().min(LIFECYCLE_TIMEOUT_MIN).max(LIFECYCLE_TIMEOUT_MAX).optional(), + }) + .superRefine((data, ctx) => { + if (data.idleRuntimeSessionTimeout !== undefined && data.maxLifetime !== undefined) { + if (data.idleRuntimeSessionTimeout > data.maxLifetime) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'idleRuntimeSessionTimeout must be <= maxLifetime', + path: ['idleRuntimeSessionTimeout'], + }); + } + } + }); +export type LifecycleConfiguration = z.infer; + +// ============================================================================ +// Runtime Endpoint Schema +// ============================================================================ + +/** + * Endpoint name follows the AgentCore API regex for endpoint aliases. + */ +export const RuntimeEndpointNameSchema = z + .string() + .min(1, 'Endpoint name is required') + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +export const RuntimeEndpointSchema = z.object({ + /** Version number this endpoint points to. Must be >= 1. */ + version: z.number().int().min(1), + /** Optional human-readable description of this endpoint. */ + description: z.string().max(200).optional(), +}); + +export type RuntimeEndpoint = z.infer; + +/** + * AgentEnvSpec - represents an AgentCore Runtime. + * This is a top-level resource in the schema. + */ +export const AgentEnvSpecSchema = z + .object({ + name: AgentNameSchema, + /** Optional description for the runtime. */ + description: z.string().max(200).optional(), + build: BuildTypeSchema, + entrypoint: EntrypointSchema, + codeLocation: DirectoryPathSchema, + /** + * Dockerfile for Container builds, resolved relative to the build context (`buildContextPath` + * when set, otherwise `codeLocation`). A filename or a relative subpath; no traversal. Default: 'Dockerfile'. + */ + dockerfile: DockerfilePathSchema.optional(), + /** + * Docker build context directory for Container builds. When set, this directory (instead of + * `codeLocation`) is used as the `docker build` context and as the root the Dockerfile path is + * resolved against, so a single Dockerfile can be shared across multiple agents in a monorepo + * (e.g. so it can COPY files that live outside `codeLocation`). Container builds only. + * + * Like `codeLocation`, this is intentionally not containment-checked: the config author may point + * it at any directory (including a parent via `..` for a monorepo root). The unconditional + * secret-exclusion baseline on the deploy upload still applies to whatever directory is chosen. + */ + buildContextPath: DirectoryPathSchema.optional(), + /** + * Custom build arguments passed to `docker build` as `--build-arg` flags. Keys must be valid + * environment-variable names (each arg is forwarded to the build as an env var), reusing + * `EnvVarNameSchema`. Useful for parameterising a shared Dockerfile per agent + * (e.g. `{ "AGENT_NAME": "myagent" }`). Container builds only. + */ + customDockerBuildArgs: z.record(EnvVarNameSchema, BuildArgValueSchema).optional(), + runtimeVersion: RuntimeVersionSchemaFromConstants.optional(), + /** Environment variables to set on the runtime */ + envVars: z.array(EnvVarSchema).optional(), + /** Network mode for the runtime. Defaults to PUBLIC. */ + networkMode: NetworkModeSchema.optional(), + /** Network configuration for VPC mode. Required when networkMode is 'VPC'. */ + networkConfig: NetworkConfigSchema.optional(), + /** Instrumentation settings for observability. Defaults to OTel enabled. */ + instrumentation: InstrumentationSchema.optional(), + /** Protocol for the runtime (HTTP, MCP, A2A, AGUI). */ + protocol: ProtocolModeSchema.optional(), + /** Allowed request headers forwarded to the runtime at invocation time. */ + requestHeaderAllowlist: RequestHeaderAllowlistSchema.optional(), + /** ARN of an existing IAM execution role to use instead of creating a new one. */ + executionRoleArn: z.string().optional(), + /** + * Additional IAM policies attached to the runtime execution role. Each entry is either a + * managed-policy ARN (attached directly) or a `.json` policy-document file path relative to + * `codeLocation` (attached as an inline policy). For opaque AWS access (e.g. S3) the CLI does + * not model as a typed connection. + */ + additionalPolicies: z.array(z.string().min(1)).optional(), + /** Authorizer type for inbound requests. Defaults to AWS_IAM. */ + authorizerType: RuntimeAuthorizerTypeSchema.optional(), + /** Authorizer configuration. Required when authorizerType is CUSTOM_JWT. */ + authorizerConfiguration: AuthorizerConfigSchema.optional(), + tags: TagsSchema.optional(), + /** Lifecycle configuration for runtime sessions. */ + lifecycleConfiguration: LifecycleConfigurationSchema.optional(), + /** Filesystem configurations for session-scoped persistent storage. */ + filesystemConfigurations: z.array(FilesystemConfigurationSchema).optional(), + /** Named endpoints (version aliases) for this runtime. Keys are endpoint names. */ + endpoints: z.record(RuntimeEndpointNameSchema, RuntimeEndpointSchema).optional(), + /** Connections to external AgentCore resources (memory/gateway/runtime). The construct + * generates IAM + discovery env vars onto this runtime's execution role. */ + connections: z.array(ConnectionSchema).optional(), + /** Attach the runtime to a capacity provider (customer-managed EC2 compute) — either an + * in-project sibling by name or an external CP by ARN. Mutually exclusive with VPC networking: + * in CP mode the network topology comes from the capacity provider. */ + capacityProviderConfiguration: CapacityProviderConfigurationSchema.optional(), + }) + .superRefine((data, ctx) => { + if (data.networkMode === 'VPC' && !data.networkConfig) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'networkConfig is required when networkMode is VPC', + path: ['networkConfig'], + }); + } + if (data.networkMode !== 'VPC' && data.networkConfig) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'networkConfig is only allowed when networkMode is VPC', + path: ['networkConfig'], + }); + } + // Capacity-provider mode supplies its own network topology, so networkMode is not a settable + // property on a CP-attached runtime — neither VPC nor PUBLIC. The service derives networking + // from the capacity provider, so any explicit networkMode (or networkConfig) is rejected. + if (data.capacityProviderConfiguration && (data.networkMode !== undefined || data.networkConfig)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + 'capacityProviderConfiguration cannot be combined with a networkMode or VPC networking — a capacity provider supplies its own network topology, so leave networkMode/networkConfig unset', + path: ['capacityProviderConfiguration'], + }); + } + // NOTE: vpcId is NOT required here at the schema (read/write) level. A Container+VPC agent needs + // a vpcId to build (CodeBuild can't infer it), but enforcing that on read would hard-fail + // pre-existing agentcore.json files written before vpcId existed. Instead: the CLI input + // validators require --vpc-id for fresh Container+VPC creates, deploy backfills a missing vpcId + // from the subnets (ec2:DescribeSubnets) and persists it, and the CDK construct fails fast if it + // is still missing at synth. This keeps `status`/`remove`/`validate` working on old configs. + if ( + data.networkMode === 'VPC' && + isContainerBuild(data) && + data.networkConfig && + data.networkConfig.securityGroups.length > MAX_CONTAINER_BUILD_SECURITY_GROUPS + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Container builds in VPC mode allow at most ${MAX_CONTAINER_BUILD_SECURITY_GROUPS} security groups (CodeBuild limit)`, + path: ['networkConfig', 'securityGroups'], + }); + } + if (data.authorizerType === 'CUSTOM_JWT' && !data.authorizerConfiguration?.customJwtAuthorizer) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'authorizerConfiguration with customJwtAuthorizer is required when authorizerType is CUSTOM_JWT', + path: ['authorizerConfiguration'], + }); + } + if (data.authorizerType !== 'CUSTOM_JWT' && data.authorizerConfiguration) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'authorizerConfiguration is only allowed when authorizerType is CUSTOM_JWT', + path: ['authorizerConfiguration'], + }); + } + // Container-only fields. If adding more, extend this list (and consider consolidating into a + // containerConfig object — see the networkConfig pattern). + for (const field of ['dockerfile', 'buildContextPath', 'customDockerBuildArgs'] as const) { + if (data.build !== 'Container' && data[field]) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `${field} is only allowed for Container builds`, + path: [field], + }); + } + } + for (const key of Object.keys(data.customDockerBuildArgs ?? {})) { + if (isReservedBuildArgKey(key)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `customDockerBuildArgs key "${key}" is reserved by the build environment (must not be ${RESERVED_BUILD_ARG_KEYS.join(', ')}, or start with CODEBUILD_ or AWS_)`, + path: ['customDockerBuildArgs', key], + }); + } + } + const fcs = data.filesystemConfigurations ?? []; + if (fcs.length > 0) { + const efsCount = fcs.filter(fc => 'efsAccessPoint' in fc).length; + const s3Count = fcs.filter(fc => 's3FilesAccessPoint' in fc).length; + const ssCount = fcs.filter(fc => 'sessionStorage' in fc).length; + const cpVolCount = fcs.filter(fc => 'capacityProviderVolume' in fc).length; + + // A capacity-provider volume can only be mounted when the runtime is attached to a + // capacity provider — the volume is defined on that CP's volumes[]. + if (cpVolCount > 0 && !data.capacityProviderConfiguration) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + 'capacityProviderVolume filesystem mounts require the runtime to be attached to a capacity provider (set capacityProviderConfiguration)', + path: ['filesystemConfigurations'], + }); + } + + if (fcs.length > 5) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Maximum 5 filesystem configurations allowed', + path: ['filesystemConfigurations'], + }); + } + if (efsCount > MAX_EFS_MOUNTS) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Maximum ${MAX_EFS_MOUNTS} efsAccessPoint configurations allowed`, + path: ['filesystemConfigurations'], + }); + } + if (s3Count > MAX_S3_MOUNTS) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Maximum ${MAX_S3_MOUNTS} s3FilesAccessPoint configurations allowed`, + path: ['filesystemConfigurations'], + }); + } + if (ssCount > 1) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Maximum 1 sessionStorage configuration allowed', + path: ['filesystemConfigurations'], + }); + } + + const hasByo = efsCount > 0 || s3Count > 0; + if (hasByo && data.networkMode !== 'VPC') { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'efsAccessPoint and s3FilesAccessPoint filesystem mounts require networkMode: VPC', + path: ['filesystemConfigurations'], + }); + } + + const mountPaths = fcs.map(fc => + ('sessionStorage' in fc + ? fc.sessionStorage.mountPath + : 'efsAccessPoint' in fc + ? fc.efsAccessPoint.mountPath + : 's3FilesAccessPoint' in fc + ? fc.s3FilesAccessPoint.mountPath + : fc.capacityProviderVolume.mountPath + ).replace(/\/$/, '') + ); + if (new Set(mountPaths).size !== mountPaths.length) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Filesystem mount paths must be unique', + path: ['filesystemConfigurations'], + }); + } + } + }); + +export type AgentEnvSpec = z.infer; diff --git a/src/projectSchemas/v0/schemas/agentcore-project.ts b/src/projectSchemas/v0/schemas/agentcore-project.ts new file mode 100644 index 0000000000..eaf62dd131 --- /dev/null +++ b/src/projectSchemas/v0/schemas/agentcore-project.ts @@ -0,0 +1,797 @@ +/** + * AgentCore Project Schema - Resource-centric model + * + * Flat resource model where agents, memories, and credentials are top-level. + * All resources within a project implicitly have access to each other. + * + * @module agentcore-project + */ +import { isReservedProjectName } from '../constants'; +import { AgentEnvSpecSchema } from './agent-env'; +import { AgentCoreGatewaySchema, AgentCoreGatewayTargetSchema, AgentCoreMcpRuntimeToolSchema } from './mcp'; +import { ABTestSchema } from './primitives/ab-test'; +import { CapacityProviderSchema } from './primitives/capacity-provider'; +import { ConfigBundleSchema } from './primitives/config-bundle'; +import { DatasetSchema } from './primitives/dataset'; +import { + EvaluationLevelSchema, + EvaluatorConfigSchema, + EvaluatorNameSchema, + KmsKeyArnSchema, +} from './primitives/evaluator'; +import { HarnessNameSchema } from './primitives/harness'; +import { KnowledgeBaseSchema } from './primitives/knowledge-base'; +import { + DEFAULT_EPISODIC_REFLECTION_NAMESPACES, + DEFAULT_EPISODIC_REFLECTION_NAMESPACE_TEMPLATES, + DEFAULT_STRATEGY_NAMESPACES, + DEFAULT_STRATEGY_NAMESPACE_TEMPLATES, + MemoryStrategySchema, + MemoryStrategyTypeSchema, +} from './primitives/memory'; +import { OnlineEvalConfigSchema } from './primitives/online-eval-config'; +import { + DEFAULT_AUTO_PAYMENT, + DEFAULT_SPEND_LIMIT, + PaymentAuthorizerTypeSchema, + PaymentConnectorNameSchema, + PaymentConnectorSchema, + PaymentManagerNameSchema, + PaymentManagerSchema, + PaymentProviderSchema, + PaymentProvisionModeSchema, +} from './primitives/payment'; +import { PolicyEngineSchema } from './primitives/policy'; +import { TagsSchema } from './primitives/tags'; +import { uniqueBy } from './zod-util'; +import { z } from 'zod'; + +// Re-export for convenience +export { + DEFAULT_EPISODIC_REFLECTION_NAMESPACE_TEMPLATES, + DEFAULT_EPISODIC_REFLECTION_NAMESPACES, + DEFAULT_STRATEGY_NAMESPACE_TEMPLATES, + DEFAULT_STRATEGY_NAMESPACES, + MemoryStrategySchema, + MemoryStrategyTypeSchema, +}; +export { EvaluationLevelSchema }; +export type { MemoryStrategy, MemoryStrategyType } from './primitives/memory'; +export type { OnlineEvalConfig } from './primitives/online-eval-config'; +export { OnlineEvalConfigSchema, OnlineEvalConfigNameSchema } from './primitives/online-eval-config'; +export type { + CodeBasedConfig, + EvaluationLevel, + EvaluatorConfig, + ExternalCodeBasedConfig, + LlmAsAJudgeConfig, + ManagedCodeBasedConfig, + RatingScale, +} from './primitives/evaluator'; +export { + BedrockModelIdSchema, + isValidBedrockModelId, + EvaluatorNameSchema, + KMS_KEY_ARN_PATTERN, + isValidKmsKeyArn, +} from './primitives/evaluator'; +export { ConfigBundleSchema }; +export type { ComponentConfiguration, ComponentConfigurationMap, ConfigBundle } from './primitives/config-bundle'; +export { ConfigBundleNameSchema, ComponentConfigurationMapSchema } from './primitives/config-bundle'; +export { PolicyEngineSchema }; +export type { AuthorizationPhase, EnforcementMode, Policy, PolicyEngine, ValidationMode } from './primitives/policy'; +export { + AuthorizationPhaseSchema, + EnforcementModeSchema, + PolicyEngineNameSchema, + PolicyNameSchema, + PolicySchema, + ValidationModeSchema, +} from './primitives/policy'; +export { TagsSchema }; +export type { Tags } from './primitives/tags'; +export { DatasetSchema }; +export { DatasetNameSchema, DatasetSchemaTypeSchema } from './primitives/dataset'; +export type { Dataset, DatasetSchemaType } from './primitives/dataset'; +export { CapacityProviderSchema }; +export { + CapacityProviderArnSchema, + CapacityProviderConfigurationSchema, + CapacityProviderNameSchema, + CapacityProviderVolumeNameSchema, + CAPACITY_PROVIDER_ARN_PATTERN, + CAPACITY_PROVIDER_OPERATOR_ROLE_ARN_PATTERN, + isCapacityProviderArn, + isValidOperatorRoleArn, + OperatingSystemSchema, + OperatorRoleArnSchema, +} from './primitives/capacity-provider'; +export type { CapacityProvider, CapacityProviderConfiguration, OperatingSystem } from './primitives/capacity-provider'; +export type { ABTestMode, TargetRef, GatewayFilter, PerVariantOnlineEvaluationConfig } from './primitives/ab-test'; +export { ABTestModeSchema, TargetRefSchema, GatewayFilterSchema } from './primitives/ab-test'; +export type { + BedrockApiFormat, + HarnessApiFormat, + HarnessGatewayOutboundAuth, + HarnessMemoryRef, + HarnessModel, + HarnessModelProvider, + HarnessSpec, + ManagedMemoryStrategy, + OpenAiApiFormat, +} from './primitives/harness'; +export { + BedrockApiFormatSchema, + HarnessApiFormatSchema, + OpenAiApiFormatSchema, + GatewayOAuthGrantTypeSchema, + HarnessGatewayOutboundAuthSchema, + HarnessModelProviderSchema, + HarnessNameSchema, + HarnessSpecSchema, + HarnessToolTypeSchema, + ManagedMemoryStrategySchema, + validateApiFormat, +} from './primitives/harness'; +export type { + KnowledgeBase, + DataSource, + S3DataSource, + ConnectorDataSourceType, + ConnectorFileDataSource, +} from './primitives/knowledge-base'; +export { + KnowledgeBaseNameSchema, + KnowledgeBaseSchema, + S3DataSourceSchema, + DataSourceSchema, + ConnectorDataSourceTypeSchema, + ConnectorFileDataSourceSchema, +} from './primitives/knowledge-base'; +export { + DEFAULT_AUTO_PAYMENT, + DEFAULT_SPEND_LIMIT, + PaymentManagerSchema, + PaymentManagerNameSchema, + PaymentConnectorSchema, + PaymentConnectorNameSchema, + PaymentProviderSchema, + PaymentProvisionModeSchema, + PaymentAuthorizerTypeSchema, +}; +export type { + PaymentManager, + PaymentConnector, + PaymentProvider, + PaymentProvisionMode, + PaymentAuthorizerType, +} from './primitives/payment'; + +// ============================================================================ +// ManagedBy Schema +// ============================================================================ + +export const ManagedBySchema = z.enum(['CDK']).default('CDK'); +export type ManagedBy = z.infer; + +// Re-export MCP types (now part of unified schema) +export type { AgentCoreGateway, AgentCoreGatewayTarget, AgentCoreMcpRuntimeTool } from './mcp'; +export { AgentCoreGatewaySchema, AgentCoreGatewayTargetSchema, AgentCoreMcpRuntimeToolSchema } from './mcp'; + +// ============================================================================ +// Project Name Schema +// ============================================================================ + +// Project name is a CLI-only concept (combined with agent name to form the runtime name). +// Max 23 so that projectName + "_" + agentName fits within the 48-char runtime name limit. +export const ProjectNameSchema = z + .string() + .min(1, 'Project name is required') + .max(23, 'Project name must be 23 characters or less') + .regex( + /^[A-Za-z][A-Za-z0-9]{0,22}$/, + 'Project name must start with a letter and contain only alphanumeric characters' + ) + .refine(name => !isReservedProjectName(name), { + message: 'This name conflicts with a reserved package dependency. Please choose a different name.', + }); + +// ============================================================================ +// Memory Schema +// ============================================================================ + +export const MemoryTypeSchema = z.literal('AgentCoreMemory'); +export type MemoryType = z.infer; + +// Memory names follow the same constraints as agent runtime names. +// https://docs.aws.amazon.com/bedrock-agentcore-control/latest/APIReference/API_CreateMemory.html +export const MemoryNameSchema = z + .string() + .min(1, 'Name is required') + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +export const StreamContentLevelSchema = z.enum(['FULL_CONTENT', 'METADATA_ONLY']); +export type StreamContentLevel = z.infer; + +// TODO: kinesis is currently the only supported delivery type. When additional types +// (e.g. S3, EventBridge) are added, this should become a discriminated union. +// Non-kinesis resources will produce a Zod error about the missing kinesis field. +export const StreamDeliveryResourcesSchema = z.object({ + resources: z + .array( + z.object({ + kinesis: z.object({ + dataStreamArn: z.string().min(1), + contentConfigurations: z + .array( + z.object({ + type: z.literal('MEMORY_RECORDS'), + level: StreamContentLevelSchema, + }) + ) + .min(1), + }), + }) + ) + .min(1), +}); + +export type StreamDeliveryResources = z.infer; + +export const IndexedKeyTypeSchema = z.enum(['STRING', 'STRINGLIST', 'NUMBER']); +export type IndexedKeyType = z.infer; + +/** + * Indexed metadata key declaration on a Memory. + * Indexed keys enable filtering memory records on retrieval by attached metadata. + * + * Key pattern matches the AgentCore Control API: alphanumeric characters, whitespace, + * and the symbols `. _ : / = + @ -` (max 128 chars). + * + * Note: indexed keys are append-only on the AWS service side — once added to a Memory, + * a key cannot be removed. Reducing the array on update will fail at deploy time. + */ +export const INDEXED_KEY_NAME_PATTERN = /^[a-zA-Z0-9\s._:/=+@-]+$/; +export const INDEXED_KEY_NAME_PATTERN_MESSAGE = + 'Must contain only alphanumeric characters, whitespace, or the symbols . _ : / = + @ -'; +export const MAX_INDEXED_KEY_NAME_LENGTH = 128; +export const MAX_INDEXED_KEYS = 10; + +export const IndexedKeySchema = z.object({ + key: z + .string() + .min(1) + .max(MAX_INDEXED_KEY_NAME_LENGTH) + .regex(INDEXED_KEY_NAME_PATTERN, INDEXED_KEY_NAME_PATTERN_MESSAGE) + .refine(s => s.trim().length > 0, 'Key cannot be only whitespace'), + type: IndexedKeyTypeSchema, +}); +export type IndexedKey = z.infer; + +export const MemorySchema = z + .object({ + name: MemoryNameSchema, + eventExpiryDuration: z.number().int().min(3).max(365), + // Strategies array can be empty for short-term memory (just base memory with expiration) + // Long-term memory includes strategies like SEMANTIC, SUMMARIZATION, USER_PREFERENCE + strategies: z + .array(MemoryStrategySchema) + .default([]) + .superRefine( + uniqueBy( + strategy => strategy.type, + type => `Duplicate memory strategy type: ${type}` + ) + ), + indexedKeys: z + .array(IndexedKeySchema) + .max(MAX_INDEXED_KEYS) + .superRefine( + uniqueBy( + entry => entry.key, + key => `Duplicate indexed key: ${key}` + ) + ) + .optional(), + tags: TagsSchema.optional(), + encryptionKeyArn: z.string().optional(), + executionRoleArn: z.string().optional(), + streamDeliveryResources: StreamDeliveryResourcesSchema.optional(), + }) + .superRefine((memory, ctx) => { + // Indexed keys filter long-term memory records on retrieval; they have no + // meaning on a short-term-only memory (no strategies => no LTM records). + if (memory.indexedKeys && memory.indexedKeys.length > 0 && memory.strategies.length === 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ['indexedKeys'], + message: 'indexedKeys requires at least one memory strategy (long-term memory)', + }); + } + }); + +export type Memory = z.infer; + +// ============================================================================ +// Credential Schema +// ============================================================================ + +// https://docs.aws.amazon.com/bedrock-agentcore-control/latest/APIReference/API_CreateApiKeyCredentialProvider.html +export const CredentialNameSchema = z + .string() + .min(1, 'Credential name is required') + .max(128, 'Credential name must be 128 characters or less') + .regex(/^[a-zA-Z0-9\-_]+$/, 'Must contain only alphanumeric characters, hyphens, and underscores (1-128 chars)'); + +export const CredentialTypeSchema = z.enum([ + 'ApiKeyCredentialProvider', + 'OAuthCredentialProvider', + 'PaymentCredentialProvider', +]); +export type CredentialType = z.infer; + +export const ApiKeyCredentialSchema = z.object({ + authorizerType: z.literal('ApiKeyCredentialProvider'), + name: CredentialNameSchema, +}); + +export type ApiKeyCredential = z.infer; + +export const OAuthCredentialSchema = z.object({ + authorizerType: z.literal('OAuthCredentialProvider'), + name: CredentialNameSchema, + /** OIDC discovery URL for the OAuth provider (optional for imported providers that already exist in Identity service) */ + discoveryUrl: z.string().url().optional(), + /** Scopes this credential provider supports */ + scopes: z.array(z.string()).optional(), + /** Credential provider vendor type */ + vendor: z.string().default('CustomOauth2'), + /** Whether this credential was auto-created by the CLI (e.g., for CUSTOM_JWT inbound auth) */ + managed: z.boolean().optional(), + /** Whether this credential is used for inbound or outbound auth */ + usage: z.enum(['inbound', 'outbound']).optional(), +}); + +export type OAuthCredential = z.infer; + +export const PaymentCredentialSchema = z.object({ + authorizerType: z.literal('PaymentCredentialProvider'), + name: CredentialNameSchema, + provider: PaymentProviderSchema, +}); + +export type PaymentCredential = z.infer; + +export const CredentialSchema = z.discriminatedUnion('authorizerType', [ + ApiKeyCredentialSchema, + OAuthCredentialSchema, + PaymentCredentialSchema, +]); + +export type Credential = z.infer; + +// ============================================================================ +// Evaluator Schema +// ============================================================================ + +export const EvaluatorTypeSchema = z.literal('CustomEvaluator'); +export type EvaluatorType = z.infer; + +export const EvaluatorSchema = z.object({ + name: EvaluatorNameSchema, + level: EvaluationLevelSchema, + description: z.string().optional(), + config: EvaluatorConfigSchema, + kmsKeyArn: KmsKeyArnSchema.optional(), + tags: TagsSchema.optional(), +}); + +export type Evaluator = z.infer; + +// ============================================================================ +// Harness Registry Schema +// ============================================================================ + +export const HarnessRegistryEntrySchema = z.object({ + name: HarnessNameSchema, + path: z.string().min(1, 'Path to harness config directory is required'), +}); + +export type HarnessRegistryEntry = z.infer; + +// ============================================================================ +// Project Schema (Top Level) +// ============================================================================ + +const BUILTIN_EVALUATOR_PREFIX = 'Builtin.'; +const ARN_PREFIX = 'arn:'; + +export const AgentCoreProjectSpecSchema = z + .object({ + $schema: z.string().optional(), + name: ProjectNameSchema, + version: z.number().int().min(1), + managedBy: ManagedBySchema, + tags: TagsSchema.optional(), + + runtimes: z + .array(AgentEnvSpecSchema) + .default([]) + .superRefine( + uniqueBy( + agent => agent.name, + name => `Duplicate agent name: ${name}` + ) + ), + + memories: z + .array(MemorySchema) + .default([]) + .superRefine( + uniqueBy( + memory => memory.name, + name => `Duplicate memory name: ${name}` + ) + ), + + knowledgeBases: z + .array(KnowledgeBaseSchema) + .default([]) + .superRefine( + uniqueBy( + kb => kb.name, + name => `Duplicate knowledge base name: ${name}` + ) + ), + + credentials: z + .array(CredentialSchema) + .default([]) + .superRefine( + uniqueBy( + credential => credential.name, + name => `Duplicate credential name: ${name}` + ) + ), + + evaluators: z + .array(EvaluatorSchema) + .default([]) + .superRefine( + uniqueBy( + evaluator => evaluator.name, + name => `Duplicate evaluator name: ${name}` + ) + ), + + onlineEvalConfigs: z + .array(OnlineEvalConfigSchema) + .default([]) + .superRefine( + uniqueBy( + config => config.name, + name => `Duplicate online eval config name: ${name}` + ) + ), + + // MCP / Gateway resources (previously in mcp.json) + agentCoreGateways: z + .array(AgentCoreGatewaySchema) + .default([]) + .superRefine( + uniqueBy( + gateway => gateway.name, + name => `Duplicate gateway name: ${name}` + ) + ), + + mcpRuntimeTools: z + .array(AgentCoreMcpRuntimeToolSchema) + .optional() + .superRefine((tools, ctx) => { + if (!tools) return; + uniqueBy( + (tool: { name: string }) => tool.name, + (name: string) => `Duplicate MCP runtime tool name: ${name}` + )(tools, ctx); + }), + + unassignedTargets: z + .array(AgentCoreGatewayTargetSchema) + .optional() + .superRefine((targets, ctx) => { + if (!targets) return; + uniqueBy( + (target: { name: string }) => target.name, + (name: string) => `Duplicate unassigned target name: ${name}` + )(targets, ctx); + }), + + policyEngines: z + .array(PolicyEngineSchema) + .default([]) + .superRefine( + uniqueBy( + engine => engine.name, + name => `Duplicate policy engine name: ${name}` + ) + ), + + configBundles: z + .array(ConfigBundleSchema) + .default([]) + .superRefine( + uniqueBy( + bundle => bundle.name, + name => `Duplicate config bundle name: ${name}` + ) + ), + + abTests: z + .array(ABTestSchema) + .default([]) + .superRefine( + uniqueBy( + test => test.name, + name => `Duplicate AB test name: ${name}` + ) + ), + + harnesses: z + .array(HarnessRegistryEntrySchema) + .default([]) + .superRefine( + uniqueBy( + harness => harness.name, + name => `Duplicate harness name: ${name}` + ) + ), + + datasets: z + .array(DatasetSchema) + .optional() + .superRefine((val, ctx) => { + if (!val) return; + const seen = new Set(); + for (const dataset of val) { + if (seen.has(dataset.name)) { + ctx.addIssue({ code: z.ZodIssueCode.custom, message: `Duplicate dataset name: ${dataset.name}` }); + } + seen.add(dataset.name); + } + }), + + capacityProviders: z + .array(CapacityProviderSchema) + .optional() + .superRefine((items, ctx) => { + if (!items) return; + uniqueBy( + (cp: { name: string }) => cp.name, + (name: string) => `Duplicate capacity provider name: ${name}` + )(items, ctx); + }), + + httpGateways: z + .array(z.unknown()) + .max( + 0, + '"httpGateways" is deprecated. Migrate to agentCoreGateways with protocolType: "None", or use "agentcore import gateway".' + ) + .optional(), + + payments: z + .array(PaymentManagerSchema) + .optional() + .superRefine((items, ctx) => { + if (!items) return; + uniqueBy( + (manager: { name: string }) => manager.name, + (name: string) => `Duplicate payment manager name: ${name}` + )(items, ctx); + }), + }) + .strict() + .superRefine((spec, ctx) => { + const agentNames = new Set(spec.runtimes.map(a => a.name)); + const evaluatorNames = new Set(spec.evaluators.map(e => e.name)); + + for (const config of spec.onlineEvalConfigs) { + // Validate agent reference (only when agent is specified — custom log groups don't need one) + if (config.agent && !agentNames.has(config.agent)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Online eval config "${config.name}" references unknown agent "${config.agent}"`, + }); + } + + // Validate evaluator references + for (const evalName of config.evaluators ?? []) { + // Skip built-in evaluators and ARN references (externally managed) + if (evalName.startsWith(BUILTIN_EVALUATOR_PREFIX) || evalName.startsWith(ARN_PREFIX)) continue; + if (!evaluatorNames.has(evalName)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Online eval config "${config.name}" references unknown evaluator "${evalName}"`, + }); + } + } + } + + // Validate httpRuntime target runtime references + for (const gw of spec.agentCoreGateways ?? []) { + for (const target of gw.targets) { + if (target.targetType === 'httpRuntime') { + if (target.httpRuntime?.runtime) { + const runtimeExists = spec.runtimes.some(r => r.name === target.httpRuntime!.runtime); + if (!runtimeExists) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Gateway "${gw.name}" target "${target.name}" references unknown runtime "${target.httpRuntime.runtime}". Check spec.runtimes.`, + }); + } else if (target.httpRuntime.runtimeEndpoint && target.httpRuntime.runtimeEndpoint !== 'DEFAULT') { + const runtime = spec.runtimes.find(r => r.name === target.httpRuntime!.runtime); + if (runtime && !runtime.endpoints?.[target.httpRuntime.runtimeEndpoint]) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Gateway "${gw.name}" target "${target.name}" references endpoint "${target.httpRuntime.runtimeEndpoint}" which does not exist on runtime "${target.httpRuntime.runtime}".`, + }); + } + } + } + } + } + } + + // Validate runtime -> capacity-provider sibling references. A runtime may attach to a + // capacity provider by name (an in-project sibling) or by ARN (external). A name must + // resolve to a capacityProviders[] entry; ARNs are accepted as external and not checked here. + const capacityProvidersByName = new Map((spec.capacityProviders ?? []).map(cp => [cp.name, cp])); + for (const runtime of spec.runtimes) { + const cpName = runtime.capacityProviderConfiguration?.capacityProviderName; + if (cpName && !capacityProvidersByName.has(cpName)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Runtime "${runtime.name}" references unknown capacity provider "${cpName}". Check spec.capacityProviders.`, + }); + } + + // A capacityProviderVolume mount must reference a volume defined on the attached CP. We can + // only introspect an in-project sibling (by name); an external CP referenced by ARN is skipped. + const cpVolumeMounts = (runtime.filesystemConfigurations ?? []).filter(fc => 'capacityProviderVolume' in fc); + if (cpVolumeMounts.length > 0 && cpName) { + const cp = capacityProvidersByName.get(cpName); + if (cp) { + const definedVolumeNames = new Set( + (cp.computeConfiguration.ec2Configuration.volumes ?? []).map(v => v.ebsConfiguration.name) + ); + for (const fc of cpVolumeMounts) { + const volumeName = (fc as { capacityProviderVolume: { volumeName: string } }).capacityProviderVolume + .volumeName; + if (!definedVolumeNames.has(volumeName)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Runtime "${runtime.name}" mounts capacity provider volume "${volumeName}" which is not defined on capacity provider "${cpName}". Check its computeConfiguration.ec2Configuration.volumes.`, + }); + } + } + } + } + } + + // Validate AB test gateway references + for (const test of spec.abTests ?? []) { + const gwField = test.gatewayRef; + if (gwField && typeof gwField === 'string') { + const match = /^\{\{gateway:(.+)\}\}$/.exec(gwField); + if (match) { + const gwName = match[1]; + const gwExists = (spec.agentCoreGateways ?? []).some(gw => gw.name === gwName); + if (!gwExists) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `AB test "${test.name}" references gateway "${gwName}" which does not exist in agentCoreGateways`, + }); + } + + // For target-based AB tests, validate target names exist in the gateway's targets array + if (test.mode === 'target-based') { + const gw = (spec.agentCoreGateways ?? []).find(g => g.name === gwName); + if (gw) { + const gwTargetNames = new Set((gw.targets ?? []).map(t => t.name)); + for (const variant of test.variants) { + const targetName = variant.variantConfiguration.target?.targetName; + if (targetName && !gwTargetNames.has(targetName)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `AB test "${test.name}" variant "${variant.name}" references target "${targetName}" which does not exist in gateway "${gwName}" targets`, + }); + } + } + } + } + } + } + } + + // Connector gateway target KB reference: a project KB name (entry in + // knowledgeBases[]) or a literal 10-char KB ID (an external KB this + // project does not own). Real KB IDs match ^[A-Z0-9]{10}$; KB names + // start with a letter and may include dashes/underscores. The two + // formats can never collide. + const knowledgeBaseNames = new Set((spec.knowledgeBases ?? []).map(kb => kb.name)); + const REAL_KB_ID_PATTERN = /^[A-Z0-9]{10}$/; + const validateKbReference = (target: { name: string }, value: string, fieldLabel: string): void => { + const looksLikeRealId = REAL_KB_ID_PATTERN.test(value); + if (looksLikeRealId) { + if (knowledgeBaseNames.has(value)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Connector target "${target.name}" ${fieldLabel} "${value}" looks like a literal KB ID but also matches a knowledgeBases[] entry. Rename the knowledge base or reference it by its project name instead.`, + }); + } + } else { + if (!knowledgeBaseNames.has(value)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Connector target "${target.name}" ${fieldLabel} "${value}" does not match any knowledgeBases[] entry. To wire an external KB that this project does not own, use its 10-character KB ID.`, + }); + } + } + }; + + for (const gateway of spec.agentCoreGateways ?? []) { + for (const target of gateway.targets ?? []) { + if (target.targetType !== 'connector') continue; + if (target.connectorId !== 'bedrock-knowledge-bases') { + continue; + } + for (const cfg of target.configurations ?? []) { + const pv = cfg.parameterValues; + if (cfg.name === 'Retrieve' && pv?.knowledgeBaseId && typeof pv.knowledgeBaseId === 'string') { + validateKbReference(target, pv.knowledgeBaseId, 'configurations[].parameterValues.knowledgeBaseId'); + } + if (cfg.name === 'AgenticRetrieveStream') { + const rawRetrievers = pv?.retrievers; + if (!Array.isArray(rawRetrievers)) continue; + for (const r of rawRetrievers) { + if (!r || typeof r !== 'object') continue; + const kbId = (r as { configuration?: { knowledgeBase?: { knowledgeBaseId?: string } } }).configuration + ?.knowledgeBase?.knowledgeBaseId; + if (kbId) + validateKbReference(target, kbId, 'configurations[].parameterValues.retrievers[].knowledgeBaseId'); + } + } + } + } + } + + // Validate payment connector credential references + for (const payment of spec.payments ?? []) { + const paymentIndex = (spec.payments ?? []).indexOf(payment); + for (const connector of payment.connectors) { + const connectorIndex = payment.connectors.indexOf(connector); + if (connector.provisionMode === 'QUICK_CREATE') continue; + const credential = spec.credentials.find(c => c.name === connector.credentialName); + if (!credential) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Payment connector "${connector.name}" in manager "${payment.name}" references credential "${connector.credentialName}" which does not exist in credentials[]`, + path: ['payments', paymentIndex, 'connectors', connectorIndex, 'credentialName'], + }); + } else if (credential.authorizerType !== 'PaymentCredentialProvider') { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Payment connector "${connector.name}" in manager "${payment.name}" references credential "${connector.credentialName}" which is a ${credential.authorizerType}, not a PaymentCredentialProvider`, + path: ['payments', paymentIndex, 'connectors', connectorIndex, 'credentialName'], + }); + } + } + } + }); + +export type AgentCoreProjectSpec = z.infer; diff --git a/src/projectSchemas/v0/schemas/auth.ts b/src/projectSchemas/v0/schemas/auth.ts new file mode 100644 index 0000000000..16860576d9 --- /dev/null +++ b/src/projectSchemas/v0/schemas/auth.ts @@ -0,0 +1,283 @@ +import { SECURITY_GROUP_ID_PATTERN, SUBNET_ID_PATTERN, VPC_ID_PATTERN } from '../constants'; +import { TagsSchema } from './primitives/tags'; +import { z } from 'zod'; + +// Re-exported so TUI components that import *_ID_PATTERN from schemas/auth keep working. +export { SECURITY_GROUP_ID_PATTERN, SUBNET_ID_PATTERN, VPC_ID_PATTERN }; + +// ============================================================================ +// Shared Authorization Schemas +// ============================================================================ + +export const GatewayAuthorizerTypeSchema = z.enum(['NONE', 'AWS_IAM', 'CUSTOM_JWT']); +export type GatewayAuthorizerType = z.infer; + +export const RuntimeAuthorizerTypeSchema = z.enum(['AWS_IAM', 'CUSTOM_JWT']); +export type RuntimeAuthorizerType = z.infer; + +/** OIDC well-known configuration endpoint suffix (per OpenID Connect Discovery 1.0 spec) */ +const OIDC_WELL_KNOWN_SUFFIX = '/.well-known/openid-configuration'; + +/** + * OIDC Discovery URL schema. + * Must be a valid URL ending with the standard OIDC well-known endpoint. + * @see https://openid.net/specs/openid-connect-discovery-1_0.html + */ +const OidcDiscoveryUrlSchema = z + .string() + .url('Must be a valid URL') + .refine(url => url.startsWith('https://'), { + message: 'OIDC discovery URL must use HTTPS', + }) + .refine(url => url.endsWith(OIDC_WELL_KNOWN_SUFFIX), { + message: `OIDC discovery URL must end with '${OIDC_WELL_KNOWN_SUFFIX}'`, + }); + +// ── Custom Claims Schemas (matches CFN CustomClaimValidationType) ── + +// API-documented patterns (from ClaimMatchValueType and CustomClaimValidationType) +const MATCH_VALUE_PATTERN = /^[A-Za-z0-9_.-]+$/; +// OAuth scope token: printable ASCII excluding space (0x20) and double-quote (0x22). +// Mirrors CFN CustomJWTAuthorizerConfiguration.AllowedScopes.items pattern byte-for-byte. +const ALLOWED_SCOPE_PATTERN = /^[\x21\x23-\x5B\x5D-\x7E]+$/; +const CLAIM_NAME_PATTERN = /^[A-Za-z0-9_.:-]+$/; +// Server-side reserved claim names (not regex-documented; API rejects these at deploy time) +const RESERVED_CLAIM_NAMES = ['client_id']; + +export const ClaimMatchOperatorSchema = z.enum(['EQUALS', 'CONTAINS', 'CONTAINS_ANY']); +export type ClaimMatchOperator = z.infer; + +export const ClaimMatchValueSchema = z + .object({ + matchValueString: z + .string() + .min(1) + .max(255) + .regex(MATCH_VALUE_PATTERN, 'Match value must match [A-Za-z0-9_.-]+') + .optional(), + matchValueStringList: z + .array(z.string().min(1).max(255).regex(MATCH_VALUE_PATTERN, 'Each match value must match [A-Za-z0-9_.-]+')) + .min(1) + .max(255) + .optional(), + }) + .refine(data => data.matchValueString !== undefined || data.matchValueStringList !== undefined, { + message: 'Either matchValueString or matchValueStringList must be provided', + }) + .refine(data => !(data.matchValueString !== undefined && data.matchValueStringList !== undefined), { + message: 'Only one of matchValueString or matchValueStringList may be provided', + }); +export type ClaimMatchValue = z.infer; + +export const InboundTokenClaimValueTypeSchema = z.enum(['STRING', 'STRING_ARRAY']); +export type InboundTokenClaimValueType = z.infer; + +export const CustomClaimValidationSchema = z + .object({ + inboundTokenClaimName: z + .string() + .min(1) + .max(255) + .regex(CLAIM_NAME_PATTERN, 'Claim name must match [A-Za-z0-9_.-:]+') + .refine(name => !RESERVED_CLAIM_NAMES.includes(name), { + message: `Claim name cannot be a reserved name (${RESERVED_CLAIM_NAMES.join(', ')})`, + }), + inboundTokenClaimValueType: InboundTokenClaimValueTypeSchema, + authorizingClaimMatchValue: z.object({ + claimMatchOperator: ClaimMatchOperatorSchema, + claimMatchValue: ClaimMatchValueSchema, + }), + }) + .strict(); +export type CustomClaimValidation = z.infer; + +// ── PrivateLink Inbound — private endpoint for reaching the OIDC discovery URL ── +// +// Nested inside CustomJWTAuthorizerConfiguration ("PrivateLink inbound" GA-parity feature): +// when a JWT IdP's discovery/JWKS endpoint is privately hosted, this tells the harness how to +// reach it over a private network. Two mutually-exclusive arms. Patterns match the +// AWS::BedrockAgentCore::Harness CFN spec byte-for-byte. + +// VPC Lattice resource-config id, or its full ARN. Exported so the TUI validators reuse the +// schema regex (single source of truth) instead of hand-rolled checks that drift from it. +export const LATTICE_RESOURCE_CONFIG_PATTERN = + /^((rcfg-[0-9a-z]{17})|(arn:[a-z0-9-]+:vpc-lattice:[a-zA-Z0-9-]+:\d{12}:resourceconfiguration\/rcfg-[0-9a-z]{17}))$/; + +export const EndpointIpAddressTypeSchema = z.enum(['IPV4', 'IPV6']); +export type EndpointIpAddressType = z.infer; + +/** Reach the discovery endpoint via a self-managed VPC Lattice resource configuration. */ +export const SelfManagedLatticeResourceSchema = z + .object({ + resourceConfigurationIdentifier: z + .string() + .min(20) + .max(2048) + .regex(LATTICE_RESOURCE_CONFIG_PATTERN, 'Must be a VPC Lattice resource-config id (rcfg-...) or its ARN'), + }) + .strict(); +export type SelfManagedLatticeResource = z.infer; + +/** Reach the discovery endpoint via a service-managed VPC interface endpoint. */ +export const ManagedVpcResourceSchema = z + .object({ + vpcIdentifier: z.string().regex(VPC_ID_PATTERN, 'Must be a VPC id (vpc-...)'), + subnetIds: z.array(z.string().regex(SUBNET_ID_PATTERN, 'Must be a subnet id (subnet-...)')).min(1), + endpointIpAddressType: EndpointIpAddressTypeSchema, + securityGroupIds: z + .array(z.string().regex(SECURITY_GROUP_ID_PATTERN, 'Must be a security group id (sg-...)')) + .max(5) + .optional(), + tags: TagsSchema.optional(), + routingDomain: z.string().min(3).max(255).optional(), + }) + .strict(); +export type ManagedVpcResource = z.infer; + +/** + * A private endpoint: exactly one of selfManagedLatticeResource or managedVpcResource. + * The CFN spec dropped `oneOf` (contract-test antipattern) and enforces exactly-one structurally; + * we mirror that with a superRefine rather than a discriminated union. + */ +export const PrivateEndpointSchema = z + .object({ + selfManagedLatticeResource: SelfManagedLatticeResourceSchema.optional(), + managedVpcResource: ManagedVpcResourceSchema.optional(), + }) + .strict() + .superRefine((data, ctx) => { + const count = [data.selfManagedLatticeResource, data.managedVpcResource].filter(v => v !== undefined).length; + if (count !== 1) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'A private endpoint must set exactly one of selfManagedLatticeResource or managedVpcResource', + }); + } + }); +export type PrivateEndpoint = z.infer; + +/** Maps a specific domain to its own private endpoint (overrides the discovery-URL endpoint for that domain). */ +export const PrivateEndpointOverrideSchema = z + .object({ + domain: z.string().min(1).max(253), + privateEndpoint: PrivateEndpointSchema, + }) + .strict(); +export type PrivateEndpointOverride = z.infer; + +/** + * Which arm a PrivateEndpoint uses. The nested exactly-one-of refine guarantees a single arm, + * so this is read at the authorizer level to enforce the service's "all endpoints same kind" rule. + */ +type PrivateEndpointArm = 'selfManagedLatticeResource' | 'managedVpcResource' | undefined; +function privateEndpointArm(pe: PrivateEndpoint): PrivateEndpointArm { + if (pe.selfManagedLatticeResource) return 'selfManagedLatticeResource'; + if (pe.managedVpcResource) return 'managedVpcResource'; + return undefined; +} + +// ── Custom JWT Authorizer Configuration ── + +/** + * Custom JWT authorizer configuration. + * Used when authorizerType is 'CUSTOM_JWT'. + * + * At least one of allowedAudience, allowedClients, allowedScopes, or customClaims + * must be provided. Only discoveryUrl is unconditionally required. + */ +export const CustomJwtAuthorizerConfigSchema = z + .object({ + /** OIDC discovery URL (e.g., https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/openid-configuration) */ + discoveryUrl: OidcDiscoveryUrlSchema, + /** List of allowed audiences (typically client IDs) */ + allowedAudience: z.array(z.string().min(1)).optional(), + /** List of allowed client IDs */ + allowedClients: z.array(z.string().min(1)).optional(), + /** List of allowed scopes (printable ASCII, no space/quote; ≤255 chars each — CFN parity) */ + allowedScopes: z + .array( + z + .string() + .min(1) + .max(255) + .regex(ALLOWED_SCOPE_PATTERN, 'Scope must be printable ASCII with no spaces or quotes') + ) + .optional(), + /** Custom claim validations */ + customClaims: z.array(CustomClaimValidationSchema).min(1).optional(), + /** PrivateLink inbound: how to reach the OIDC discovery endpoint over a private network. */ + privateEndpoint: PrivateEndpointSchema.optional(), + /** Per-domain private-endpoint overrides (≤5). */ + privateEndpointOverrides: z.array(PrivateEndpointOverrideSchema).max(5).optional(), + }) + .strict() + .superRefine((data, ctx) => { + const hasAudience = data.allowedAudience && data.allowedAudience.length > 0; + const hasClients = data.allowedClients && data.allowedClients.length > 0; + const hasScopes = data.allowedScopes && data.allowedScopes.length > 0; + const hasClaims = data.customClaims && data.customClaims.length > 0; + + if (!hasAudience && !hasClients && !hasScopes && !hasClaims) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'At least one of allowedAudience, allowedClients, allowedScopes, or customClaims must be provided', + }); + } + + // PrivateEndpointOverrides coupling rules — mirror the AgentCore Identity service's deploy-time + // validation so the user fails fast here instead of mid-deploy. + const overrides = data.privateEndpointOverrides ?? []; + if (overrides.length > 0) { + // 1. Overrides require a base privateEndpoint. + if (!data.privateEndpoint) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'privateEndpointOverrides can only be used when privateEndpoint is also set', + path: ['privateEndpointOverrides'], + }); + } else { + // 2. The base endpoint and every override must use the same arm (all self-managed or all service-managed). + const baseArm = privateEndpointArm(data.privateEndpoint); + overrides.forEach((o, i) => { + if (privateEndpointArm(o.privateEndpoint) !== baseArm) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + 'privateEndpoint and privateEndpointOverrides must all be the same kind — either all selfManagedLatticeResource or all managedVpcResource', + path: ['privateEndpointOverrides', i, 'privateEndpoint'], + }); + } + }); + } + + // 3. Override domains must be unique. + const seen = new Set(); + overrides.forEach((o, i) => { + if (seen.has(o.domain)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Duplicate privateEndpointOverride domain: ${o.domain}`, + path: ['privateEndpointOverrides', i, 'domain'], + }); + } + seen.add(o.domain); + }); + } + }); + +export type CustomJwtAuthorizerConfig = z.infer; + +/** + * Resource-agnostic authorizer configuration container. + * Used by both Gateway and Runtime resources. + */ +export const AuthorizerConfigSchema = z.object({ + customJwtAuthorizer: CustomJwtAuthorizerConfigSchema.optional(), +}); + +export type AuthorizerConfig = z.infer; + +/** @deprecated Use AuthorizerConfigSchema. Backwards-compatible alias for Gateway. */ +export const GatewayAuthorizerConfigSchema = AuthorizerConfigSchema; +/** @deprecated Use AuthorizerConfig. Backwards-compatible alias for Gateway. */ +export type GatewayAuthorizerConfig = AuthorizerConfig; diff --git a/src/projectSchemas/v0/schemas/aws-targets.ts b/src/projectSchemas/v0/schemas/aws-targets.ts new file mode 100644 index 0000000000..b82e88b766 --- /dev/null +++ b/src/projectSchemas/v0/schemas/aws-targets.ts @@ -0,0 +1,82 @@ +import { uniqueBy } from './zod-util'; +import { z } from 'zod'; + +// ============================================================================ +// AgentCore Regions +// Keep in sync with: https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/agentcore-regions.html +// ============================================================================ + +export const AgentCoreRegionSchema = z.enum([ + 'ap-northeast-1', + 'ap-northeast-2', + 'ap-south-1', + 'ap-south-2', + 'ap-southeast-1', + 'ap-southeast-2', + 'ap-southeast-5', + 'ap-southeast-7', + 'ca-central-1', + 'eu-central-1', + 'eu-north-1', + 'eu-south-1', + 'eu-south-2', + 'eu-west-1', + 'eu-west-2', + 'eu-west-3', + 'sa-east-1', + 'us-east-1', + 'us-east-2', + 'us-west-1', + 'us-west-2', + 'us-gov-west-1', +]); +export type AgentCoreRegion = z.infer; + +// ============================================================================ +// Deployment Target Name +// ============================================================================ + +export const DeploymentTargetNameSchema = z + .string() + .min(1) + .max(64) + .regex( + /^[a-zA-Z][a-zA-Z0-9-]*$/, + 'Name must start with a letter and contain only alphanumeric characters and hyphens' + ) + .describe('Unique identifier for the deployment target'); + +// ============================================================================ +// AWS Account ID +// ============================================================================ + +export const AwsAccountIdSchema = z + .string() + .regex(/^[0-9]{12}$/, 'AWS account ID must be exactly 12 digits') + .describe('AWS account ID'); + +// ============================================================================ +// AWS Deployment Target +// ============================================================================ + +export const AwsDeploymentTargetSchema = z.object({ + name: DeploymentTargetNameSchema, + description: z.string().max(256).optional(), + account: AwsAccountIdSchema, + region: AgentCoreRegionSchema, +}); + +export type AwsDeploymentTarget = z.infer; + +// ============================================================================ +// AWS Deployment Targets Array +// ============================================================================ + +export const AwsDeploymentTargetsSchema = z.array(AwsDeploymentTargetSchema).superRefine( + uniqueBy( + target => target.name, + name => `Duplicate deployment target name: ${name}` + ) +); + +export type AwsDeploymentTargets = z.infer; diff --git a/src/projectSchemas/v0/schemas/connections.ts b/src/projectSchemas/v0/schemas/connections.ts new file mode 100644 index 0000000000..bff82b2c97 --- /dev/null +++ b/src/projectSchemas/v0/schemas/connections.ts @@ -0,0 +1,192 @@ +import { z } from 'zod'; + +// ============================================================================ +// Resource Connections +// +// A connection declares that a principal (an agent runtime or a harness) accesses +// an EXTERNAL AgentCore resource (a memory/gateway/runtime that is NOT part of this +// project). The construct generates the correct least-privilege IAM onto the +// principal's execution role AND injects the discovery env vars from each connection. +// +// Connections are embedded on the source resource (AgentEnvSpec.connections / +// HarnessSpec.connections); the enclosing resource IS the source, so there is no +// `from` field. In-project access remains implicit (all-to-all wiring) and is +// untouched — connections only ADD grants for external targets. +// +// FUTURE (additive, not in this milestone): targets gain an optional `name` to +// reference an in-project resource (managed reference + access gating); new target +// kinds (s3, secret) are added as union members. +// ============================================================================ + +/** + * OAuth grant type for an external gateway, matching the runtime/Smithy model. + * The harness runtime maps these to AgentCore Identity auth flows: + * CLIENT_CREDENTIALS -> M2M, AUTHORIZATION_CODE -> USER_FEDERATION, TOKEN_EXCHANGE -> TOKEN_EXCHANGE. + */ +export const GatewayGrantTypeSchema = z.enum(['CLIENT_CREDENTIALS', 'AUTHORIZATION_CODE', 'TOKEN_EXCHANGE']); +export type GatewayGrantType = z.infer; + +/** + * Outbound auth a caller uses to reach an external gateway. This is the union the + * gateway/harness runtime actually consumes — NOT the gateway's inbound authorizerType + * (which lives on the gateway resource and is invisible to an external caller). + * - awsIam: SigV4-sign with the execution role (grants InvokeGateway) + * - none: no auth + * - oauth: fetch an OAuth token via AgentCore Identity (grants token-fetch perms on + * the provider). All four oauth fields are consumed at runtime. + */ +export const GatewayOutboundAuthSchema = z.union([ + z.object({ awsIam: z.object({}).strict() }).strict(), + z.object({ none: z.object({}).strict() }).strict(), + z + .object({ + oauth: z + .object({ + providerArn: z.string().min(1), + scopes: z.array(z.string().min(1)), + grantType: GatewayGrantTypeSchema.optional(), + customParameters: z.record(z.string(), z.string()).optional(), + }) + .strict(), + }) + .strict(), +]); +export type GatewayOutboundAuth = z.infer; + +// ---- Connection targets (external AgentCore resources, ARN-addressed) ---- +// Partition-agnostic ARN prefix (arn:[^:]+:) per multi-partition rules. + +const MEMORY_ARN_PATTERN = /^arn:[^:]+:bedrock-agentcore:[a-z0-9-]+:\d{12}:memory\/.+$/; +const GATEWAY_ARN_PATTERN = /^arn:[^:]+:bedrock-agentcore:[a-z0-9-]+:\d{12}:gateway\/.+$/; +const RUNTIME_ARN_PATTERN = /^arn:[^:]+:bedrock-agentcore:[a-z0-9-]+:\d{12}:runtime\/.+$/; +// Browser / code-interpreter ARNs come in two legitimate resource-segment forms: +// - customer-owned (CreateBrowser/CreateCodeInterpreter): `-custom/` with a 12-digit account +// - AWS-managed default (SYSTEM): `/` with the `aws` account +export const BROWSER_ARN_PATTERN = /^arn:[^:]+:bedrock-agentcore:[a-z0-9-]+:(\d{12}|aws):browser(-custom)?\/.+$/; +export const CODE_INTERPRETER_ARN_PATTERN = + /^arn:[^:]+:bedrock-agentcore:[a-z0-9-]+:(\d{12}|aws):code-interpreter(-custom)?\/.+$/; + +const MemoryTargetSchema = z + .object({ + type: z.literal('memory'), + arn: z.string().regex(MEMORY_ARN_PATTERN, 'Must be a valid bedrock-agentcore memory ARN'), + /** Optional namespace templates to scope List/RetrieveMemoryRecords via the + * bedrock-agentcore:namespace / namespacePath condition keys. */ + namespaces: z.array(z.string().min(1)).optional(), + }) + .strict(); + +const GatewayTargetSchema = z + .object({ + type: z.literal('gateway'), + arn: z.string().regex(GATEWAY_ARN_PATTERN, 'Must be a valid bedrock-agentcore gateway ARN'), + /** How the caller authenticates outbound to the gateway. Defaults to awsIam (SigV4). */ + outboundAuth: GatewayOutboundAuthSchema.optional(), + }) + .strict(); + +const RuntimeTargetSchema = z + .object({ + type: z.literal('runtime'), + arn: z.string().regex(RUNTIME_ARN_PATTERN, 'Must be a valid bedrock-agentcore runtime ARN'), + /** Also grant InvokeAgentRuntimeCommand (container exec) in addition to invoke. */ + exec: z.boolean().optional(), + }) + .strict(); + +const BrowserTargetSchema = z + .object({ + type: z.literal('browser'), + /** Customer-owned browser ARN. Omit to use the AWS-managed default browser. */ + arn: z.string().regex(BROWSER_ARN_PATTERN, 'Must be a valid bedrock-agentcore browser ARN').optional(), + }) + .strict(); + +const CodeInterpreterTargetSchema = z + .object({ + type: z.literal('codeInterpreter'), + /** Customer-owned code-interpreter ARN. Omit to use the AWS-managed default. */ + arn: z + .string() + .regex(CODE_INTERPRETER_ARN_PATTERN, 'Must be a valid bedrock-agentcore code-interpreter ARN') + .optional(), + }) + .strict(); + +export const ConnectionTargetSchema = z.discriminatedUnion('type', [ + MemoryTargetSchema, + GatewayTargetSchema, + RuntimeTargetSchema, + BrowserTargetSchema, + CodeInterpreterTargetSchema, +]); +export type ConnectionTarget = z.infer; + +/** + * A single connection from the enclosing principal to an external resource. + * `access` is meaningful only for memory (read | readwrite); ignored for invoke-only + * targets. Defaults to `read` (least-privilege). + */ +export const ConnectionSchema = z + .object({ + id: z + .string() + .regex(/^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/, 'Connection id must match [a-zA-Z][a-zA-Z0-9_-]{0,63}') + .optional(), + to: ConnectionTargetSchema, + access: z.enum(['read', 'readwrite']).optional(), + description: z.string().max(200).optional(), + }) + .strict(); +export type Connection = z.infer; + +export const ConnectionsSchema = z.array(ConnectionSchema); + +// ============================================================================ +// Connection discovery env-var naming — SINGLE SOURCE OF TRUTH. +// +// The discovery env var (e.g. MEMORY__ID, GATEWAY__URL) is the handshake between the +// CLI export (which bakes the NAME into the generated agent code) and the CDK deploy (which injects +// the VALUE onto the runtime). Both sides MUST compute the identical , so the token derivation +// lives here — the one file already kept in lockstep across the CLI and @aws/agentcore-cdk repos. +// `connectionEnvToken` is used by `harness-mapper` (CLI) and `connectionTokenFor` by +// `wire-connections` (CDK); do not re-implement the token derivation. Each side then assembles the +// final `__` name inline (the prefixes/suffixes differ per resource kind). +// ============================================================================ + +/** Maximum length of a connection id (matches the ConnectionSchema id regex bound). */ +export const CONNECTION_ID_MAX_LENGTH = 64; + +/** Last segment of an ARN (the resource id): `memory/mem-123` -> `mem-123`. */ +export function resourceIdFromArn(arn: string): string { + const afterColon = arn.split(':').pop() ?? arn; + const slash = afterColon.lastIndexOf('/'); + return slash >= 0 ? afterColon.slice(slash + 1) : afterColon; +} + +/** + * Stable connection id for an external target: `-`, sanitized to the schema id + * charset and length. Used as the connection's `id` AND as the basis for its discovery env-var + * token, so the name baked into generated code matches what deploy injects. + */ +export function connectionIdForTarget(target: ConnectionTarget): string { + const suffix = 'arn' in target && target.arn ? resourceIdFromArn(target.arn) : target.type; + const id = `${target.type}-${suffix}`; + // Conform to ConnectionSchema id regex: start with a letter, then [a-zA-Z0-9_-], max length. + return id.replace(/[^a-zA-Z0-9_-]/g, '-').slice(0, CONNECTION_ID_MAX_LENGTH); +} + +/** Uppercase, underscore-safe token for env-var naming, derived from a connection id. */ +export function connectionEnvToken(id: string): string { + return id.toUpperCase().replace(/[^A-Z0-9]/g, '_'); +} + +/** + * Resolve the env-var token for a connection. Prefers the explicit `id`; otherwise derives the same + * `-` id the CLI would have assigned — so an id-less connection (schema permits it, + * e.g. a hand-authored config or a direct @aws/agentcore-cdk consumer) yields the SAME token on both + * sides instead of diverging. + */ +export function connectionTokenFor(connection: Connection): string { + return connectionEnvToken(connection.id ?? connectionIdForTarget(connection.to)); +} diff --git a/src/projectSchemas/v0/schemas/deployed-state.ts b/src/projectSchemas/v0/schemas/deployed-state.ts new file mode 100644 index 0000000000..aa3553c8a7 --- /dev/null +++ b/src/projectSchemas/v0/schemas/deployed-state.ts @@ -0,0 +1,409 @@ +import { CustomClaimValidationSchema } from './auth'; +import { DeploymentTargetNameSchema } from './aws-targets'; +import { z } from 'zod'; + +// ============================================================================ +// Agent Deployed State +// ============================================================================ + +export const AgentCoreDeployedStateSchema = z.object({ + runtimeId: z.string().min(1), + runtimeArn: z.string().min(1), + roleArn: z.string().min(1), + sessionId: z.string().optional(), + memoryIds: z.array(z.string()).optional(), + browserId: z.string().optional(), + codeInterpreterId: z.string().optional(), + /** The latest deployed version number of this runtime. */ + runtimeVersion: z.number().int().min(1).optional(), +}); + +export type AgentCoreDeployedState = z.infer; + +// ============================================================================ +// Memory Deployed State +// ============================================================================ + +export const MemoryDeployedStateSchema = z.object({ + memoryId: z.string().min(1), + memoryArn: z.string().min(1), +}); + +export type MemoryDeployedState = z.infer; + +// ============================================================================ +// MCP Gateway Deployed State +// ============================================================================ + +export const GatewayTargetDeployedStateSchema = z.object({ + targetId: z.string().min(1), +}); + +export type GatewayTargetDeployedState = z.infer; + +export const GatewayDeployedStateSchema = z.object({ + gatewayId: z.string().min(1), + gatewayArn: z.string().min(1), + gatewayUrl: z.string().optional(), + targets: z.record(z.string(), GatewayTargetDeployedStateSchema).optional(), +}); + +export type GatewayDeployedState = z.infer; + +// ============================================================================ +// MCP Runtime Deployed State +// ============================================================================ + +export const McpRuntimeDeployedStateSchema = z.object({ + runtimeId: z.string().min(1), + runtimeArn: z.string().min(1), + runtimeEndpoint: z.string().min(1), +}); + +export type McpRuntimeDeployedState = z.infer; + +// ============================================================================ +// MCP Lambda Deployed State +// ============================================================================ + +export const McpLambdaDeployedStateSchema = z.object({ + functionArn: z.string().min(1), + functionName: z.string().min(1), +}); + +export type McpLambdaDeployedState = z.infer; + +// ============================================================================ +// MCP Deployed State Container +// ============================================================================ + +export const McpDeployedStateSchema = z.object({ + gateways: z.record(z.string(), GatewayDeployedStateSchema).optional(), + runtimes: z.record(z.string(), McpRuntimeDeployedStateSchema).optional(), + lambdas: z.record(z.string(), McpLambdaDeployedStateSchema).optional(), +}); + +export type McpDeployedState = z.infer; + +// ============================================================================ +// Externally Managed Resources +// ============================================================================ + +export const ExternallyManagedResourceSchema = z.object({ + name: z.string().min(1), +}); + +export type ExternallyManagedResource = z.infer; + +export const CustomJwtAuthorizerSchema = ExternallyManagedResourceSchema.extend({ + allowedAudience: z.array(z.string()).optional(), + allowedClients: z.array(z.string()).optional(), + allowedScopes: z.array(z.string()).optional(), + customClaims: z.array(CustomClaimValidationSchema).optional(), + discoveryUrl: z.string(), +}); + +export type CustomJwtAuthorizer = z.infer; + +export const VpcConfigSchema = ExternallyManagedResourceSchema.extend({ + securityGroups: z.array(z.string()), + subnets: z.array(z.string()), +}); + +export type VpcConfig = z.infer; + +export const ExternallyManagedStateSchema = z.object({ + customJwtAuthorizer: CustomJwtAuthorizerSchema.optional(), + vpcConfig: VpcConfigSchema.optional(), +}); + +export type ExternallyManagedState = z.infer; + +// ============================================================================ +// Policy Engine Deployed State +// ============================================================================ + +export const PolicyEngineDeployedStateSchema = z.object({ + policyEngineId: z.string().min(1), + policyEngineArn: z.string().min(1), +}); + +export type PolicyEngineDeployedState = z.infer; + +// ============================================================================ +// Policy Deployed State +// ============================================================================ + +export const PolicyDeployedStateSchema = z.object({ + policyId: z.string().min(1), + policyArn: z.string().min(1), + engineName: z.string().min(1), +}); + +export type PolicyDeployedState = z.infer; + +// ============================================================================ +// Harness Deployed State +// ============================================================================ + +export const HarnessDeployedStateSchema = z.object({ + harnessId: z.string().min(1), + harnessArn: z.string().min(1), + roleArn: z.string().min(1), + status: z.string().min(1), + /** Read-only harness config version from the CFN `Version` output; service-incremented per update. */ + harnessVersion: z.number().int().min(1).optional(), + agentRuntimeArn: z.string().optional(), + memoryArn: z.string().optional(), + /** Which subsystem provisioned this harness. Stamped 'cloudformation' by the CDK deploy path. */ + provisioner: z.enum(['cloudformation']).optional(), +}); + +export type HarnessDeployedState = z.infer; + +// ============================================================================ +// Credential Deployed State +// ============================================================================ + +export const CredentialDeployedStateSchema = z.object({ + credentialProviderArn: z.string().min(1), + clientSecretArn: z.string().optional(), + callbackUrl: z.string().optional(), +}); + +export type CredentialDeployedState = z.infer; + +// ============================================================================ +// Evaluator Deployed State +// ============================================================================ + +export const EvaluatorDeployedStateSchema = z.object({ + evaluatorId: z.string().min(1), + evaluatorArn: z.string().min(1), +}); + +export type EvaluatorDeployedState = z.infer; + +// ============================================================================ +// Online Eval Config Deployed State +// ============================================================================ + +export const OnlineEvalDeployedStateSchema = z.object({ + onlineEvaluationConfigId: z.string().min(1), + onlineEvaluationConfigArn: z.string().min(1), + executionStatus: z.enum(['ENABLED', 'DISABLED']).optional(), + /** Agent name this online eval config monitors. */ + agent: z.string().min(1).optional(), + /** Runtime endpoint name scoped to this online eval config. */ + endpoint: z.string().min(1).optional(), +}); + +export type OnlineEvalDeployedState = z.infer; + +// ============================================================================ +// Dataset Deployed State +// ============================================================================ + +export const DatasetDeployedStateSchema = z.object({ + datasetId: z.string().min(1), + datasetArn: z.string().min(1), + contentHash: z.string().optional(), +}); + +export type DatasetDeployedState = z.infer; + +// ============================================================================ +// Knowledge Base Deployed State +// ============================================================================ + +export const KnowledgeBaseDataSourceDeployedStateSchema = z.object({ + dataSourceId: z.string().min(1), + uri: z.string().min(1), +}); + +export type KnowledgeBaseDataSourceDeployedState = z.infer; + +/** + * Per-target deployed state for a knowledge base. Captures the IDs the + * status command needs to call bedrock-agent for live KB and ingestion state. + * + * `dataSources` is an array (not a record) because the deploy step writes + * them in the same order as the local `dataSources[]` array; the index + * lets us correlate local sources with deployed DSs without extra IDs. + * + * `sourcesHash` is a SHA-256 of the data-source URIs (joined with newlines) + * captured at the time auto-ingestion last fired. The post-deploy ingestion + * hook computes a fresh hash from the current spec and compares — if equal, + * skip ingestion (no changes to ingest). Optional so projects deployed + * before the hook shipped don't fail validation; treated as "ingest needed" + * when absent. + */ +export const KnowledgeBaseDeployedStateSchema = z.object({ + knowledgeBaseId: z.string().min(1), + knowledgeBaseArn: z.string().min(1), + dataSources: z.array(KnowledgeBaseDataSourceDeployedStateSchema).default([]), + sourcesHash: z.string().min(1).optional(), +}); + +export type KnowledgeBaseDeployedState = z.infer; + +// ============================================================================ +// Configuration Bundle Deployed State +// ============================================================================ + +export const ConfigBundleDeployedStateSchema = z.object({ + bundleId: z.string().min(1), + bundleArn: z.string().min(1), + versionId: z.string().min(1), +}); + +export type ConfigBundleDeployedState = z.infer; + +// ============================================================================ +// AB Test Deployed State +// ============================================================================ + +export const ABTestDeployedStateSchema = z.object({ + abTestId: z.string().min(1), + abTestArn: z.string().min(1), + roleArn: z.string().min(1).optional(), + roleCreatedByCli: z.boolean().optional(), + configHash: z.string().optional(), +}); + +export type ABTestDeployedState = z.infer; + +// ============================================================================ +// Runtime Endpoint Deployed State +// ============================================================================ + +export const RuntimeEndpointDeployedStateSchema = z.object({ + endpointId: z.string().min(1), + endpointArn: z.string().min(1), +}); + +export type RuntimeEndpointDeployedState = z.infer; + +// ============================================================================ +// Payment Connector Deployed State +// ============================================================================ + +const PaymentConnectorDeployedStateBaseSchema = z.object({ + connectorId: z.string().min(1), + credentialProviderName: z.string().optional(), +}); + +export const PaymentConnectorDeployedStateSchema = z.union([ + PaymentConnectorDeployedStateBaseSchema.extend({ + provisionMode: z.literal('QUICK_CREATE'), + credentialProviderArn: z.never().optional(), + }), + PaymentConnectorDeployedStateBaseSchema.extend({ + provisionMode: z.literal('MANUAL').optional(), + credentialProviderArn: z.string().min(1), + }), +]); + +export type PaymentConnectorDeployedState = z.infer; + +// ============================================================================ +// Payment Deployed State +// ============================================================================ + +export const PaymentDeployedStateSchema = z.object({ + managerId: z.string().min(1), + managerArn: z.string().min(1), + connectors: z.record(z.string(), PaymentConnectorDeployedStateSchema).default({}), + processPaymentRoleArn: z.string().min(1), + resourceRetrievalRoleArn: z.string().min(1), + authorizerType: z.enum(['AWS_IAM', 'CUSTOM_JWT']).optional(), + autoPayment: z.boolean().optional(), + paymentToolAllowlist: z.array(z.string()).optional(), + networkPreferences: z.array(z.string()).optional(), +}); + +export type PaymentDeployedState = z.infer; + +// ============================================================================ +// Capacity Provider Deployed State +// ============================================================================ + +export const CapacityProviderDeployedStateSchema = z.object({ + capacityProviderId: z.string().min(1), + capacityProviderArn: z.string().min(1), +}); + +export type CapacityProviderDeployedState = z.infer; + +// ============================================================================ +// Deployed Resource State +// ============================================================================ + +export const DeployedResourceStateSchema = z.object({ + runtimes: z.record(z.string(), AgentCoreDeployedStateSchema).optional(), + memories: z.record(z.string(), MemoryDeployedStateSchema).optional(), + mcp: McpDeployedStateSchema.optional(), + gateways: z.record(z.string(), GatewayDeployedStateSchema).optional(), + externallyManaged: ExternallyManagedStateSchema.optional(), + credentials: z.record(z.string(), CredentialDeployedStateSchema).optional(), + evaluators: z.record(z.string(), EvaluatorDeployedStateSchema).optional(), + onlineEvalConfigs: z.record(z.string(), OnlineEvalDeployedStateSchema).optional(), + datasets: z.record(z.string(), DatasetDeployedStateSchema).optional(), + knowledgeBases: z.record(z.string(), KnowledgeBaseDeployedStateSchema).optional(), + configBundles: z.record(z.string(), ConfigBundleDeployedStateSchema).optional(), + abTests: z.record(z.string(), ABTestDeployedStateSchema).optional(), + policyEngines: z.record(z.string(), PolicyEngineDeployedStateSchema).optional(), + policies: z.record(z.string(), PolicyDeployedStateSchema).optional(), + harnesses: z.record(z.string(), HarnessDeployedStateSchema).optional(), + runtimeEndpoints: z.record(z.string(), RuntimeEndpointDeployedStateSchema).optional(), + payments: z.record(z.string(), PaymentDeployedStateSchema).optional(), + capacityProviders: z.record(z.string(), CapacityProviderDeployedStateSchema).optional(), + stackName: z.string().optional(), + identityKmsKeyArn: z.string().optional(), + deployHash: z.string().optional(), +}); + +export type DeployedResourceState = z.infer; + +// ============================================================================ +// Target Deployed State +// ============================================================================ + +export const TargetDeployedStateSchema = z.object({ + resources: DeployedResourceStateSchema.optional(), +}); + +export type TargetDeployedState = z.infer; + +// ============================================================================ +// Root Deployed State +// ============================================================================ + +/** + * Type alias for deployment target name (maps to aws-targets name field). + */ +export type DeploymentTargetName = string; + +export const DeployedStateSchema = z.object({ + targets: z.record(DeploymentTargetNameSchema, TargetDeployedStateSchema), +}); + +export type DeployedState = z.infer; + +/** + * Creates a DeployedState schema that validates target keys against aws-targets. + * Ensures all keys in deployed-state exist as names in aws-targets. + */ +export function createValidatedDeployedStateSchema(targetNames: string[]) { + const targetNameSet = new Set(targetNames); + + return DeployedStateSchema.refine( + state => { + const stateKeys = Object.keys(state.targets); + return stateKeys.every(key => targetNameSet.has(key)); + }, + { + message: 'Deployed state contains target names not present in aws-targets', + } + ); +} diff --git a/src/projectSchemas/v0/schemas/index.ts b/src/projectSchemas/v0/schemas/index.ts new file mode 100644 index 0000000000..903def0953 --- /dev/null +++ b/src/projectSchemas/v0/schemas/index.ts @@ -0,0 +1,12 @@ +// Consolidated Zod-first schemas with types derived from z.infer<> +export * from './agent-env'; +export * from './agentcore-project'; +export * from './auth'; +export * from './aws-targets'; +export * from './connections'; +export * from './deployed-state'; +export * from './mcp'; +export * from './mcp-defs'; +export { EvaluatorModelIdSchema, EvaluatorModelProviderSchema } from './primitives/evaluator'; +export type { EvaluatorModelProvider } from './primitives/evaluator'; +export * from './zod-util'; diff --git a/src/projectSchemas/v0/schemas/mcp-defs.ts b/src/projectSchemas/v0/schemas/mcp-defs.ts new file mode 100644 index 0000000000..72c449bcbc --- /dev/null +++ b/src/projectSchemas/v0/schemas/mcp-defs.ts @@ -0,0 +1,79 @@ +import { z } from 'zod'; + +// ============================================================================ +// Schema Primitive Types +// ============================================================================ + +export const SchemaPrimitiveTypeSchema = z.enum(['string', 'number', 'object', 'array', 'boolean', 'integer']); +export type SchemaPrimitiveType = z.infer; + +// ============================================================================ +// Schema Definition (recursive) +// ============================================================================ + +/** + * Opaque schema definition for tool input/output. + * This is passed through to CloudFormation without validation. + */ +export interface SchemaDefinition { + type: SchemaPrimitiveType; + description?: string; + items?: SchemaDefinition; + properties?: Record; + required?: string[]; +} + +export const SchemaDefinitionSchema: z.ZodType = z.object({ + type: SchemaPrimitiveTypeSchema, + description: z.string().optional(), + items: z.lazy(() => SchemaDefinitionSchema).optional(), + properties: z.lazy(() => z.record(z.string(), SchemaDefinitionSchema)).optional(), + required: z.array(z.string()).optional(), +}); + +// ============================================================================ +// Tool Definition +// ============================================================================ + +/** + * Tool name validation for CLI input. + * Allows alphanumeric characters and hyphens. Underscores are not permitted + * for gateway targets. + * This is a general-purpose schema for tool names that works for both + * MCP runtime tools (direct) and gateway target tools. + */ +export const ToolNameSchema = z + .string() + .min(1, 'Tool name is required') + .max(128, 'Tool name must be at most 128 characters') + .regex( + /^[a-zA-Z][a-zA-Z0-9-]*$/, + 'Tool name must start with a letter and contain only alphanumeric characters or hyphens' + ); + +/** + * Gateway Target Definition schema. + */ +export const ToolDefinitionSchema = z + .object({ + name: z.string().min(1).max(128), + description: z.string().min(1), + inputSchema: SchemaDefinitionSchema, + outputSchema: SchemaDefinitionSchema.optional(), + }) + .strict(); + +export type ToolDefinition = z.infer; + +// ============================================================================ +// MCP Definitions File (mcp-defs.json) +// ============================================================================ + +/** + * Top-level MCP definitions file schema (mcp-defs.json). + */ +export const AgentCoreCliMcpDefsSchema = z.object({ + tools: z.record(z.string(), ToolDefinitionSchema), +}); + +export type AgentCoreCliMcpDefs = z.infer; diff --git a/src/projectSchemas/v0/schemas/mcp.ts b/src/projectSchemas/v0/schemas/mcp.ts new file mode 100644 index 0000000000..e320684e06 --- /dev/null +++ b/src/projectSchemas/v0/schemas/mcp.ts @@ -0,0 +1,1029 @@ +import { NetworkModeSchema, NodeRuntimeSchema, PythonRuntimeSchema } from '../constants'; +import type { DirectoryPath, FilePath } from '../types'; +import { EnvVarNameSchema, GatewayNameSchema } from './agent-env'; +import { GatewayAuthorizerConfigSchema, GatewayAuthorizerTypeSchema } from './auth'; +import { ToolDefinitionSchema } from './mcp-defs'; +import { TagsSchema } from './primitives/tags'; +import { z } from 'zod'; + +// ============================================================================ +// MCP-Specific Schemas +// ============================================================================ + +export const GatewayTargetTypeSchema = z.enum([ + 'lambda', + 'mcpServer', + 'openApiSchema', + 'smithyModel', + 'apiGateway', + 'lambdaFunctionArn', + 'httpRuntime', + 'connector', + 'passthrough', +]); +export type GatewayTargetType = z.infer; + +/** + * Target types that use the non-MCP (HTTP) protocol. + * These targets require a gateway with protocolType: "None". + */ +export const NON_MCP_TARGET_TYPES: readonly GatewayTargetType[] = ['httpRuntime', 'passthrough'] as const; + +/** + * Target types that use the MCP protocol. + */ +export const MCP_TARGET_TYPES: readonly GatewayTargetType[] = [ + 'lambda', + 'mcpServer', + 'openApiSchema', + 'smithyModel', + 'apiGateway', + 'lambdaFunctionArn', +] as const; + +// ============================================================================ +// Connector (managed-service gateway target) +// ============================================================================ + +/** + * Managed-service connector identifiers. The L3 maps each one to an operation + * name + Enabled list via CONNECTOR_DEFAULTS. + * + * Spec note: the original DevEx doc (cli-knowledge-bases-devex.md) uses + * `agentic-retrieve`, but that is now a configuration within bedrock-knowledge-bases + * rather than a standalone connector ID. + */ +export const CONNECTOR_ID = { + BEDROCK_KNOWLEDGE_BASES: 'bedrock-knowledge-bases', + WEB_SEARCH: 'web-search', +} as const; +export const CONNECTOR_ID_VALUES = [CONNECTOR_ID.BEDROCK_KNOWLEDGE_BASES, CONNECTOR_ID.WEB_SEARCH] as const; +export const ConnectorIdSchema = z.enum(CONNECTOR_ID_VALUES); +export type ConnectorId = z.infer; + +/** + * Real Bedrock Knowledge Base IDs are 10 uppercase alphanumeric chars. + * KB names follow the standard primitive-name shape (1-48 chars, starts with a letter). + * The two formats can never collide, so a KB reference in parameterValues + * is unambiguously a project KB name or a literal external KB ID. + */ +export const REAL_KB_ID_PATTERN = /^[A-Z0-9]{10}$/; + +// ============================================================================ +// Gateway Authorization Schemas +// ============================================================================ +// Auth schemas (GatewayAuthorizerTypeSchema, CustomJwtAuthorizerConfigSchema, etc.) +// are defined in ./auth.ts and exported via the barrel (index.ts). + +export const OutboundAuthTypeSchema = z.enum(['OAUTH', 'API_KEY', 'NONE', 'GATEWAY_IAM_ROLE', 'JWT_PASSTHROUGH']); +export type OutboundAuthType = z.infer; + +export const OutboundAuthSchema = z + .object({ + type: OutboundAuthTypeSchema.default('NONE'), + credentialName: z.string().min(1).optional(), + scopes: z.array(z.string()).optional(), + service: z.string().min(1).max(64).optional(), + region: z.string().min(1).max(32).optional(), + }) + .strict(); + +export type OutboundAuth = z.infer; + +// ============================================================================ +// Target Type → Auth Rules (single source of truth) +// ============================================================================ + +/** + * Outbound authentication rules per gateway target type. + * + * - `authRequired` — target cannot be created without outbound auth + * - `validAuthTypes` — allowed OutboundAuthType values (empty = no outbound auth applicable) + * - `iamRoleFallback` — CDK passes GATEWAY_IAM_ROLE when no auth configured + */ +export const TARGET_TYPE_AUTH_CONFIG: Record< + GatewayTargetType, + { authRequired: boolean; validAuthTypes: readonly OutboundAuthType[]; iamRoleFallback: boolean } +> = { + openApiSchema: { authRequired: true, validAuthTypes: ['OAUTH', 'API_KEY'], iamRoleFallback: false }, + smithyModel: { authRequired: false, validAuthTypes: [], iamRoleFallback: true }, + apiGateway: { authRequired: false, validAuthTypes: ['API_KEY', 'NONE'], iamRoleFallback: true }, + mcpServer: { authRequired: false, validAuthTypes: ['OAUTH', 'NONE'], iamRoleFallback: false }, + lambda: { authRequired: false, validAuthTypes: ['OAUTH', 'NONE'], iamRoleFallback: true }, + lambdaFunctionArn: { authRequired: false, validAuthTypes: ['OAUTH', 'NONE'], iamRoleFallback: true }, + httpRuntime: { authRequired: false, validAuthTypes: ['OAUTH', 'NONE'], iamRoleFallback: true }, + // Connector targets call the underlying managed service (Bedrock KB, etc.) + // via the gateway's IAM role. No outbound auth applies. + connector: { authRequired: false, validAuthTypes: [], iamRoleFallback: true }, + passthrough: { + authRequired: true, + validAuthTypes: ['GATEWAY_IAM_ROLE', 'OAUTH', 'JWT_PASSTHROUGH'], + iamRoleFallback: false, + }, +}; + +// ============================================================================ +// API Gateway Target Schemas +// ============================================================================ + +export const ApiGatewayHttpMethodSchema = z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']); +export type ApiGatewayHttpMethod = z.infer; + +export const ApiGatewayToolFilterSchema = z + .object({ + filterPath: z.string().min(1), + methods: z.array(ApiGatewayHttpMethodSchema).min(1), + }) + .strict(); + +export const ApiGatewayToolOverrideSchema = z + .object({ + name: z.string().min(1), + path: z.string().min(1), + method: ApiGatewayHttpMethodSchema, + description: z.string().optional(), + }) + .strict(); + +export const ApiGatewayToolConfigurationSchema = z + .object({ + toolFilters: z.array(ApiGatewayToolFilterSchema).min(1), + toolOverrides: z.array(ApiGatewayToolOverrideSchema).optional(), + }) + .strict(); + +export const ApiGatewayConfigSchema = z + .object({ + restApiId: z.string().min(1), + stage: z.string().min(1), + apiGatewayToolConfiguration: ApiGatewayToolConfigurationSchema, + }) + .strict(); +export type ApiGatewayConfig = z.infer; + +export const LambdaFunctionArnConfigSchema = z + .object({ + lambdaArn: z.string().min(1).max(170), + toolSchemaFile: z.string().min(1), + }) + .strict(); +export type LambdaFunctionArnConfig = z.infer; + +export const McpImplLanguageSchema = z.enum(['TypeScript', 'Python']); +export type McpImplementationLanguage = z.infer; + +export const ComputeHostSchema = z.enum(['Lambda', 'AgentCoreRuntime']); +export type ComputeHost = z.infer; + +// ============================================================================ +// Branded Path Schemas +// ============================================================================ + +// Branded path schemas - cast string output to branded path types +const DirectoryPathSchema = z.string().min(1) as unknown as z.ZodType; + +// ============================================================================ +// Tool Implementation Binding +// ============================================================================ + +/** + * Code-based tool implementation (Python, TypeScript). + * + * The CLI is responsible for: + * - installing dependencies + * - building / bundling + * - creating a zip artifact + * - uploading artifacts to S3 + */ +export const ToolImplementationBindingSchema = z + .object({ + language: z.enum(['TypeScript', 'Python']), + path: z.string().min(1), + handler: z.string().min(1), + }) + .strict(); + +export type ToolImplementationBinding = z.infer; + +// ============================================================================ +// IAM Policy Document +// ============================================================================ + +/** + * Opaque IAM policy document. + * + * This is passed through verbatim to CloudFormation / IAM. + * AgentCore does not validate, transform, or provide compatibility guarantees. + */ +export const IamPolicyDocumentSchema = z + .object({ + Version: z.string(), + Statement: z.array(z.unknown()), + }) + .passthrough(); // Allow additional IAM policy fields + +export type IamPolicyDocument = z.infer; + +// ============================================================================ +// Runtime Configuration +// ============================================================================ + +/** + * AgentCore Runtime name validation. + * Pattern: [a-zA-Z][a-zA-Z0-9_]{0,47} + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-bedrockagentcore-runtime.html#cfn-bedrockagentcore-runtime-agentruntimename + */ +const AgentRuntimeNameSchema = z + .string() + .min(1) + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +/** + * Python entrypoint validation for Runtime codeConfiguration. + * Format: "file.py" or "file.py:handler" or "path/file.py:handler" + */ +const PythonEntrypointSchema = z + .string() + .min(1) + .regex( + // eslint-disable-next-line security/detect-unsafe-regex -- character class quantifiers don't cause backtracking + /^[a-zA-Z0-9_][a-zA-Z0-9_/.-]*\.py(:[a-zA-Z_][a-zA-Z0-9_]*)?$/, + 'Must be a Python file path with optional handler (e.g., "main.py:agent" or "src/handler.py:app")' + ) as unknown as z.ZodType; + +/** + * Instrumentation configuration for runtime observability. + */ +const InstrumentationSchema = z.object({ + /** + * Enable OpenTelemetry instrumentation using opentelemetry-distro. + * When enabled, the runtime entrypoint is wrapped with opentelemetry-instrument. + * Defaults to true for new runtimes. + */ + enableOtel: z.boolean().default(true), +}); + +const CodeZipRuntimeConfigSchema = z + .object({ + artifact: z.literal('CodeZip'), + pythonVersion: PythonRuntimeSchema, + name: AgentRuntimeNameSchema, + entrypoint: PythonEntrypointSchema, + codeLocation: DirectoryPathSchema, + /** Instrumentation settings for observability. Defaults to OTel enabled. */ + instrumentation: InstrumentationSchema.optional(), + networkMode: NetworkModeSchema.optional().default('PUBLIC'), + description: z.string().optional(), + }) + .strict(); + +export type CodeZipRuntimeConfig = z.infer; + +/** + * Runtime configuration for AgentCore Runtime (MCP mode). + * Explicit CodeZip artifact configuration - no CLI-managed defaults. + */ +export const RuntimeConfigSchema = CodeZipRuntimeConfigSchema; + +export type RuntimeConfig = z.infer; + +// ============================================================================ +// Compute Configuration +// ============================================================================ + +/** + * Lambda compute configuration schema. + * Lambda supports both Python and TypeScript. + */ +const LambdaComputeConfigSchema = z + .object({ + host: z.literal('Lambda'), + implementation: ToolImplementationBindingSchema, + nodeVersion: NodeRuntimeSchema.optional(), + pythonVersion: PythonRuntimeSchema.optional(), + timeout: z.number().int().min(1).max(900).optional(), + memorySize: z.number().int().min(128).max(10240).optional(), + iamPolicy: IamPolicyDocumentSchema.optional(), + }) + .strict() + .refine( + data => { + // TypeScript requires nodeVersion + if (data.implementation.language === 'TypeScript' && !data.nodeVersion) { + return false; + } + // Python requires pythonVersion + if (data.implementation.language === 'Python' && !data.pythonVersion) { + return false; + } + // Other (container) does not require runtime version - uses container image + return true; + }, + { + message: 'TypeScript Lambda must specify nodeVersion, Python Lambda must specify pythonVersion', + } + ); + +export type LambdaComputeConfig = z.infer; + +/** + * AgentCore Runtime compute configuration schema. + * AgentCore Runtime ONLY supports Python. + */ +const AgentCoreRuntimeComputeConfigSchema = z + .object({ + host: z.literal('AgentCoreRuntime'), + implementation: ToolImplementationBindingSchema, + runtime: RuntimeConfigSchema.optional(), + iamPolicy: IamPolicyDocumentSchema.optional(), + }) + .strict() + .refine(data => data.implementation.language === 'Python', { + message: 'AgentCore Runtime only supports Python', + }); + +export type AgentCoreRuntimeComputeConfig = z.infer; + +/** + * Tool compute configuration (discriminated union). + */ +export const ToolComputeConfigSchema = z.discriminatedUnion('host', [ + LambdaComputeConfigSchema, + AgentCoreRuntimeComputeConfigSchema, +]); + +export type ToolComputeConfig = z.infer; + +// ============================================================================ +// Schema Source (for OpenAPI / Smithy targets) +// ============================================================================ + +/** S3 reference for an API schema file. */ +const SchemaS3SourceSchema = z + .object({ + uri: z.string().min(1).startsWith('s3://'), + bucketOwnerAccountId: z.string().optional(), + }) + .strict(); + +/** Inline (local file) reference for an API schema file. Path is relative to project root. */ +const SchemaInlineSourceSchema = z + .object({ + path: z.string().min(1), + }) + .strict(); + +/** Schema source: either a local file path (read at synth time) or an S3 URI. */ +export const SchemaSourceSchema = z.union([ + z.object({ inline: SchemaInlineSourceSchema }).strict(), + z.object({ s3: SchemaS3SourceSchema }).strict(), +]); +export type SchemaSource = z.infer; + +// ============================================================================ +// HTTP Runtime Configuration +// ============================================================================ + +export const HttpRuntimeConfigSchema = z + .object({ + runtime: z.string().min(1), + runtimeEndpoint: z.string().min(1).optional(), + }) + .strict(); + +export type HttpRuntimeConfig = z.infer; + +// ============================================================================ +// Passthrough Target Configuration +// ============================================================================ + +export const StickinessConfigSchema = z + .object({ + identifier: z.string().min(1).max(256), + timeout: z.number().int().min(1).max(86400).optional(), + }) + .strict(); +export type StickinessConfig = z.infer; + +/** + * Passthrough protocol type. HTTP is NOT valid — use CUSTOM for plain HTTP/REST backends. + */ +export const PassthroughProtocolTypeSchema = z.enum(['MCP', 'A2A', 'INFERENCE', 'CUSTOM']); +export type PassthroughProtocolType = z.infer; + +export const PassthroughConfigSchema = z + .object({ + endpoint: z + .string() + .min(1) + .regex(/^https:\/\/[a-zA-Z0-9\-.]+(:[0-9]{1,5})?(\/.*)?$/, 'Must be a valid HTTPS URL'), + /** Protocol type for the passthrough backend. Defaults to CUSTOM (generic HTTP/REST). */ + protocolType: PassthroughProtocolTypeSchema.default('CUSTOM'), + stickinessConfiguration: StickinessConfigSchema.optional(), + }) + .strict(); +export type PassthroughConfig = z.infer; + +// ============================================================================ +// Gateway Target +// ============================================================================ + +/** + * A gateway target binds one or more ToolDefinitions to compute that services them. + * + * A single Lambda or AgentCoreRuntime can expose multiple tools. The gateway routes + * tool invocations to the appropriate target based on tool name. + * + * If compute is omitted, the tools are treated as external or abstract targets. + */ +export const AgentCoreGatewayTargetSchema = z + .object({ + name: z.string().min(1), + targetType: GatewayTargetTypeSchema, + /** Tool definitions. Required for Lambda targets. Optional for MCP Server (discovered via tools/list). */ + toolDefinitions: z.array(ToolDefinitionSchema).optional(), + /** Compute configuration. Required for Lambda/Runtime scaffold targets. */ + compute: ToolComputeConfigSchema.optional(), + /** Endpoint URL for mcpServer targets. */ + endpoint: z.string().url().optional(), + /** Outbound auth configuration for the target. */ + outboundAuth: OutboundAuthSchema.optional(), + /** API Gateway configuration. Required for apiGateway target type. */ + apiGateway: ApiGatewayConfigSchema.optional(), + /** Schema source for openApiSchema / smithyModel targets. */ + schemaSource: SchemaSourceSchema.optional(), + /** Lambda Function ARN configuration. Required for lambdaFunctionArn target type. */ + lambdaFunctionArn: LambdaFunctionArnConfigSchema.optional(), + /** HTTP Runtime configuration. Required for httpRuntime target type. */ + httpRuntime: HttpRuntimeConfigSchema.optional(), + /** + * Managed-service connector identifier. Required for `connector` target type. + */ + connectorId: ConnectorIdSchema.optional(), + /** + * Per-operation configuration entries for connector targets. Each entry + * represents a tool the connector exposes (e.g. "Retrieve", "AgenticRetrieveStream", + * "WebSearch"). Written by the CLI translator from bespoke flags or hand-edited + * by customers for advanced settings. + */ + configurations: z + .array( + z.object({ + name: z.string(), + description: z.string().optional(), + parameterValues: z.record(z.string(), z.unknown()).optional(), + parameterOverrides: z + .array( + z.object({ + path: z.string(), + description: z.string().optional(), + visible: z.boolean().optional(), + }) + ) + .optional(), + }) + ) + .optional(), + /** Passthrough configuration. Required for passthrough target type. */ + passthrough: PassthroughConfigSchema.optional(), + }) + .strict() + .superRefine((data, ctx) => { + if (data.targetType === 'apiGateway') { + if (!data.apiGateway) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'apiGateway config is required for apiGateway target type', + path: ['apiGateway'], + }); + } + if (data.compute) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'compute is not applicable for apiGateway target type', + path: ['compute'], + }); + } + if (data.endpoint) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'endpoint is not applicable for apiGateway target type', + path: ['endpoint'], + }); + } + if (data.toolDefinitions && data.toolDefinitions.length > 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'toolDefinitions is not applicable for apiGateway target type (tools are auto-discovered)', + path: ['toolDefinitions'], + }); + } + if (data.lambdaFunctionArn) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'lambdaFunctionArn is not applicable for apiGateway target type', + path: ['lambdaFunctionArn'], + }); + } + } + if (data.targetType === 'openApiSchema' || data.targetType === 'smithyModel') { + if (!data.schemaSource) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `${data.targetType} targets require a schemaSource.`, + path: ['schemaSource'], + }); + } + if (data.compute) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `compute is not applicable for ${data.targetType} target type`, + path: ['compute'], + }); + } + if (data.endpoint) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `endpoint is not applicable for ${data.targetType} target type`, + path: ['endpoint'], + }); + } + if (data.toolDefinitions && data.toolDefinitions.length > 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `toolDefinitions is not applicable for ${data.targetType} target type`, + path: ['toolDefinitions'], + }); + } + if (data.apiGateway) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `apiGateway config is not applicable for ${data.targetType} target type`, + path: ['apiGateway'], + }); + } + } + if (data.targetType === 'lambdaFunctionArn') { + if (!data.lambdaFunctionArn) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'lambdaFunctionArn config is required for lambdaFunctionArn target type', + path: ['lambdaFunctionArn'], + }); + } + if (data.compute) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'compute is not applicable for lambdaFunctionArn target type', + path: ['compute'], + }); + } + if (data.endpoint) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'endpoint is not applicable for lambdaFunctionArn target type', + path: ['endpoint'], + }); + } + if (data.apiGateway) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'apiGateway is not applicable for lambdaFunctionArn target type', + path: ['apiGateway'], + }); + } + if (data.outboundAuth) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'outboundAuth is not applicable for lambdaFunctionArn target type', + path: ['outboundAuth'], + }); + } + if (data.toolDefinitions && data.toolDefinitions.length > 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + 'toolDefinitions is not applicable for lambdaFunctionArn target type (tools are defined via toolSchemaFile)', + path: ['toolDefinitions'], + }); + } + } + if (data.targetType === 'mcpServer') { + if (!data.compute && !data.endpoint) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'MCP Server targets require either an endpoint URL or compute configuration.', + }); + } + if (data.apiGateway) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'apiGateway is not applicable for mcpServer target type', + path: ['apiGateway'], + }); + } + if (data.lambdaFunctionArn) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'lambdaFunctionArn is not applicable for mcpServer target type', + path: ['lambdaFunctionArn'], + }); + } + } + if (data.targetType === 'httpRuntime') { + if (!data.httpRuntime) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'httpRuntime targets require an httpRuntime configuration (with a runtime reference).', + path: ['httpRuntime'], + }); + } + if (data.endpoint) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'httpRuntime targets should use httpRuntime.runtimeEndpoint instead of endpoint.', + path: ['endpoint'], + }); + } + if (data.compute) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'compute is not applicable for httpRuntime target type', + path: ['compute'], + }); + } + if (data.apiGateway) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'apiGateway is not applicable for httpRuntime target type', + path: ['apiGateway'], + }); + } + if (data.lambdaFunctionArn) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'lambdaFunctionArn is not applicable for httpRuntime target type', + path: ['lambdaFunctionArn'], + }); + } + if (data.toolDefinitions && data.toolDefinitions.length > 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'toolDefinitions is not applicable for httpRuntime target type', + path: ['toolDefinitions'], + }); + } + } + if (data.targetType === 'passthrough') { + if (!data.passthrough) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'passthrough targets require a passthrough configuration (with an endpoint).', + path: ['passthrough'], + }); + } + if (data.endpoint) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'passthrough targets should use passthrough.endpoint instead of endpoint.', + path: ['endpoint'], + }); + } + if (data.compute) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'compute is not applicable for passthrough target type', + path: ['compute'], + }); + } + if (data.apiGateway) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'apiGateway is not applicable for passthrough target type', + path: ['apiGateway'], + }); + } + if (data.lambdaFunctionArn) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'lambdaFunctionArn is not applicable for passthrough target type', + path: ['lambdaFunctionArn'], + }); + } + if (data.httpRuntime) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'httpRuntime is not applicable for passthrough target type', + path: ['httpRuntime'], + }); + } + if (data.toolDefinitions && data.toolDefinitions.length > 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'toolDefinitions is not applicable for passthrough target type', + path: ['toolDefinitions'], + }); + } + } + if (data.targetType === 'lambda' && !data.compute) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Lambda targets require compute configuration.', + path: ['compute'], + }); + } + if (data.targetType === 'lambda' && (!data.toolDefinitions || data.toolDefinitions.length === 0)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Lambda targets require at least one tool definition.', + path: ['toolDefinitions'], + }); + } + if (data.targetType === 'connector') { + if (!data.connectorId) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'connectorId is required for connector target type', + path: ['connectorId'], + }); + } + if (data.compute) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'compute is not applicable for connector target type', + path: ['compute'], + }); + } + if (data.endpoint) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'endpoint is not applicable for connector target type', + path: ['endpoint'], + }); + } + if (data.toolDefinitions && data.toolDefinitions.length > 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'toolDefinitions is not applicable for connector target type', + path: ['toolDefinitions'], + }); + } + if (data.apiGateway) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'apiGateway is not applicable for connector target type', + path: ['apiGateway'], + }); + } + if (data.lambdaFunctionArn) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'lambdaFunctionArn is not applicable for connector target type', + path: ['lambdaFunctionArn'], + }); + } + if (data.schemaSource) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'schemaSource is not applicable for connector target type', + path: ['schemaSource'], + }); + } + if (data.httpRuntime) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'httpRuntime is not applicable for connector target type', + path: ['httpRuntime'], + }); + } + if (data.passthrough) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'passthrough is not applicable for connector target type', + path: ['passthrough'], + }); + } + } + if (data.targetType !== 'connector') { + if (data.connectorId) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `connectorId only applies to connector target type`, + path: ['connectorId'], + }); + } + if (data.configurations && data.configurations.length > 0) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `configurations only applies to connector target type`, + path: ['configurations'], + }); + } + } + // Centralized outbound auth validation (driven by TARGET_TYPE_AUTH_CONFIG) + const authConfig = TARGET_TYPE_AUTH_CONFIG[data.targetType]; + const authType = data.outboundAuth?.type ?? 'NONE'; + if (authConfig.authRequired && authType === 'NONE') { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `${data.targetType} targets require outbound auth (${authConfig.validAuthTypes.join(' or ')})`, + path: ['outboundAuth'], + }); + } + if (authConfig.validAuthTypes.length === 0 && authType !== 'NONE') { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `${data.targetType} targets use IAM role auth; outboundAuth is not applicable`, + path: ['outboundAuth'], + }); + } + if (authConfig.validAuthTypes.length > 0 && authType !== 'NONE' && !authConfig.validAuthTypes.includes(authType)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `${data.targetType} targets do not support ${authType} outbound auth`, + path: ['outboundAuth'], + }); + } + if ( + data.outboundAuth && + data.outboundAuth.type !== 'NONE' && + data.outboundAuth.type !== 'GATEWAY_IAM_ROLE' && + data.outboundAuth.type !== 'JWT_PASSTHROUGH' && + !data.outboundAuth.credentialName + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `${data.outboundAuth.type} outbound auth requires a credentialName.`, + path: ['outboundAuth', 'credentialName'], + }); + } + // GATEWAY_IAM_ROLE on passthrough requires service + if ( + data.targetType === 'passthrough' && + data.outboundAuth?.type === 'GATEWAY_IAM_ROLE' && + !data.outboundAuth.service + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'GATEWAY_IAM_ROLE outbound auth on passthrough targets requires a service name.', + path: ['outboundAuth', 'service'], + }); + } + // JWT_PASSTHROUGH is only valid for passthrough targets + if (data.outboundAuth?.type === 'JWT_PASSTHROUGH' && data.targetType !== 'passthrough') { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'JWT_PASSTHROUGH outbound auth is only valid for passthrough targets.', + path: ['outboundAuth', 'type'], + }); + } + }); + +export type AgentCoreGatewayTarget = z.infer; + +// ============================================================================ +// Gateway Exception Level +// ============================================================================ + +export const GatewayExceptionLevelSchema = z.enum(['NONE', 'DEBUG']); +export type GatewayExceptionLevel = z.infer; + +// ============================================================================ +// Gateway Policy Engine Configuration +// ============================================================================ + +export const PolicyEngineModeSchema = z.enum(['LOG_ONLY', 'ENFORCE']); +export type PolicyEngineMode = z.infer; + +export const GatewayPolicyEngineConfigurationSchema = z + .object({ + policyEngineName: z.string().min(1), + mode: PolicyEngineModeSchema, + }) + .strict(); +export type GatewayPolicyEngineConfiguration = z.infer; + +// ============================================================================ +// Gateway +// ============================================================================ + +/** + * Gateway abstraction with opinionated defaults. + * Supports NONE (default) or CUSTOM_JWT authorizer types. + */ +export const GatewayProtocolTypeSchema = z.enum(['MCP', 'None']); +export type GatewayProtocolType = z.infer; + +export const AgentCoreGatewaySchema = z + .object({ + name: GatewayNameSchema, + /** Actual AWS resource name for imported gateways. When set, CDK uses this instead of generating projectName-name. */ + resourceName: GatewayNameSchema.optional(), + /** Protocol type for this gateway. */ + protocolType: GatewayProtocolTypeSchema.optional(), + description: z.string().optional(), + targets: z.array(AgentCoreGatewayTargetSchema), + /** Authorization type for the gateway. Defaults to 'NONE'. */ + authorizerType: GatewayAuthorizerTypeSchema.default('NONE'), + /** Authorizer configuration. Required when authorizerType is 'CUSTOM_JWT'. */ + authorizerConfiguration: GatewayAuthorizerConfigSchema.optional(), + /** Whether to enable semantic search for tool discovery. Defaults to true. */ + enableSemanticSearch: z.boolean().default(true), + /** Exception verbosity level. 'NONE' = generic errors (default), 'DEBUG' = verbose errors. */ + exceptionLevel: GatewayExceptionLevelSchema.default('NONE'), + /** Policy engine configuration for Cedar-based authorization of tool calls. */ + policyEngineConfiguration: GatewayPolicyEngineConfigurationSchema.optional(), + /** ARN of an existing IAM execution role. When set, CDK uses this role instead of creating a new one. */ + executionRoleArn: z + .string() + .regex(/^arn:[^:]+:iam::\d{12}:role\/.+/, 'Must be a valid IAM role ARN') + .max(2048) + .optional(), + tags: TagsSchema.optional(), + }) + .strict() + .refine( + data => { + // If authorizerType is CUSTOM_JWT, customJwtAuthorizer config must be provided + if (data.authorizerType === 'CUSTOM_JWT') { + return data.authorizerConfiguration?.customJwtAuthorizer !== undefined; + } + return true; + }, + { + message: 'customJwtAuthorizer configuration is required when authorizerType is CUSTOM_JWT', + path: ['authorizerConfiguration'], + } + ) + .superRefine((gw, ctx) => { + // A protocolType: "None" (HTTP) gateway is a superset: it can host any target + // type, including MCP targets (mcpServer, connector, KB, etc.). Only an MCP + // gateway is restrictive — it cannot host the HTTP-only target types. + for (const target of gw.targets) { + if (gw.protocolType !== 'None' && NON_MCP_TARGET_TYPES.includes(target.targetType)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Target "${target.name}" is ${target.targetType} but gateway does not have protocolType: "None". Add --protocol-type None when creating the gateway.`, + }); + } + } + }); + +export type AgentCoreGateway = z.infer; + +// ============================================================================ +// MCP Runtime Tool +// ============================================================================ + +/** + * Binding from an MCP runtime tool to a runtime. + * When present, the runtime is granted InvokeAgentRuntime permission + * and receives the runtime ARN in the specified environment variable. + */ +export const McpRuntimeBindingSchema = z + .object({ + runtimeName: z.string().min(1), + envVarName: EnvVarNameSchema, + }) + .strict(); + +export type McpRuntimeBinding = z.infer; + +/** + * AgentCore MCP Runtime tool servers. + * + * These are not behind a Gateway. They are deployed as AgentCoreRuntime compute + * and are directly addressable by agents via the generated DNS endpoint. + * + * Use the `bindings` array to grant agents permission to invoke this tool. + * Each binding grants InvokeAgentRuntime permission and sets an environment variable + * with the runtime ARN on the bound agent. + */ +export const AgentCoreMcpRuntimeToolSchema = z + .object({ + name: z.string().min(1), + toolDefinition: ToolDefinitionSchema, + compute: AgentCoreRuntimeComputeConfigSchema, + bindings: z.array(McpRuntimeBindingSchema).optional(), + }) + .strict(); + +export type AgentCoreMcpRuntimeTool = z.infer; + +// ============================================================================ +// MCP Spec Type (convenience alias) +// ============================================================================ + +/** + * Shape of MCP-related fields within AgentCoreProjectSpec. + * These fields are now part of agentcore.json (previously in mcp.json). + */ +export interface AgentCoreMcpSpec { + agentCoreGateways: AgentCoreGateway[]; + mcpRuntimeTools?: AgentCoreMcpRuntimeTool[]; + unassignedTargets?: AgentCoreGatewayTarget[]; +} diff --git a/src/projectSchemas/v0/schemas/primitives/ab-test.ts b/src/projectSchemas/v0/schemas/primitives/ab-test.ts new file mode 100644 index 0000000000..431bdf7b93 --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/ab-test.ts @@ -0,0 +1,145 @@ +import { z } from 'zod'; + +// ============================================================================ +// AB Test Types +// ============================================================================ + +export const ABTestNameSchema = z + .string() + .min(1, 'Name is required') + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +export const ABTestDescriptionSchema = z.string().min(1).max(200).optional(); + +export const ABTestModeSchema = z.enum(['config-bundle', 'target-based']).optional().default('config-bundle'); + +export type ABTestMode = z.infer; + +export const VariantNameSchema = z.enum(['C', 'T1']); + +export const VariantWeightSchema = z.number().int().min(1).max(100); + +// ── Config Bundle variant configuration ──────────────────────────────────── + +export const ConfigurationBundleRefSchema = z.object({ + bundleArn: z.string().min(1), + bundleVersion: z.string().min(1), +}); + +export type ConfigurationBundleRef = z.infer; + +// ── Target-based variant configuration ───────────────────────────────────── + +export const TargetRefSchema = z.object({ + targetName: z.string().min(1).max(100), +}); + +export type TargetRef = z.infer; + +// ── Variant configuration union ──────────────────────────────────────────── +// Exactly one of configurationBundle or target must be set (XOR). + +const ConfigBundleVariantConfigSchema = z.object({ + configurationBundle: ConfigurationBundleRefSchema, + target: z.never().optional(), +}); + +const TargetVariantConfigSchema = z.object({ + configurationBundle: z.never().optional(), + target: TargetRefSchema, +}); + +export const VariantConfigurationSchema = z.union([ConfigBundleVariantConfigSchema, TargetVariantConfigSchema]); + +export type VariantConfiguration = z.infer; + +export const ABTestVariantSchema = z.object({ + name: VariantNameSchema, + weight: VariantWeightSchema, + variantConfiguration: VariantConfigurationSchema, +}); + +export type ABTestVariant = z.infer; + +// ── Evaluation config union ──────────────────────────────────────────────── + +export const PerVariantOnlineEvaluationConfigSchema = z.object({ + treatmentName: VariantNameSchema, + onlineEvaluationConfigArn: z.string().min(1), +}); + +export type PerVariantOnlineEvaluationConfig = z.infer; + +export const ABTestEvaluationConfigSchema = z.union([ + z.object({ onlineEvaluationConfigArn: z.string().min(1) }), + z.object({ + perVariantOnlineEvaluationConfig: z.array(PerVariantOnlineEvaluationConfigSchema).length(2), + }), +]); + +export type ABTestEvaluationConfig = z.infer; + +// ── Gateway filter ───────────────────────────────────────────────────────── + +export const GatewayFilterSchema = z.object({ + targetPaths: z.array(z.string().min(1).max(500)).max(1), +}); + +export type GatewayFilter = z.infer; + +// ── Traffic allocation ───────────────────────────────────────────────────── + +export const TrafficRouteOnHeaderSchema = z.object({ + headerName: z.string().min(1), +}); + +export const TrafficAllocationConfigSchema = z.object({ + routeOnHeader: TrafficRouteOnHeaderSchema, +}); + +export type TrafficAllocationConfig = z.infer; + +// ── AB Test schema ───────────────────────────────────────────────────────── + +export const ABTestSchema = z + .object({ + name: ABTestNameSchema, + description: ABTestDescriptionSchema, + mode: ABTestModeSchema, + gatewayRef: z.string().min(1), + roleArn: z.string().min(1).optional(), + variants: z.array(ABTestVariantSchema).length(2), + evaluationConfig: ABTestEvaluationConfigSchema, + gatewayFilter: GatewayFilterSchema.optional(), + enableOnCreate: z.boolean().optional(), + promoted: z.boolean().optional(), + }) + .refine( + data => { + const names = data.variants.map(v => v.name); + return names.includes('C') && names.includes('T1'); + }, + { message: 'Variants must include exactly one control (C) and one treatment (T1)', path: ['variants'] } + ) + .refine(data => data.variants.reduce((sum, v) => sum + v.weight, 0) === 100, { + message: 'Variant weights must sum to 100', + path: ['variants'], + }) + .refine( + data => { + if (data.mode === 'target-based') { + return data.variants.every(v => v.variantConfiguration.target != null); + } + return data.variants.every(v => v.variantConfiguration.configurationBundle != null); + }, + { + message: 'Target-based mode requires target on each variant; config-bundle mode requires configurationBundle', + path: ['variants'], + } + ); + +export type ABTest = z.infer; diff --git a/src/projectSchemas/v0/schemas/primitives/capacity-provider.ts b/src/projectSchemas/v0/schemas/primitives/capacity-provider.ts new file mode 100644 index 0000000000..ca2437696b --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/capacity-provider.ts @@ -0,0 +1,284 @@ +import { TagsSchema } from './tags'; +import { z } from 'zod'; + +// ============================================================================ +// Capacity Provider Types +// +// Models the AWS::BedrockAgentCore::CapacityProvider CFN resource. Known fields +// are typed and validated here so bad input is rejected at `add` time instead +// of failing late at deploy/CFN time; the long tail of launch parameters is +// accepted via `.passthrough()` and validated by CFN on deploy. +// +// NOTE: This schema is duplicated in @aws/agentcore-cdk +// (src/schema/schemas/primitives/capacity-provider.ts). Keep the two in sync. +// ============================================================================ + +/** + * Capacity provider name validation. + * Pattern: ^[a-zA-Z][a-zA-Z0-9_]{0,47}$ (matches the CFN Name property). + */ +export const CapacityProviderNameSchema = z + .string() + .min(1, 'Capacity provider name is required') + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +// ============================================================================ +// Operator Role ARN Validation +// ============================================================================ + +/** + * Pattern for the capacity provider operator role ARN, matching the CFN + * resource contract exactly. The account segment is OPTIONAL — the service + * accepts role ARNs without an account id, so we must not force 12 digits. + */ +// eslint-disable-next-line security/detect-unsafe-regex -- anchored ARN pattern, no backtracking risk +export const CAPACITY_PROVIDER_OPERATOR_ROLE_ARN_PATTERN = /^arn:[^:]+:iam::([0-9]{12})?:role\/.+$/; + +export const OperatorRoleArnSchema = z + .string() + .min(1, 'Operator role ARN is required') + .max(2048) + .regex( + CAPACITY_PROVIDER_OPERATOR_ROLE_ARN_PATTERN, + 'Must be a valid IAM role ARN (e.g. arn::iam::123456789012:role/MyOperatorRole)' + ); + +export function isValidOperatorRoleArn(value: string): boolean { + return CAPACITY_PROVIDER_OPERATOR_ROLE_ARN_PATTERN.test(value); +} + +// ============================================================================ +// Capacity Provider Attach (runtime -> capacity provider reference) +// +// A runtime attaches to a capacity provider via `capacityProviderConfiguration`. +// The reference is EITHER an in-project sibling (by name) OR an external CP (by +// ARN) — exactly one. At synth the CDK app resolves a sibling name to the created +// CP's ARN, or passes the ARN through, then injects +// CapacityProviderConfiguration.CapacityProviderArn onto the CfnRuntime. +// +// NOTE: This block is duplicated in @aws/agentcore-cdk. Keep the two in sync. +// ============================================================================ + +/** + * Partition-agnostic capacity-provider ARN (arn:[^:]+: per multi-partition rules). The resource + * segment is the service capacityProviderId — `{name}-{10 alnum}` — not a free-form string, so a + * malformed external ARN is rejected at `add`/validate time instead of only failing at deploy. + * Keep the id shape in sync with CAPACITY_PROVIDER_ID_PATTERN (cli/commands/capacity-provider/constants). + */ +export const CAPACITY_PROVIDER_ARN_PATTERN = + /^arn:[^:]+:bedrock-agentcore:[a-z0-9-]+:\d{12}:capacity-provider\/[a-zA-Z][a-zA-Z0-9_]{0,47}-[a-zA-Z0-9]{10}$/; + +export const CapacityProviderArnSchema = z + .string() + .regex( + CAPACITY_PROVIDER_ARN_PATTERN, + 'Must be a valid bedrock-agentcore capacity provider ARN (…:capacity-provider/{name}-{10 alphanumerics})' + ); + +/** + * Route a `--capacity-provider ` value: an `arn:` prefix means an + * external CP referenced by ARN, otherwise it is an in-project sibling name. + */ +export function isCapacityProviderArn(value: string): boolean { + return value.startsWith('arn:'); +} + +/** + * Logical name of a capacity-provider volume, referenced by a runtime's + * `capacityProviderVolume` filesystem mount. Must match the name of a volume + * defined on the capacity provider (EbsVolumeConfiguration.name). + */ +export const CapacityProviderVolumeNameSchema = z + .string() + .min(1, 'Capacity provider volume name is required') + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_-]{0,47}$/, + 'Volume name must begin with a letter and contain only alphanumerics, underscores, and hyphens (max 48 chars)' + ); + +/** + * Runtime -> capacity-provider reference. Exactly one of `capacityProviderArn` + * (external CP) or `capacityProviderName` (in-project sibling) must be set. + */ +export const CapacityProviderConfigurationSchema = z + .strictObject({ + /** ARN of an external capacity provider (not defined in this project). */ + capacityProviderArn: CapacityProviderArnSchema.optional(), + /** Name of an in-project capacity provider (a `capacityProviders[]` sibling). */ + capacityProviderName: CapacityProviderNameSchema.optional(), + }) + .superRefine((data, ctx) => { + if ((data.capacityProviderArn !== undefined) === (data.capacityProviderName !== undefined)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'capacityProviderConfiguration must set exactly one of capacityProviderArn or capacityProviderName', + }); + } + }); +export type CapacityProviderConfiguration = z.infer; + +// ============================================================================ +// Operating System +// +// The CFN resource enum lists four values (LINUX_X86_64, LINUX_ARM64, +// MAC_ARM64, WINDOWS_X86_64), but the service API contract only supports the +// two Linux values today; the extra two leaked into the CFN autogen ahead of +// real support. The CLI follows the API and exposes only the Linux values. +// ============================================================================ + +export const OperatingSystemSchema = z.enum(['LINUX_X86_64', 'LINUX_ARM64']); +export type OperatingSystem = z.infer; + +// ============================================================================ +// VPC Configuration +// ============================================================================ + +export const VpcConfigurationSchema = z.object({ + subnets: z + .array(z.string().regex(/^subnet-[0-9a-zA-Z]{8,17}$/, 'Must be a valid subnet ID')) + .min(1, 'At least one subnet is required') + .max(16), + securityGroups: z + .array(z.string().regex(/^sg-[0-9a-zA-Z]{8,17}$/, 'Must be a valid security group ID')) + .min(1, 'At least one security group is required') + .max(16), +}); + +export type VpcConfiguration = z.infer; + +// ============================================================================ +// Instance Requirements +// ============================================================================ + +export const InstanceRequirementsSchema = z.object({ + allowedInstanceTypes: z.array(z.string().min(1).max(255)).min(1, 'At least one instance type is required').max(30), +}); + +export type InstanceRequirements = z.infer; + +// ============================================================================ +// Launch Parameters +// +// Known fields are typed; the long tail (sshKeyName, monitoring, +// licenseSpecifications, capacityReservationSpecification, ephemeralVolumes, +// propagatedTags) is accepted via `.passthrough()` and validated by CFN. +// ============================================================================ + +export const LaunchParametersSchema = z + .object({ + operatingSystem: OperatingSystemSchema, + instanceRequirements: InstanceRequirementsSchema, + instanceProfileArn: z + .string() + .regex(/^arn:[^:]+:iam::[0-9]{12}:instance-profile\/.+$/, 'Must be a valid IAM instance profile ARN') + .optional(), + }) + .passthrough(); + +export type LaunchParameters = z.infer; + +// ============================================================================ +// EBS Volume Configuration +// +// Known fields typed; EBS long-tail tuning (iops, throughput, snapshotId) is +// accepted via `.passthrough()`. +// ============================================================================ + +export const EbsVolumeConfigurationSchema = z + .object({ + name: z + .string() + .min(1) + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_-]{0,47}$/, + 'Volume name must begin with a letter and contain only alphanumerics, underscores, and hyphens (max 48 chars)' + ), + sizeGiB: z.number().int().min(1).max(65536), + volumeType: z.enum(['standard', 'io1', 'io2', 'gp2', 'sc1', 'st1', 'gp3']).optional(), + encrypted: z.boolean().optional(), + kmsKeyId: z + .string() + .regex( + /^arn:[^:]+:kms:[a-z0-9-]+:[0-9]{12}:key\/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/, + 'Must be a valid KMS key ARN' + ) + .optional(), + }) + .passthrough(); + +export type EbsVolumeConfiguration = z.infer; + +export const VolumeConfigurationSchema = z.object({ + ebsConfiguration: EbsVolumeConfigurationSchema, +}); + +export type VolumeConfiguration = z.infer; + +// ============================================================================ +// Instance Lifecycle Configuration +// ============================================================================ + +const LIFECYCLE_SECONDS_MIN = 60; +const LIFECYCLE_SECONDS_MAX = 1209600; + +export const InstanceLifecycleConfigurationSchema = z.object({ + idleInstanceTimeout: z.number().int().min(LIFECYCLE_SECONDS_MIN).max(LIFECYCLE_SECONDS_MAX).optional(), + maxLifetime: z.number().int().min(LIFECYCLE_SECONDS_MIN).max(LIFECYCLE_SECONDS_MAX).optional(), +}); + +export type InstanceLifecycleConfiguration = z.infer; + +// ============================================================================ +// Compute Configuration +// +// `rootVolume` is accepted via `.passthrough()` on ec2Configuration (long-tail, +// service-managed). +// ============================================================================ + +export const Ec2ConfigurationSchema = z + .object({ + launchTemplateSource: z.object({ + launchParameters: LaunchParametersSchema, + }), + vpcConfiguration: VpcConfigurationSchema, + volumes: z.array(VolumeConfigurationSchema).max(5).optional(), + lifecycleConfiguration: InstanceLifecycleConfigurationSchema.optional(), + }) + .passthrough(); + +export type Ec2Configuration = z.infer; + +export const ComputeConfigurationSchema = z.object({ + ec2Configuration: Ec2ConfigurationSchema, +}); + +export type ComputeConfiguration = z.infer; + +// ============================================================================ +// Capacity Provider Schema +// ============================================================================ + +export const CapacityProviderSchema = z.object({ + /** Capacity provider name (immutable after creation). */ + name: CapacityProviderNameSchema, + /** Optional description (max 4096 chars). The only mutable field besides tags. */ + description: z.string().min(1).max(4096).optional(), + /** + * ARN of the IAM role AgentCore assumes to manage the capacity provider (immutable). Optional: + * when omitted, an operator role with the required trust policy and managed permissions is + * created automatically at deploy time. + */ + operatorRoleArn: OperatorRoleArnSchema.optional(), + /** Compute resources for the capacity provider (immutable after creation). */ + computeConfiguration: ComputeConfigurationSchema, + /** Optional resource tags. */ + tags: TagsSchema.optional(), +}); + +export type CapacityProvider = z.infer; diff --git a/src/projectSchemas/v0/schemas/primitives/config-bundle.ts b/src/projectSchemas/v0/schemas/primitives/config-bundle.ts new file mode 100644 index 0000000000..ba5032482f --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/config-bundle.ts @@ -0,0 +1,52 @@ +import { KmsKeyArnSchema } from './evaluator'; +import { z } from 'zod'; + +// ============================================================================ +// Configuration Bundle Types +// ============================================================================ + +export const ConfigBundleNameSchema = z + .string() + .min(1, 'Name is required') + .max(100) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,99}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 100 chars)' + ); + +export const ConfigBundleDescriptionSchema = z.string().min(1).max(500).optional(); + +/** Freeform configuration for a single component within a bundle. */ +export const ComponentConfigurationSchema = z.object({ + configuration: z.record(z.string(), z.unknown()), +}); + +export type ComponentConfiguration = z.infer; + +/** + * Map of component identifier (ARN or placeholder) to its configuration. + * + * Keys are typically resource ARNs (runtime ARN, gateway ARN) but may use + * placeholder tokens like `{{runtime:}}` when the bundle is created + * before deploy and ARNs are not yet available. + */ +export const ComponentConfigurationMapSchema = z.record(z.string(), ComponentConfigurationSchema); + +export type ComponentConfigurationMap = z.infer; + +export const ConfigBundleSchema = z.object({ + name: ConfigBundleNameSchema, + /** Discriminator required by the CDK package's schema validation. */ + type: z.literal('ConfigurationBundle').default('ConfigurationBundle'), + description: ConfigBundleDescriptionSchema, + /** Component configurations keyed by component ARN or placeholder. */ + components: ComponentConfigurationMapSchema, + /** Optional branch name for versioning. */ + branchName: z.string().max(128).optional(), + /** Optional commit message for this version. */ + commitMessage: z.string().max(500).optional(), + /** Optional KMS key ARN for customer-managed encryption of the bundle. */ + kmsKeyArn: KmsKeyArnSchema.optional(), +}); + +export type ConfigBundle = z.infer; diff --git a/src/projectSchemas/v0/schemas/primitives/dataset.ts b/src/projectSchemas/v0/schemas/primitives/dataset.ts new file mode 100644 index 0000000000..272f050118 --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/dataset.ts @@ -0,0 +1,67 @@ +import { z } from 'zod'; + +// ============================================================================ +// Dataset Types +// ============================================================================ + +/** + * Dataset name validation. + * Pattern: ^[a-zA-Z][a-zA-Z0-9_]{0,47}$ + */ +export const DatasetNameSchema = z + .string() + .min(1, 'Dataset name is required') + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +/** + * Versioned schema type governing the structure of dataset examples. + * Immutable after creation (createOnly CFN property). + */ +export const DatasetSchemaTypeSchema = z.enum([ + 'AGENTCORE_EVALUATION_PREDEFINED_V1', + 'AGENTCORE_EVALUATION_SIMULATED_V1', +]); + +export type DatasetSchemaType = z.infer; + +/** + * Managed dataset config — CLI manages the local file and syncs to service. + */ +export const DatasetManagedConfigSchema = z.object({ + location: z.string().min(1), +}); + +/** + * Dataset configuration. + */ +export const DatasetConfigSchema = z.object({ + managed: DatasetManagedConfigSchema, +}); + +/** + * Dataset specification in agentcore.json. + */ +export const DatasetSchema = z.object({ + /** Dataset name */ + name: DatasetNameSchema, + /** + * Versioned schema type governing dataset structure. + * Immutable after creation. + */ + schemaType: DatasetSchemaTypeSchema, + /** Optional description (max 200 characters) */ + description: z.string().max(200).optional(), + /** Dataset content management config */ + config: DatasetConfigSchema, + /** Optional KMS key ARN for SSE-KMS encryption. Immutable after creation. */ + kmsKeyArn: z + .string() + .regex(/^arn:aws(-[a-z]+)*:kms:[a-zA-Z0-9-]*:[0-9]{12}:key\/[a-zA-Z0-9-]{36}$/, 'Must be a valid KMS key ARN') + .optional(), +}); + +export type Dataset = z.infer; diff --git a/src/projectSchemas/v0/schemas/primitives/evaluator.ts b/src/projectSchemas/v0/schemas/primitives/evaluator.ts new file mode 100644 index 0000000000..1df0c12957 --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/evaluator.ts @@ -0,0 +1,155 @@ +import { z } from 'zod'; + +// ============================================================================ +// Evaluator Types +// ============================================================================ + +export const EvaluationLevelSchema = z.enum(['SESSION', 'TRACE', 'TOOL_CALL']); +export type EvaluationLevel = z.infer; + +export const EvaluatorNameSchema = z + .string() + .min(1, 'Name is required') + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +// ============================================================================ +// Rating Scale +// ============================================================================ + +export const NumericalRatingSchema = z.object({ + value: z.number().int(), + label: z.string().min(1), + definition: z.string().min(1), +}); + +export type NumericalRating = z.infer; + +export const CategoricalRatingSchema = z.object({ + label: z.string().min(1), + definition: z.string().min(1), +}); + +export type CategoricalRating = z.infer; + +export const RatingScaleSchema = z + .object({ + numerical: z.array(NumericalRatingSchema).optional(), + categorical: z.array(CategoricalRatingSchema).optional(), + }) + .refine( + scale => { + const hasNumerical = Boolean(scale.numerical); + const hasCategorical = Boolean(scale.categorical); + return hasNumerical !== hasCategorical; + }, + { message: 'Rating scale must have either numerical or categorical, not both' } + ); + +export type RatingScale = z.infer; + +// ============================================================================ +// LLM-as-a-Judge Config +// ============================================================================ + +export const EvaluatorModelProviderSchema = z.enum(['Bedrock', 'OpenResponses']); +export type EvaluatorModelProvider = z.infer; + +// eslint-disable-next-line security/detect-unsafe-regex -- anchored pattern, no backtracking risk +const BEDROCK_MODEL_ID_PATTERN = /^[a-z][a-z0-9-]*\.[a-zA-Z0-9._-]+(:[0-9]+)?$/; +const BEDROCK_ARN_PATTERN = /^arn:aws[a-z-]*:bedrock:[a-z0-9-]+:\d{12}:(inference-profile|foundation-model)\/.+$/; + +export function isValidBedrockModelId(value: string): boolean { + return BEDROCK_MODEL_ID_PATTERN.test(value) || BEDROCK_ARN_PATTERN.test(value); +} + +export const EvaluatorModelIdSchema = z + .string() + .trim() + .min(1, 'Model ID is required') + .max(2048, 'Model ID must be 2048 characters or fewer') + .regex(/^[\x21-\x7e]+$/, 'Model ID must contain only printable ASCII characters without spaces'); + +// Retained for compatibility with existing imports. +export const BedrockModelIdSchema = EvaluatorModelIdSchema; + +export const LlmAsAJudgeConfigSchema = z.object({ + modelProvider: EvaluatorModelProviderSchema.optional(), + model: EvaluatorModelIdSchema, + instructions: z.string().min(1, 'Evaluation instructions are required'), + ratingScale: RatingScaleSchema, +}); + +export type LlmAsAJudgeConfig = z.infer; + +// ============================================================================ +// Code-Based Evaluator Config +// ============================================================================ + +export const ManagedCodeBasedConfigSchema = z.object({ + codeLocation: z.string().min(1), + entrypoint: z.string().min(1).default('lambda_function.handler'), + timeoutSeconds: z.number().int().min(1).max(300).default(60), + additionalPolicies: z.array(z.string().min(1)).optional(), +}); + +export type ManagedCodeBasedConfig = z.infer; + +const LAMBDA_ARN_PATTERN = /^arn:aws[a-z-]*:lambda:[a-z0-9-]+:\d{12}:function:.+$/; + +export const ExternalCodeBasedConfigSchema = z.object({ + lambdaArn: z.string().min(1).regex(LAMBDA_ARN_PATTERN, 'Must be a valid Lambda function ARN'), +}); + +export type ExternalCodeBasedConfig = z.infer; + +export const CodeBasedConfigSchema = z + .object({ + managed: ManagedCodeBasedConfigSchema.optional(), + external: ExternalCodeBasedConfigSchema.optional(), + }) + .refine(config => Boolean(config.managed) !== Boolean(config.external), { + message: 'Code-based config must have either managed or external, not both', + }); + +export type CodeBasedConfig = z.infer; + +// ============================================================================ +// Evaluator Config +// ============================================================================ + +export const EvaluatorConfigSchema = z + .object({ + llmAsAJudge: LlmAsAJudgeConfigSchema.optional(), + codeBased: CodeBasedConfigSchema.optional(), + }) + .refine(config => Boolean(config.llmAsAJudge) !== Boolean(config.codeBased), { + message: 'Config must have either llmAsAJudge or codeBased, not both', + }); + +export type EvaluatorConfig = z.infer; + +// ============================================================================ +// KMS Key ARN Validation +// ============================================================================ + +/** + * Pattern for KMS key ARNs accepted by the AgentCore Evaluation service. + * Matches key ARNs across all AWS partitions with a 36-char UUID key ID. + * Alias ARNs are not supported by the service for evaluator encryption. + */ +export const KMS_KEY_ARN_PATTERN = /^arn:[^:]+:kms:[a-zA-Z0-9-]*:[0-9]{12}:key\/[a-zA-Z0-9-]{36}$/; + +export const KmsKeyArnSchema = z + .string() + .regex( + KMS_KEY_ARN_PATTERN, + 'Must be a valid KMS key ARN (e.g. arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012)' + ); + +export function isValidKmsKeyArn(value: string): boolean { + return KMS_KEY_ARN_PATTERN.test(value); +} diff --git a/src/projectSchemas/v0/schemas/primitives/harness.ts b/src/projectSchemas/v0/schemas/primitives/harness.ts new file mode 100644 index 0000000000..203de4d1f2 --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/harness.ts @@ -0,0 +1,688 @@ +import { MAX_CONTAINER_BUILD_SECURITY_GROUPS, NetworkModeSchema, isContainerBuild } from '../../constants'; +import { + EfsAccessPointConfigSchema, + LifecycleConfigurationSchema, + NetworkConfigSchema, + S3FilesAccessPointConfigSchema, + SessionStorageSchema, +} from '../agent-env'; +import { AuthorizerConfigSchema, RuntimeAuthorizerTypeSchema } from '../auth'; +import { ConnectionSchema } from '../connections'; +import { uniqueBy } from '../zod-util'; +import { TagsSchema } from './tags'; +import { z } from 'zod'; + +/** + * ECR container image URI pattern, mirroring the CFN ContainerConfiguration.ContainerUri + * constraint (private 12-digit ECR registry or public.ecr.aws, optional tag/digest). + * A non-ECR URI is rejected client-side instead of failing at CloudFormation CREATE. + */ +export const CONTAINER_URI_PATTERN = + // eslint-disable-next-line security/detect-unsafe-regex -- mirrors the CFN ContainerUri pattern; input is length-bounded by .max(MAX_CONTAINER_URI_LENGTH) + /^(([0-9]{12})\.dkr\.ecr\.([a-z0-9-]+)\.amazonaws\.com(\.cn)?|public\.ecr\.aws)\/((?:[a-z0-9]+(?:[._-][a-z0-9]+)*\/)*[a-z0-9]+(?:[._-][a-z0-9]+)*)(?::([^:@]{1,300}))?(?:@(.+))?$/; +/** CFN ContainerConfiguration.ContainerUri maxLength. */ +export const MAX_CONTAINER_URI_LENGTH = 1024; +/** CFN EnvironmentVariables value maxLength and map maxProperties. */ +export const MAX_ENV_VAR_VALUE_LENGTH = 5000; +export const MAX_ENV_VARS = 50; +/** CFN/Smithy EnvironmentVariableKey length bounds (Smithy EnvironmentVariableKey: 1–100, no char pattern). */ +export const MAX_ENV_VAR_KEY_LENGTH = 100; + +// ============================================================================ +// Harness Name +// ============================================================================ + +export const HarnessNameSchema = z + .string() + .min(1, 'Harness name is required') + .max(40) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,39}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 40 chars)' + ); + +// ============================================================================ +// Model Configuration +// ============================================================================ + +export const HarnessModelProviderSchema = z.enum(['bedrock', 'open_ai', 'gemini', 'lite_llm']); +export type HarnessModelProvider = z.infer; + +/** Max length of the LiteLLM apiBase URL (Smithy: HarnessLiteLlmApiBase, 1–16383). */ +export const MAX_LITE_LLM_API_BASE_LENGTH = 16383; + +export const BedrockApiFormatSchema = z.enum(['converse_stream', 'responses', 'chat_completions']); +export type BedrockApiFormat = z.infer; + +export const OpenAiApiFormatSchema = z.enum(['responses', 'chat_completions']); +export type OpenAiApiFormat = z.infer; + +export const HarnessApiFormatSchema = z.enum(['converse_stream', 'responses', 'chat_completions']); +export type HarnessApiFormat = z.infer; + +export const HarnessModelSchema = z + .object({ + provider: HarnessModelProviderSchema, + modelId: z.string().min(1, 'Model ID is required'), + apiKeyArn: z.string().optional(), + apiFormat: HarnessApiFormatSchema.optional(), + temperature: z.number().min(0).max(2).optional(), + topP: z.number().min(0).max(1).optional(), + topK: z.number().int().min(0).max(500).optional(), + maxTokens: z.number().int().min(1).optional(), + /** LiteLLM only: base URL for the third-party model provider's API endpoint. */ + apiBase: z.string().min(1).max(MAX_LITE_LLM_API_BASE_LENGTH).optional(), + /** LiteLLM only: provider-specific parameters passed through to the model provider unchanged. */ + additionalParams: z.record(z.string(), z.unknown()).optional(), + }) + .superRefine((model, ctx) => { + if (model.topK !== undefined && model.provider !== 'gemini') { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'topK is only supported for the "gemini" provider', + path: ['topK'], + }); + } + if (model.apiFormat !== undefined) { + if (model.provider !== 'bedrock' && model.provider !== 'open_ai') { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: '--api-format is only supported for bedrock and open_ai providers', + path: ['apiFormat'], + }); + } else if (model.provider === 'open_ai' && model.apiFormat === 'converse_stream') { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Invalid API format for open_ai: ${model.apiFormat}. Use ${OpenAiApiFormatSchema.options.join(', ')}`, + path: ['apiFormat'], + }); + } + } + // CFN requires ApiKeyArn for the open_ai and gemini model configs (bedrock and lite_llm do not). + if (model.apiKeyArn === undefined && (model.provider === 'open_ai' || model.provider === 'gemini')) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `apiKeyArn is required for the "${model.provider}" provider`, + path: ['apiKeyArn'], + }); + } + if (model.apiBase !== undefined && model.provider !== 'lite_llm') { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'apiBase is only supported for the "lite_llm" provider', + path: ['apiBase'], + }); + } + if (model.additionalParams !== undefined && model.provider !== 'lite_llm') { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'additionalParams is only supported for the "lite_llm" provider', + path: ['additionalParams'], + }); + } + }); + +export type HarnessModel = z.infer; + +export function validateApiFormat( + apiFormat: string, + provider: string +): { valid: true } | { valid: false; error: string } { + const allFormats = HarnessApiFormatSchema.options as readonly string[]; + if (!allFormats.includes(apiFormat)) { + return { valid: false, error: `Invalid API format: ${apiFormat}. Use ${allFormats.join(', ')}` }; + } + if (provider !== 'bedrock' && provider !== 'open_ai') { + return { valid: false, error: '--api-format is only supported for bedrock and open_ai providers' }; + } + const result = HarnessModelSchema.safeParse({ provider, modelId: 'placeholder', apiFormat }); + if (result.success) return { valid: true }; + const apiFormatIssue = result.error.issues.find(i => i.path.includes('apiFormat')); + if (apiFormatIssue) { + return { + valid: false, + error: `Invalid API format for ${provider}: ${apiFormat}. Use ${(provider === 'open_ai' ? OpenAiApiFormatSchema : BedrockApiFormatSchema).options.join(', ')}`, + }; + } + return { valid: true }; +} + +// ============================================================================ +// Tool Configuration +// ============================================================================ + +export const HarnessToolTypeSchema = z.enum([ + 'remote_mcp', + 'agentcore_browser', + 'agentcore_gateway', + 'inline_function', + 'agentcore_code_interpreter', +]); +export type HarnessToolType = z.infer; + +export const HarnessToolNameSchema = z + .string() + .min(1) + .max(64) + .regex( + /^[a-zA-Z0-9_-]+$/, + 'Tool name must contain only alphanumeric characters, hyphens, and underscores (1-64 chars)' + ); + +export const RemoteMcpConfigSchema = z.object({ + remoteMcp: z.object({ + url: z.string().min(1), + headers: z.record(z.string(), z.string()).optional(), + }), +}); + +export const AgentCoreBrowserConfigSchema = z.object({ + agentCoreBrowser: z.object({ + browserArn: z.string().optional(), + }), +}); + +export const AgentCoreCodeInterpreterConfigSchema = z.object({ + agentCoreCodeInterpreter: z.object({ + codeInterpreterArn: z.string().optional(), + }), +}); + +export const GatewayOAuthGrantTypeSchema = z.enum(['CLIENT_CREDENTIALS', 'USER_FEDERATION']); + +export const HarnessGatewayOutboundAuthSchema = z.union([ + z.object({ awsIam: z.object({}) }), + z.object({ none: z.object({}) }), + z.object({ + oauth: z.object({ + providerArn: z.string().min(1), + scopes: z.array(z.string().min(1)), + grantType: GatewayOAuthGrantTypeSchema.optional(), + customParameters: z.record(z.string(), z.string()).optional(), + }), + }), +]); + +export type HarnessGatewayOutboundAuth = z.infer; + +export const AgentCoreGatewayConfigSchema = z.object({ + agentCoreGateway: z + .object({ + gatewayArn: z.string().min(1), + outboundAuth: HarnessGatewayOutboundAuthSchema.optional(), + }) + .passthrough() + .superRefine((data, ctx) => { + if ('credentialProviderName' in data) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + 'credentialProviderName is no longer supported. Use outboundAuth instead. Example: outboundAuth: { awsIam: {} } or outboundAuth: { oauth: { providerArn: "...", scopes: [...] } }', + path: ['credentialProviderName'], + }); + } + }), +}); + +export const InlineFunctionConfigSchema = z.object({ + inlineFunction: z.object({ + description: z.string().min(1), + inputSchema: z.record(z.string(), z.unknown()), + }), +}); + +export const HarnessToolConfigSchema = z.union([ + RemoteMcpConfigSchema, + AgentCoreBrowserConfigSchema, + AgentCoreCodeInterpreterConfigSchema, + AgentCoreGatewayConfigSchema, + InlineFunctionConfigSchema, +]); + +const TOOL_TYPE_TO_CONFIG_KEY: Record = { + remote_mcp: 'remoteMcp', + agentcore_browser: 'agentCoreBrowser', + agentcore_gateway: 'agentCoreGateway', + inline_function: 'inlineFunction', + agentcore_code_interpreter: 'agentCoreCodeInterpreter', +}; + +const TOOL_TYPES_REQUIRING_CONFIG = new Set(['remote_mcp', 'agentcore_gateway', 'inline_function']); + +export const HarnessToolSchema = z + .object({ + type: HarnessToolTypeSchema, + name: HarnessToolNameSchema, + config: HarnessToolConfigSchema.optional(), + }) + .superRefine((tool, ctx) => { + const expectedKey = TOOL_TYPE_TO_CONFIG_KEY[tool.type]; + + if (!tool.config) { + if (TOOL_TYPES_REQUIRING_CONFIG.has(tool.type)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Tool type "${tool.type}" requires a "${expectedKey}" config`, + path: ['config'], + }); + } + return; + } + + const configKeys = Object.keys(tool.config); + if (configKeys.length !== 1 || configKeys[0] !== expectedKey) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Tool type "${tool.type}" requires "${expectedKey}" config, got "${configKeys[0]}"`, + path: ['config'], + }); + } + }); + +export type HarnessTool = z.infer; + +// ============================================================================ +// Memory Reference +// ============================================================================ + +/** + * Per-namespace retrieval tuning, applied as a flat default across every namespace + * of the referenced memory's strategies. Namespaces are only known at CDK synth + * (from the resolved Memory's strategies), so a per-namespace map cannot be authored + * here; the CDK fans this single config out to each namespace. StrategyId is omitted + * deliberately — the namespace already identifies the strategy and the id is + * service-assigned. Maps to CFN HarnessAgentCoreMemoryRetrievalConfig {TopK, RelevanceScore}. + */ +export const HarnessMemoryRetrievalConfigSchema = z + .object({ + topK: z.number().int().min(1).optional(), + relevanceScore: z.number().min(0).max(1).optional(), + }) + .strict() + // An empty `{}` parses against the optional fields, but fans out to per-namespace `{}` objects — + // the exact shape that crashed the pre-v6 service handler. Require at least one knob. + .refine(v => v.topK !== undefined || v.relevanceScore !== undefined, { + message: 'retrievalConfig must specify at least one of topK or relevanceScore', + }); + +export type HarnessMemoryRetrievalConfig = z.infer; + +/** + * Managed-memory strategy set. NOT MemoryStrategyTypeSchema: managed harness memory excludes + * CUSTOM (the CFN ManagedMemoryConfiguration.Strategies enum is exactly these four). + */ +export const ManagedMemoryStrategySchema = z.enum(['SEMANTIC', 'SUMMARIZATION', 'USER_PREFERENCE', 'EPISODIC']); + +/** + * Managed: the harness creates and owns its memory internally. The memory `arn` is read-only + * (service-populated) and never authored here. `strategies` is OPTIONAL and left absent by default: + * when omitted, the harness/service applies its own default strategy set. It is only written when the + * user explicitly tunes it, so the CLI never pins a default the service might evolve. + */ +const ManagedMemoryRefSchema = z + .object({ + mode: z.literal('managed'), + strategies: z.array(ManagedMemoryStrategySchema).min(1).max(4).optional(), + eventExpiryDuration: z.number().int().min(3).max(365).optional(), + encryptionKeyArn: z.string().min(1).optional(), + }) + .strict(); + +/** + * Existing (bring-your-own): reference a memory by name (project sibling) or arn, carrying the + * optional deploy-time tuning. This is the pre-union flat shape, now tagged `existing`. + */ +const ExistingMemoryRefSchema = z + .object({ + mode: z.literal('existing'), + name: z.string().min(1).optional(), + arn: z.string().min(1).optional(), + actorId: z.string().optional(), + /** Limits how many recent memory messages are loaded into context (CFN MessagesCount). */ + messagesCount: z.number().int().min(1).optional(), + /** Retrieval tuning applied to every namespace of the referenced memory (CFN RetrievalConfig). */ + retrievalConfig: HarnessMemoryRetrievalConfigSchema.optional(), + }) + // .strict() so a typo (e.g. `messageCount` for `messagesCount`) is a parse error rather than a + // silently-dropped field that defeats the B6 MessagesCount fix. + .strict() + .refine(m => m.arn != null || m.name != null, { + message: 'existing memory requires `arn` or `name`', + path: ['name'], + }) + .superRefine((ref, ctx) => { + // retrievalConfig is applied per-namespace, and namespaces are only resolvable from a by-name + // memory's strategies. At synth `arn` takes precedence over `name` (resolveHarnessMemory), so + // ANY ref carrying `arn` resolves no strategies and buildRetrievalConfig drops the tuning — + // including the `{ arn, name, retrievalConfig }` combo. Gate on `arn` alone, not `arn && !name`, + // so that combo can't slip through. (messagesCount and actorId are emitted directly from the + // ref, so they stay valid for a by-arn reference.) + if (ref.arn && ref.retrievalConfig !== undefined) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: + 'retrievalConfig is not supported when memory is referenced by `arn` (per-namespace tuning is only resolvable for a by-name reference). Reference the memory by `name` only, or drop retrievalConfig.', + path: ['retrievalConfig'], + }); + } + }); + +/** Disabled: explicit opt-out of memory. */ +const DisabledMemoryRefSchema = z.object({ mode: z.literal('disabled') }).strict(); + +/** + * Memory reference for a harness — exactly one of managed | existing | disabled. + * A legacy-aware preprocess maps the pre-union flat shape ({ name | arn | ... }) to the `existing` + * arm. Absent memory STAYS absent — managed is the default only for NEW harnesses (seeded at create + * time by the CLI/TUI), never invented here, so already-deployed harnesses are not auto-upgraded. + */ +export const HarnessMemoryRefSchema = z.preprocess( + val => { + if (val == null || typeof val !== 'object') return val; + const obj = val as Record; + if ('mode' in obj) return obj; // already union-tagged + // Legacy flat shape → existing (it always referenced a sibling/external memory by name or arn). + return { mode: 'existing', ...obj }; + }, + z.discriminatedUnion('mode', [ManagedMemoryRefSchema, ExistingMemoryRefSchema, DisabledMemoryRefSchema]) +); + +export type HarnessMemoryRef = z.infer; +export type ManagedMemoryStrategy = z.infer; + +// ============================================================================ +// Truncation Configuration +// ============================================================================ + +export const HarnessTruncationStrategySchema = z.enum(['sliding_window', 'summarization', 'none']); + +// .strict() on the outer object so a payload carrying BOTH arms +// (`{ slidingWindow: {...}, summarization: {...} }`) fails the union — without it the union +// matches the first arm and silently drops the second arm's config. +export const SlidingWindowConfigSchema = z + .object({ + slidingWindow: z.object({ + messagesCount: z.number().int().min(1).optional(), + }), + }) + .strict(); + +export const SummarizationConfigSchema = z + .object({ + summarization: z.object({ + summaryRatio: z.number().min(0).max(1).optional(), + preserveRecentMessages: z.number().int().min(0).optional(), + summarizationSystemPrompt: z.string().optional(), + }), + }) + .strict(); + +export const HarnessTruncationConfigSchema = z + .object({ + strategy: HarnessTruncationStrategySchema, + config: z.union([SlidingWindowConfigSchema, SummarizationConfigSchema]).optional(), + }) + .superRefine((data, ctx) => { + // Bind the config arm to the chosen strategy: sliding_window must carry a slidingWindow + // config (or none), summarization a summarization config (or none), and none takes no config. + if (!data.config) return; + const configKey = 'slidingWindow' in data.config ? 'slidingWindow' : 'summarization'; + const expected: Record = { + sliding_window: 'slidingWindow', + summarization: 'summarization', + none: undefined, + }; + if (expected[data.strategy] === undefined) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Truncation strategy "${data.strategy}" does not take a config`, + path: ['config'], + }); + } else if (expected[data.strategy] !== configKey) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Truncation strategy "${data.strategy}" requires a "${expected[data.strategy]}" config, got "${configKey}"`, + path: ['config'], + }); + } + }); + +export type HarnessTruncationConfig = z.infer; + +// ============================================================================ +// Skill Configuration +// ============================================================================ + +export const HarnessSkillGitAuthSchema = z.object({ + credentialName: z.string().min(1), + username: z.string().optional(), +}); + +export type HarnessSkillGitAuth = z.infer; + +export const HarnessSkillS3SourceSchema = z + .object({ + s3Uri: z + .string() + .min(5) + .regex(/^s3:\/\//, 'Must be an S3 URI starting with s3://'), + }) + .strict(); + +export type HarnessSkillS3Source = z.infer; + +export const HarnessSkillGitSourceSchema = z + .object({ + gitUrl: z + .string() + .min(8) + .regex(/^https:\/\//, 'Must be an HTTPS git URL'), + path: z.string().min(1).optional(), + auth: HarnessSkillGitAuthSchema.optional(), + }) + .strict(); + +export type HarnessSkillGitSource = z.infer; + +export const HarnessSkillPathSourceSchema = z + .object({ + path: z.string().min(1), + }) + .strict(); + +export type HarnessSkillPathSource = z.infer; + +export const HarnessSkillAwsSkillsSourceSchema = z + .object({ + awsSkills: z + .object({ + paths: z.array(z.string().min(1).max(4096)).optional(), + }) + .strict(), + }) + .strict(); + +export type HarnessSkillAwsSkillsSource = z.infer; + +export const HarnessSkillSchema = z.union([ + z + .string() + .min(1) + .transform(path => ({ path })), + HarnessSkillS3SourceSchema, + HarnessSkillGitSourceSchema, + HarnessSkillPathSourceSchema, + HarnessSkillAwsSkillsSourceSchema, +]); + +export type HarnessSkillInput = z.input; +export type HarnessSkill = z.output; + +// ============================================================================ +// Allowed Tools +// ============================================================================ + +export const AllowedToolSchema = z + .string() + .min(1) + .max(64) + // eslint-disable-next-line security/detect-unsafe-regex -- safe: input is bounded to 64 chars by .max(64) + .regex(/^(\*|@?[^/]+(\/[^/]+)?)$/, 'Must be "*" or a tool name pattern (max 64 chars)'); + +/** + * Detects the legacy file-path-shaped `systemPrompt` (the pre-migration `./prompt.md` style that + * the old L3 read from disk). A real system prompt is instructional prose containing whitespace; + * the legacy shape was always a single bare token that is a relative path or ends in .md/.txt. + * Used to fail fast on upgrade rather than silently shipping the path string as the prompt text. + */ +export function looksLikeLegacyPromptPath(value: string): boolean { + const v = value.trim(); + if (!/^\S+$/.test(v)) return false; // prose contains whitespace — never a path + return /^\.\.?\//.test(v) || /\.(md|txt)$/i.test(v); +} + +// ============================================================================ +// HarnessSpec — per-harness config file schema (harness.json) +// ============================================================================ + +export const HarnessSpecSchema = z + .object({ + name: HarnessNameSchema, + model: HarnessModelSchema, + // Always literal text. CFN HarnessSystemContentBlock.Text is minLength:1, so a blank or + // whitespace-only prompt would deploy to CREATE_FAILED — reject it client-side instead. + // (File-backed prompts are supplied via system-prompt.md auto-discovery, not this field.) + systemPrompt: z + .string() + .refine(val => val.trim().length > 0, { message: 'systemPrompt must not be empty or whitespace-only' }) + // Migration fail-fast: the previous L3 treated a `./prompt.md`-style value as a file path and + // loaded its contents; this field is now ALWAYS literal text, so such a value would silently + // ship as the prompt itself. Reject the legacy file-path shape so the divergence fails loudly + // at parse/validate time (before synth) instead of in production. + .refine(val => !looksLikeLegacyPromptPath(val), { + message: + 'systemPrompt looks like a file path. It is now always literal text — put file-backed prompts in a `system-prompt.md` in the harness directory (auto-discovered), or inline the prompt text here.', + }) + .optional(), + tools: z + .array(HarnessToolSchema) + .default([]) + .superRefine( + uniqueBy( + tool => tool.name, + name => `Duplicate tool name: ${name}` + ) + ), + skills: z.array(HarnessSkillSchema).default([]), + allowedTools: z.array(AllowedToolSchema).optional(), + memory: HarnessMemoryRefSchema.optional(), + maxIterations: z.number().int().min(1).optional(), + maxTokens: z.number().int().min(1).optional(), + timeoutSeconds: z.number().int().min(1).optional(), + truncation: HarnessTruncationConfigSchema.optional(), + containerUri: z + .string() + .min(1) + .max(MAX_CONTAINER_URI_LENGTH) + .regex(CONTAINER_URI_PATTERN, 'containerUri must be an ECR image URI (12-digit private ECR or public.ecr.aws)') + .optional(), + dockerfile: z.string().min(1).optional(), + executionRoleArn: z.string().optional(), + networkMode: NetworkModeSchema.optional(), + networkConfig: NetworkConfigSchema.optional(), + lifecycleConfig: LifecycleConfigurationSchema.optional(), + sessionStoragePath: SessionStorageSchema.shape.mountPath.optional(), + efsAccessPoints: z.array(EfsAccessPointConfigSchema).max(2).optional(), + s3AccessPoints: z.array(S3FilesAccessPointConfigSchema).max(2).optional(), + environmentVariables: z + // Key bound (Smithy EnvironmentVariableKey: length 1–100, no character pattern) — an empty or + // >100-char key passes a bare z.string() here but fails at CFN CREATE. + .record(z.string().min(1).max(MAX_ENV_VAR_KEY_LENGTH), z.string().max(MAX_ENV_VAR_VALUE_LENGTH)) + .refine(rec => Object.keys(rec).length <= MAX_ENV_VARS, { + message: `A maximum of ${MAX_ENV_VARS} environment variables is allowed`, + }) + .optional(), + /** Authorizer type for inbound requests. Defaults to AWS_IAM. */ + authorizerType: RuntimeAuthorizerTypeSchema.optional(), + /** Authorizer configuration. Required when authorizerType is CUSTOM_JWT. */ + authorizerConfiguration: AuthorizerConfigSchema.optional(), + /** Connections to external AgentCore resources (memory/gateway/runtime). The construct + * generates IAM + discovery env vars onto this harness's execution role. */ + connections: z.array(ConnectionSchema).optional(), + tags: TagsSchema.optional(), + }) + .superRefine((data, ctx) => { + if (data.containerUri !== undefined && data.dockerfile !== undefined) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'containerUri and dockerfile are mutually exclusive', + path: ['containerUri'], + }); + } + if (data.networkMode === 'VPC' && !data.networkConfig) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'networkConfig is required when networkMode is VPC', + path: ['networkConfig'], + }); + } + if (data.networkMode !== 'VPC' && data.networkConfig) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'networkConfig is only allowed when networkMode is VPC', + path: ['networkConfig'], + }); + } + // vpcId is NOT required here at the schema level (see the matching note in agent-env.ts): a + // container harness build in VPC mode needs one, but requiring it on read would hard-fail + // pre-existing configs. The CLI validators enforce it for fresh creates, deploy backfills + + // persists a missing vpcId, and the CDK construct fails fast at synth. The SG cap stays here — it + // is a hard CodeBuild limit that backfill can't satisfy. Gating on the shared isContainerBuild + // predicate keeps this in sync (a dockerfile-only gate previously missed containerUri harnesses). + if ( + data.networkMode === 'VPC' && + isContainerBuild(data) && + data.networkConfig && + data.networkConfig.securityGroups.length > MAX_CONTAINER_BUILD_SECURITY_GROUPS + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Container builds in VPC mode allow at most ${MAX_CONTAINER_BUILD_SECURITY_GROUPS} security groups (CodeBuild limit)`, + path: ['networkConfig', 'securityGroups'], + }); + } + if ((data.efsAccessPoints?.length || data.s3AccessPoints?.length) && data.networkMode !== 'VPC') { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'efsAccessPoints and s3AccessPoints require networkMode: VPC', + path: ['efsAccessPoints'], + }); + } + const mountPaths: string[] = []; + if (data.sessionStoragePath) mountPaths.push(data.sessionStoragePath.replace(/\/$/, '')); + for (const ap of data.efsAccessPoints ?? []) mountPaths.push(ap.mountPath.replace(/\/$/, '')); + for (const ap of data.s3AccessPoints ?? []) mountPaths.push(ap.mountPath.replace(/\/$/, '')); + if (new Set(mountPaths).size !== mountPaths.length) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Filesystem mount paths must be unique', + path: ['efsAccessPoints'], + }); + } + if (data.authorizerType === 'CUSTOM_JWT' && !data.authorizerConfiguration?.customJwtAuthorizer) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'authorizerConfiguration with customJwtAuthorizer is required when authorizerType is CUSTOM_JWT', + path: ['authorizerConfiguration'], + }); + } + if (data.authorizerType !== 'CUSTOM_JWT' && data.authorizerConfiguration) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'authorizerConfiguration is only allowed when authorizerType is CUSTOM_JWT', + path: ['authorizerConfiguration'], + }); + } + }); + +export type HarnessSpec = z.infer; diff --git a/src/projectSchemas/v0/schemas/primitives/index.ts b/src/projectSchemas/v0/schemas/primitives/index.ts new file mode 100644 index 0000000000..7b18db2bbc --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/index.ts @@ -0,0 +1,168 @@ +export type { + ABTest, + ABTestVariant, + ABTestEvaluationConfig, + ConfigurationBundleRef, + TrafficAllocationConfig, + VariantConfiguration, +} from './ab-test'; + +export type { Dataset, DatasetSchemaType } from './dataset'; +export { DatasetNameSchema, DatasetSchema, DatasetSchemaTypeSchema } from './dataset'; + +export type { + CapacityProvider, + CapacityProviderConfiguration, + ComputeConfiguration, + Ec2Configuration, + EbsVolumeConfiguration, + InstanceLifecycleConfiguration, + InstanceRequirements, + LaunchParameters, + OperatingSystem, + VolumeConfiguration, + VpcConfiguration, +} from './capacity-provider'; +export { + CAPACITY_PROVIDER_ARN_PATTERN, + CAPACITY_PROVIDER_OPERATOR_ROLE_ARN_PATTERN, + CapacityProviderArnSchema, + CapacityProviderConfigurationSchema, + CapacityProviderNameSchema, + CapacityProviderSchema, + CapacityProviderVolumeNameSchema, + ComputeConfigurationSchema, + Ec2ConfigurationSchema, + EbsVolumeConfigurationSchema, + InstanceLifecycleConfigurationSchema, + InstanceRequirementsSchema, + isCapacityProviderArn, + isValidOperatorRoleArn, + LaunchParametersSchema, + OperatingSystemSchema, + OperatorRoleArnSchema, + VolumeConfigurationSchema, + VpcConfigurationSchema, +} from './capacity-provider'; +export { + ABTestNameSchema, + ABTestDescriptionSchema, + ABTestSchema, + ABTestVariantSchema, + ABTestEvaluationConfigSchema, + ConfigurationBundleRefSchema, + TrafficAllocationConfigSchema, + VariantConfigurationSchema, + VariantNameSchema, + VariantWeightSchema, +} from './ab-test'; + +export type { MemoryStrategy, MemoryStrategyType } from './memory'; +export { + DEFAULT_EPISODIC_REFLECTION_NAMESPACE_TEMPLATES, + DEFAULT_EPISODIC_REFLECTION_NAMESPACES, + DEFAULT_STRATEGY_NAMESPACE_TEMPLATES, + DEFAULT_STRATEGY_NAMESPACES, + MemoryStrategyNameSchema, + MemoryStrategySchema, + MemoryStrategyTypeSchema, +} from './memory'; + +export type { + CategoricalRating, + CodeBasedConfig, + EvaluationLevel, + EvaluatorConfig, + EvaluatorModelProvider, + ExternalCodeBasedConfig, + LlmAsAJudgeConfig, + ManagedCodeBasedConfig, + NumericalRating, + RatingScale, +} from './evaluator'; +export { + BedrockModelIdSchema, + CategoricalRatingSchema, + CodeBasedConfigSchema, + EvaluationLevelSchema, + EvaluatorConfigSchema, + EvaluatorModelIdSchema, + EvaluatorModelProviderSchema, + EvaluatorNameSchema, + ExternalCodeBasedConfigSchema, + isValidBedrockModelId, + LlmAsAJudgeConfigSchema, + ManagedCodeBasedConfigSchema, + NumericalRatingSchema, + RatingScaleSchema, +} from './evaluator'; + +export type { OnlineEvalConfig, ClusteringConfig } from './online-eval-config'; +export { OnlineEvalConfigSchema, OnlineEvalConfigNameSchema, ClusteringConfigSchema } from './online-eval-config'; + +export type { AuthorizationPhase, EnforcementMode, Policy, PolicyEngine, ValidationMode } from './policy'; +export { + AuthorizationPhaseSchema, + EnforcementModeSchema, + PolicyEngineNameSchema, + PolicyEngineSchema, + PolicyNameSchema, + PolicySchema, + ValidationModeSchema, +} from './policy'; + +export type { + BedrockApiFormat, + HarnessApiFormat, + HarnessGatewayOutboundAuth, + HarnessMemoryRef, + HarnessModel, + HarnessModelProvider, + HarnessSpec, + HarnessTool, + HarnessToolType, + HarnessTruncationConfig, + ManagedMemoryStrategy, + OpenAiApiFormat, +} from './harness'; +export { + AllowedToolSchema, + BedrockApiFormatSchema, + HarnessApiFormatSchema, + OpenAiApiFormatSchema, + GatewayOAuthGrantTypeSchema, + HarnessGatewayOutboundAuthSchema, + HarnessMemoryRefSchema, + HarnessModelProviderSchema, + HarnessModelSchema, + HarnessNameSchema, + HarnessSpecSchema, + HarnessToolConfigSchema, + HarnessToolNameSchema, + HarnessToolSchema, + HarnessToolTypeSchema, + HarnessTruncationConfigSchema, + HarnessTruncationStrategySchema, + ManagedMemoryStrategySchema, +} from './harness'; + +export type { + PaymentManager, + PaymentConnector, + PaymentProvider, + PaymentProvisionMode, + PaymentAuthorizerType, +} from './payment'; +export { + DEFAULT_AUTO_PAYMENT, + DEFAULT_SPEND_LIMIT, + PaymentManagerSchema, + PaymentManagerNameSchema, + PaymentConnectorSchema, + PaymentConnectorNameSchema, + ManualPaymentConnectorSchema, + QuickCreatePaymentConnectorSchema, + PaymentProvisionModeSchema, + PaymentProviderSchema, + PaymentAuthorizerTypeSchema, +} from './payment'; diff --git a/src/projectSchemas/v0/schemas/primitives/knowledge-base.ts b/src/projectSchemas/v0/schemas/primitives/knowledge-base.ts new file mode 100644 index 0000000000..5940d620a5 --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/knowledge-base.ts @@ -0,0 +1,122 @@ +import { uniqueBy } from '../zod-util'; +import { z } from 'zod'; + +/** + * Knowledge Base name validation. + * 1-48 chars, starts with a letter, alphanumeric + dash + underscore. + * Mirrors the naming convention used by Memory/Evaluator/Dataset primitives; + * stricter than the Bedrock CreateKnowledgeBase API allows (which permits up + * to 100 chars), but consistent with the rest of the agentcore-cli schemas. + */ +export const KnowledgeBaseNameSchema = z + .string() + .min(1, 'Name is required') + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_-]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters, dashes, and underscores (max 48 chars)' + ); + +/** + * S3 data source for FMKB. Wave 1 supports S3 only. + * + * `uri` must be an `s3://bucket[/prefix]` URI. Non-S3 connectors (Confluence, + * SharePoint, OneDrive, Google Drive, Web Crawler) are deferred to a later wave. + * + * Bucket validation enforces the AWS S3 bucket naming rules at parse time: + * 3-63 chars, lowercase + digits + dot + hyphen, must start and end with + * letter/digit, no consecutive dots, and none of the AWS-reserved prefixes + * (`xn--`, `sthree-`) or suffixes (`-s3alias`). AWS will ultimately reject + * non-conformant buckets server-side; failing fast at config-load time + * gives a better error surface. + */ +const S3_BUCKET_NAME = /^(?!xn--)(?!sthree-)[a-z0-9](?!.*\.\.)[a-z0-9.-]{1,61}[a-z0-9](? { + const m = /^s3:\/\/([^/]+)(?:\/.*)?$/.exec(s); + return !!m && S3_BUCKET_NAME.test(m[1]!); + }, + { message: 'Must be a valid s3:// URI with an AWS-compliant bucket name' } + ), + }) + .strict(); + +export type S3DataSource = z.infer; + +/** + * Wire-verbatim connector type values for non-S3 FMKB data sources. These are + * the exact `connectorParameters.type` literals the Bedrock managed-connector + * API uses (confirmed against the FMKB console module's read and write paths). + * Note `WEB` (not `WEBCRAWLER`) and the single-word `GOOGLEDRIVE`. + */ +export const ConnectorDataSourceTypeSchema = z.enum(['WEB', 'CONFLUENCE', 'SHAREPOINT', 'ONEDRIVE', 'GOOGLEDRIVE']); +export type ConnectorDataSourceType = z.infer; + +/** + * Non-S3 data source. The connector-specific structure lives in a JSON file + * (`connectorConfigFile`, a project-relative path) and is passed through to + * the DataSource's connectorParameters verbatim at deploy time. This honors + * the DevEx "JSON file passthrough" decision: new connector params don't + * require CLI/schema changes. + */ +export const ConnectorFileDataSourceSchema = z + .object({ + type: ConnectorDataSourceTypeSchema, + connectorConfigFile: z.string().min(1, 'connectorConfigFile path is required'), + }) + .strict(); + +export type ConnectorFileDataSource = z.infer; + +/** + * Knowledge Base data source: S3 (inline `uri`) or a non-S3 connector + * (file-path reference). Discriminated union on `type`. + */ +export const DataSourceSchema = z.discriminatedUnion('type', [S3DataSourceSchema, ConnectorFileDataSourceSchema]); +export type DataSource = z.infer; + +/** + * Type literal for KnowledgeBase entries in `agentcore.json`. + * Mirrors how Memory/Evaluator/etc. tag themselves for forward-compat. + */ +export const KnowledgeBaseTypeSchema = z.literal('AgentCoreKnowledgeBase'); +export type KnowledgeBaseType = z.infer; + +/** + * Knowledge Base entry. The CLI creates and owns the KB, its data sources, + * its IAM role, and (when `gateway` is set in Wave 2) its connector gateway + * target. + * + * To wire an EXTERNAL KB (one this project does not own) as a gateway target, + * skip this schema and use a connector gateway target with the external KB's + * literal 10-char ID set on `knowledgeBaseId`. See `agentcore add gateway- + * target --type connector --connector bedrock-knowledge-bases`. + * + * `gateway` is optional in Wave 1 — when set, it's stored but not yet wired + * to a gateway target. Wave 2 lights up the connector gateway target. + */ +export const KnowledgeBaseSchema = z + .object({ + type: KnowledgeBaseTypeSchema.default('AgentCoreKnowledgeBase'), + name: KnowledgeBaseNameSchema, + description: z.string().max(2048).optional(), + dataSources: z + .array(DataSourceSchema) + .min(1, 'At least one data source is required') + .superRefine( + uniqueBy( + ds => (ds.type === 'S3' ? ds.uri : ds.connectorConfigFile), + key => `Duplicate data source: ${key}` + ) + ), + gateway: z.string().min(1).optional(), + }) + .strict(); + +export type KnowledgeBase = z.infer; diff --git a/src/projectSchemas/v0/schemas/primitives/memory.ts b/src/projectSchemas/v0/schemas/primitives/memory.ts new file mode 100644 index 0000000000..5e5a633cba --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/memory.ts @@ -0,0 +1,137 @@ +import { z } from 'zod'; + +// ============================================================================ +// Memory Strategy Types +// ============================================================================ + +/** + * Memory strategy types. + * Maps to AWS MemoryStrategy types: + * - SEMANTIC → SemanticMemoryStrategy + * - SUMMARIZATION → SummaryMemoryStrategy (note: CloudFormation uses "Summary") + * - USER_PREFERENCE → UserPreferenceMemoryStrategy + * - EPISODIC → EpisodicMemoryStrategy + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-bedrockagentcore-memory-memorystrategy.html + */ +export const MemoryStrategyTypeSchema = z.enum(['SEMANTIC', 'SUMMARIZATION', 'USER_PREFERENCE', 'EPISODIC']); +export type MemoryStrategyType = z.infer; + +/** + * Default namespace templates for each memory strategy type. + * These match the patterns generated in CLI session.py templates. + */ +export const DEFAULT_STRATEGY_NAMESPACE_TEMPLATES: Partial> = { + SEMANTIC: ['/users/{actorId}/facts'], + USER_PREFERENCE: ['/users/{actorId}/preferences'], + SUMMARIZATION: ['/summaries/{actorId}/{sessionId}'], + EPISODIC: ['/episodes/{actorId}/{sessionId}'], +}; + +/** + * @deprecated Use {@link DEFAULT_STRATEGY_NAMESPACE_TEMPLATES} instead. + * Retained as an alias for backward compatibility. + */ +export const DEFAULT_STRATEGY_NAMESPACES = DEFAULT_STRATEGY_NAMESPACE_TEMPLATES; + +/** + * Default reflection namespace templates for the EPISODIC strategy. + * The service requires reflection templates to be the same as or a prefix of episode templates. + */ +export const DEFAULT_EPISODIC_REFLECTION_NAMESPACE_TEMPLATES: string[] = ['/episodes/{actorId}']; + +/** + * @deprecated Use {@link DEFAULT_EPISODIC_REFLECTION_NAMESPACE_TEMPLATES} instead. + * Retained as an alias for backward compatibility. + */ +export const DEFAULT_EPISODIC_REFLECTION_NAMESPACES = DEFAULT_EPISODIC_REFLECTION_NAMESPACE_TEMPLATES; + +/** + * Memory strategy name validation. + * Pattern: ^[a-zA-Z][a-zA-Z0-9_]{0,47}$ + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-bedrockagentcore-memory.html#cfn-bedrockagentcore-memory-name + */ +export const MemoryStrategyNameSchema = z + .string() + .min(1) + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +/** + * Memory strategy configuration. + * Each memory can have multiple strategies with optional namespace scoping. + * + * Field naming: + * - `namespaceTemplates` / `reflectionNamespaceTemplates` are the preferred field names. + * - `namespaces` / `reflectionNamespaces` are deprecated aliases retained for backward + * compatibility. Specifying both the deprecated and preferred form for the same concept + * is rejected by validation. + */ +export const MemoryStrategySchema = z + .object({ + /** Strategy type */ + type: MemoryStrategyTypeSchema, + /** Optional custom name for the strategy */ + name: MemoryStrategyNameSchema.optional(), + /** Optional description */ + description: z.string().optional(), + /** Optional namespace templates for scoping memory access */ + namespaceTemplates: z.array(z.string()).optional(), + /** @deprecated Use `namespaceTemplates` instead. */ + namespaces: z.array(z.string()).optional(), + /** Reflection namespace templates for EPISODIC strategy. Required by the service for episodic strategies. */ + reflectionNamespaceTemplates: z.array(z.string()).optional(), + /** @deprecated Use `reflectionNamespaceTemplates` instead. */ + reflectionNamespaces: z.array(z.string()).optional(), + }) + .refine(strategy => !((strategy.namespaces?.length ?? 0) > 0 && (strategy.namespaceTemplates?.length ?? 0) > 0), { + message: + "'namespaces' and 'namespaceTemplates' are mutually exclusive. Prefer 'namespaceTemplates' ('namespaces' is deprecated).", + path: ['namespaceTemplates'], + }) + .refine( + strategy => + !((strategy.reflectionNamespaces?.length ?? 0) > 0 && (strategy.reflectionNamespaceTemplates?.length ?? 0) > 0), + { + message: + "'reflectionNamespaces' and 'reflectionNamespaceTemplates' are mutually exclusive. Prefer 'reflectionNamespaceTemplates' ('reflectionNamespaces' is deprecated).", + path: ['reflectionNamespaceTemplates'], + } + ) + .refine( + strategy => + strategy.type === 'EPISODIC' || + (strategy.reflectionNamespaceTemplates === undefined && strategy.reflectionNamespaces === undefined), + { + message: "'reflectionNamespaceTemplates' is only allowed on EPISODIC strategies", + path: ['reflectionNamespaceTemplates'], + } + ) + .refine( + strategy => { + if (strategy.type !== 'EPISODIC') return true; + const reflection = strategy.reflectionNamespaceTemplates ?? strategy.reflectionNamespaces; + return reflection !== undefined && reflection.length > 0; + }, + { + message: 'EPISODIC strategy requires reflectionNamespaceTemplates', + path: ['reflectionNamespaceTemplates'], + } + ) + .refine( + strategy => { + if (strategy.type !== 'EPISODIC') return true; + const reflection = strategy.reflectionNamespaceTemplates ?? strategy.reflectionNamespaces; + const templates = strategy.namespaceTemplates ?? strategy.namespaces; + if (!reflection || !templates) return true; + return reflection.every(ref => templates.some(ns => ns.startsWith(ref))); + }, + { + message: 'Each reflectionNamespaceTemplate must be a prefix of at least one namespaceTemplate', + path: ['reflectionNamespaceTemplates'], + } + ); + +export type MemoryStrategy = z.infer; diff --git a/src/projectSchemas/v0/schemas/primitives/online-eval-config.ts b/src/projectSchemas/v0/schemas/primitives/online-eval-config.ts new file mode 100644 index 0000000000..d95bde8d92 --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/online-eval-config.ts @@ -0,0 +1,78 @@ +import { TagsSchema } from './tags'; +import { z } from 'zod'; + +// ============================================================================ +// Online Eval Config Types +// ============================================================================ + +export const OnlineEvalConfigNameSchema = z + .string() + .min(1, 'Name is required') + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +export const ClusteringConfigSchema = z.object({ + frequencies: z + .array(z.enum(['DAILY', 'WEEKLY', 'MONTHLY'])) + .min(1) + .max(3), +}); + +export type ClusteringConfig = z.infer; + +export const OnlineEvalConfigSchema = z + .object({ + name: OnlineEvalConfigNameSchema, + /** Agent name to monitor (must match a project agent). Required when using managed AgentCore agents. */ + agent: z.string().min(1, 'Agent name is required').optional(), + /** Optional runtime endpoint name to scope monitoring to a specific endpoint */ + endpoint: z.string().min(1).optional(), + /** CloudWatch log group names for custom/3rd-party agents (1-5 entries) */ + logGroupNames: z.array(z.string().min(1)).min(1).max(5).optional(), + /** Service names to filter traces for custom/3rd-party agents */ + serviceNames: z.array(z.string().min(1)).min(1).optional(), + /** Evaluator names (custom), Builtin.* IDs, or evaluator ARNs */ + evaluators: z.array(z.string().min(1)).optional(), + /** Insight IDs for continuous analysis */ + insights: z.array(z.string().min(1)).optional(), + /** Clustering configuration (requires insights) */ + clusteringConfig: ClusteringConfigSchema.optional(), + /** Sampling rate as a percentage (0.01 to 100) */ + samplingRate: z.number().min(0.01).max(100), + /** Optional description for the online eval config */ + description: z.string().max(200).optional(), + /** Whether to enable execution on create (default: true) */ + enableOnCreate: z.boolean().optional(), + tags: TagsSchema.optional(), + }) + .refine(data => data.agent ?? data.logGroupNames, { + message: 'Either "agent" or "logGroupNames" must be provided', + }) + .refine(data => !(data.agent && data.logGroupNames), { + message: '"agent" and "logGroupNames" are mutually exclusive', + }) + .refine(data => !data.endpoint || data.agent, { + message: '"endpoint" requires "agent"', + }) + .refine(data => !data.serviceNames || data.logGroupNames, { + message: '"serviceNames" requires "logGroupNames"', + }) + .refine( + data => { + const hasEvaluators = data.evaluators != null && data.evaluators.length > 0; + const hasInsights = data.insights != null && data.insights.length > 0; + return hasEvaluators || hasInsights; + }, + { message: 'At least one of evaluators or insights must be provided' } + ) + .refine(data => !(data.evaluators && data.evaluators.length > 0 && data.insights && data.insights.length > 0), { + message: 'Cannot have both evaluators and insights (preview constraint)', + }) + .refine(data => !data.clusteringConfig || (data.insights && data.insights.length > 0), { + message: 'clusteringConfig requires insights to be set', + }); + +export type OnlineEvalConfig = z.infer; diff --git a/src/projectSchemas/v0/schemas/primitives/payment.ts b/src/projectSchemas/v0/schemas/primitives/payment.ts new file mode 100644 index 0000000000..af81d11f1c --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/payment.ts @@ -0,0 +1,113 @@ +import { z } from 'zod'; + +// ============================================================================ +// Payment Provider Schema +// ============================================================================ + +export const PaymentProviderSchema = z.enum(['CoinbaseCDP', 'StripePrivy']); +export type PaymentProvider = z.infer; + +// Documented payment-manager defaults. Materialized on write (via the schema +// `.default()` below and in PaymentManagerPrimitive.add()) so they appear in +// agentcore.json instead of being silently re-defaulted downstream. +export const DEFAULT_AUTO_PAYMENT = true; +export const DEFAULT_SPEND_LIMIT = '10.00'; + +// ============================================================================ +// Payment Manager Name Schema +// ============================================================================ + +// Note: the CreatePaymentManager API name pattern is [a-zA-Z][a-zA-Z0-9]{0,47} — +// no underscores (unlike connectors, which the API does allow underscores for). +// Matching it here so an invalid name is rejected at `add` time instead of failing +// late at deploy/CFN time. +export const PaymentManagerNameSchema = z + .string() + .min(1, 'Payment manager name is required') + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters (max 48 chars)' + ); + +// ============================================================================ +// Payment Connector Name Schema +// ============================================================================ + +export const PaymentConnectorNameSchema = z + .string() + .min(1, 'Payment connector name is required') + .max(48) + .regex( + /^[a-zA-Z][a-zA-Z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +// ============================================================================ +// Payment Connector Schema +// ============================================================================ + +export const PaymentProvisionModeSchema = z.enum(['MANUAL', 'QUICK_CREATE']); +export type PaymentProvisionMode = z.infer; + +export const ManualPaymentConnectorSchema = z.object({ + name: PaymentConnectorNameSchema, + provider: PaymentProviderSchema.default('CoinbaseCDP'), + provisionMode: z.literal('MANUAL').optional(), + credentialName: z.string().min(1), +}); + +export const QuickCreatePaymentConnectorSchema = z.object({ + name: PaymentConnectorNameSchema, + provider: z.literal('CoinbaseCDP'), + provisionMode: z.literal('QUICK_CREATE'), + credentialName: z.never().optional(), +}); + +export const PaymentConnectorSchema = z.union([QuickCreatePaymentConnectorSchema, ManualPaymentConnectorSchema]); + +export type PaymentConnector = z.infer; + +// ============================================================================ +// Payment Manager Schema +// ============================================================================ + +export const PaymentManagerSchema = z + .object({ + name: PaymentManagerNameSchema, + authorizerType: z.enum(['AWS_IAM', 'CUSTOM_JWT']).default('AWS_IAM'), + authorizerConfiguration: z + .object({ + customJWTAuthorizer: z.object({ + discoveryUrl: z.string().url(), + allowedClients: z.array(z.string()).optional(), + allowedAudience: z.array(z.string()).optional(), + allowedScopes: z.array(z.string()).optional(), + }), + }) + .optional(), + connectors: z.array(PaymentConnectorSchema).default([]), + description: z.string().optional(), + autoPayment: z.boolean().default(DEFAULT_AUTO_PAYMENT), + defaultSpendLimit: z.string().default(DEFAULT_SPEND_LIMIT), + paymentToolAllowlist: z.array(z.string()).optional(), + networkPreferences: z.array(z.string()).optional(), + }) + .superRefine((data, ctx) => { + if (data.authorizerType === 'CUSTOM_JWT' && !data.authorizerConfiguration?.customJWTAuthorizer) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'authorizerConfiguration with customJWTAuthorizer is required when authorizerType is CUSTOM_JWT', + path: ['authorizerConfiguration'], + }); + } + }); + +export type PaymentManager = z.infer; + +// ============================================================================ +// Payment Authorizer Type Schema (for CLI parsing) +// ============================================================================ + +export const PaymentAuthorizerTypeSchema = z.enum(['AWS_IAM', 'CUSTOM_JWT']); +export type PaymentAuthorizerType = z.infer; diff --git a/src/projectSchemas/v0/schemas/primitives/policy.ts b/src/projectSchemas/v0/schemas/primitives/policy.ts new file mode 100644 index 0000000000..4c47d86a14 --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/policy.ts @@ -0,0 +1,92 @@ +import { uniqueBy } from '../zod-util'; +import { TagsSchema } from './tags'; +import { z } from 'zod'; + +// ============================================================================ +// Policy Engine Name Schema +// ============================================================================ + +/** + * Policy engine name validation. + * Pattern: ^[A-Za-z][A-Za-z0-9_]*$ max 48 + * Must begin with a letter, alphanumeric + underscores only. + * @see API docs: PolicyEngine name constraints + */ +export const PolicyEngineNameSchema = z + .string() + .min(1, 'Policy engine name is required') + .max(48, 'Policy engine name must be 48 characters or less') + .regex( + /^[A-Za-z][A-Za-z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +// ============================================================================ +// Policy Name Schema +// ============================================================================ + +/** + * Policy name validation. + * Pattern: [A-Za-z][A-Za-z0-9_]* min 1, max 48 + * Must begin with a letter, alphanumeric + underscores only. + * @see API docs: Policy name constraints + */ +export const PolicyNameSchema = z + .string() + .min(1, 'Policy name is required') + .max(48, 'Policy name must be 48 characters or less') + .regex( + /^[A-Za-z][A-Za-z0-9_]{0,47}$/, + 'Must begin with a letter and contain only alphanumeric characters and underscores (max 48 chars)' + ); + +// ============================================================================ +// Validation Mode Schema +// ============================================================================ + +export const ValidationModeSchema = z.enum(['FAIL_ON_ANY_FINDINGS', 'IGNORE_ALL_FINDINGS']); +export type ValidationMode = z.infer; + +export const AuthorizationPhaseSchema = z.enum(['INITIATE', 'RETURN_OUTPUT']).default('INITIATE'); +export type AuthorizationPhase = z.infer; + +export const EnforcementModeSchema = z.enum(['ACTIVE', 'LOG_ONLY']).default('ACTIVE'); +export type EnforcementMode = z.infer; + +// ============================================================================ +// Policy Schema +// ============================================================================ + +export const PolicySchema = z.object({ + name: PolicyNameSchema, + description: z.string().min(1).max(4096).optional(), + statement: z.string().min(1, 'Cedar policy statement is required'), + sourceFile: z.string().optional(), + validationMode: ValidationModeSchema.default('FAIL_ON_ANY_FINDINGS'), + enforcementMode: EnforcementModeSchema.default('ACTIVE'), + authorizationPhase: AuthorizationPhaseSchema.optional(), +}); + +export type Policy = z.infer; + +// ============================================================================ +// Policy Engine Schema +// ============================================================================ + +export const PolicyEngineSchema = z.object({ + name: PolicyEngineNameSchema, + description: z.string().min(1).max(4096).optional(), + encryptionKeyArn: z.string().optional(), + tags: TagsSchema.optional(), + policies: z + .array(PolicySchema) + .default([]) + .superRefine( + uniqueBy( + policy => policy.name, + name => `Duplicate policy name: ${name}` + ) + ), +}); + +export type PolicyEngine = z.infer; diff --git a/src/projectSchemas/v0/schemas/primitives/tags.ts b/src/projectSchemas/v0/schemas/primitives/tags.ts new file mode 100644 index 0000000000..f402cae659 --- /dev/null +++ b/src/projectSchemas/v0/schemas/primitives/tags.ts @@ -0,0 +1,29 @@ +import { z } from 'zod'; + +/** + * Allowed characters for tag keys and values. + * Matches AWS tagging constraints: Unicode letters, digits, whitespace, _ . : / = + - @ + * + * NOTE: This schema is duplicated in @aws/agentcore-cdk (src/schema/schemas/primitives/tags.ts). + * If you change constraints here, update the CDK copy as well. + */ +const TAG_CHAR_PATTERN = /^[\p{L}\p{N}\s_.:/=+\-@]*$/u; + +export const TagKeySchema = z + .string() + .min(1, 'Tag key is required') + .max(128, 'Tag key must be 128 characters or less') + .regex(TAG_CHAR_PATTERN, 'Tag key contains invalid characters') + .refine(key => key.trim().length > 0, 'Tag key must contain at least one non-whitespace character') + .refine(key => !key.startsWith('aws:'), 'Tag keys starting with "aws:" are reserved'); + +export const TagValueSchema = z + .string() + .max(256, 'Tag value must be 256 characters or less') + .regex(TAG_CHAR_PATTERN, 'Tag value contains invalid characters'); + +export const TagsSchema = z + .record(TagKeySchema, TagValueSchema) + .refine(tags => Object.keys(tags).length <= 50, 'Maximum 50 tags per resource'); + +export type Tags = z.infer; diff --git a/src/projectSchemas/v0/schemas/zod-util.ts b/src/projectSchemas/v0/schemas/zod-util.ts new file mode 100644 index 0000000000..fbfce8a164 --- /dev/null +++ b/src/projectSchemas/v0/schemas/zod-util.ts @@ -0,0 +1,24 @@ +import { z } from 'zod'; + +/** + * Creates a superRefine function that validates array elements are unique by a given key. + * + * @param keyFn - Function to extract the key from each element + * @param errorMessage - Function to generate error message for duplicates + * @returns A superRefine callback for use with z.array().superRefine() + */ +export function uniqueBy( + keyFn: (item: T) => string, + errorMessage: (key: string) => string +): (items: T[], ctx: z.RefinementCtx) => void { + return (items, ctx) => { + const seen = new Set(); + for (const [idx, item] of items.entries()) { + const key = keyFn(item); + if (seen.has(key)) { + ctx.addIssue({ code: 'custom', message: errorMessage(key), path: [idx] }); + } + seen.add(key); + } + }; +} diff --git a/src/projectSchemas/v0/types/index.ts b/src/projectSchemas/v0/types/index.ts new file mode 100644 index 0000000000..44bb0aa046 --- /dev/null +++ b/src/projectSchemas/v0/types/index.ts @@ -0,0 +1 @@ +export * from './path'; diff --git a/src/projectSchemas/v0/types/path.ts b/src/projectSchemas/v0/types/path.ts new file mode 100644 index 0000000000..6f4a2213c7 --- /dev/null +++ b/src/projectSchemas/v0/types/path.ts @@ -0,0 +1,23 @@ +/** + * Path type definitions for schema fields. + * + * These types indicate whether a string field represents a file path or directory path, + * enabling the UI to render appropriate path completion (files vs directories only). + */ +import { z } from 'zod'; + +// Path type markers for schema fields +export const PathTypeSchema = z.enum(['file', 'directory']); +export type PathType = z.infer; + +/** + * Branded type for file path strings. + * Used to indicate a schema field expects a path to a file. + */ +export type FilePath = string & { readonly __brand: 'FilePath' }; + +/** + * Branded type for directory path strings. + * Used to indicate a schema field expects a path to a directory. + */ +export type DirectoryPath = string & { readonly __brand: 'DirectoryPath' };