@aws/nx-plugin 1.0.0-rc.67 → 1.0.0-rc.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +1 -0
  2. package/generators.json +7 -0
  3. package/migrations.json +6 -1
  4. package/package.json +1 -1
  5. package/src/agentcore-harness/__snapshots__/generator.spec.ts.snap +238 -0
  6. package/src/agentcore-harness/files/project/README.md.template +83 -0
  7. package/src/agentcore-harness/files/project/scripts/chat.ts.template +99 -0
  8. package/src/agentcore-harness/files/project/src/PROMPT.md.template +16 -0
  9. package/src/agentcore-harness/generator.d.ts +62 -0
  10. package/src/agentcore-harness/generator.js +158 -0
  11. package/src/agentcore-harness/generator.js.map +1 -0
  12. package/src/agentcore-harness/schema.d.js +8 -0
  13. package/src/agentcore-harness/schema.d.js.map +1 -0
  14. package/src/agentcore-harness/schema.d.ts +17 -0
  15. package/src/agentcore-harness/schema.json +53 -0
  16. package/src/migrations/latest/translate-script-whole-file-writes/files/build-system-prompt.ts.fixture +23 -0
  17. package/src/migrations/latest/translate-script-whole-file-writes/files/build-user-prompt.ts.fixture +96 -0
  18. package/src/migrations/latest/translate-script-whole-file-writes/files/config-path.ts.fixture +1 -0
  19. package/src/migrations/latest/translate-script-whole-file-writes/files/file-to-translate.ts.fixture +10 -0
  20. package/src/migrations/latest/translate-script-whole-file-writes/files/get-files-to-translate.ts.fixture +96 -0
  21. package/src/migrations/latest/translate-script-whole-file-writes/files/header.ts.fixture +15 -0
  22. package/src/migrations/latest/translate-script-whole-file-writes/files/log.ts.fixture +18 -0
  23. package/src/migrations/latest/translate-script-whole-file-writes/files/main-call.ts.fixture +6 -0
  24. package/src/migrations/latest/translate-script-whole-file-writes/files/main.ts.fixture +79 -0
  25. package/src/migrations/latest/translate-script-whole-file-writes/files/project-root.ts.fixture +1 -0
  26. package/src/migrations/latest/translate-script-whole-file-writes/files/run-with-concurrency.ts.fixture +57 -0
  27. package/src/migrations/latest/translate-script-whole-file-writes/files/scripts-dir.ts.fixture +1 -0
  28. package/src/migrations/latest/translate-script-whole-file-writes/files/translate-file-for-language.ts.fixture +61 -0
  29. package/src/migrations/latest/translate-script-whole-file-writes/grit/already-migrated.grit +1 -0
  30. package/src/migrations/latest/translate-script-whole-file-writes/grit/build-system-prompt.grit +6 -0
  31. package/src/migrations/latest/translate-script-whole-file-writes/grit/build-user-prompt.grit +6 -0
  32. package/src/migrations/latest/translate-script-whole-file-writes/grit/config-path.grit +1 -0
  33. package/src/migrations/latest/translate-script-whole-file-writes/grit/file-to-translate.grit +11 -0
  34. package/src/migrations/latest/translate-script-whole-file-writes/grit/get-files-to-translate.grit +7 -0
  35. package/src/migrations/latest/translate-script-whole-file-writes/grit/log.grit +3 -0
  36. package/src/migrations/latest/translate-script-whole-file-writes/grit/main-call.grit +1 -0
  37. package/src/migrations/latest/translate-script-whole-file-writes/grit/main.grit +8 -0
  38. package/src/migrations/latest/translate-script-whole-file-writes/grit/project-root.grit +1 -0
  39. package/src/migrations/latest/translate-script-whole-file-writes/grit/run-with-concurrency.grit +6 -0
  40. package/src/migrations/latest/translate-script-whole-file-writes/grit/translate-file-for-language.grit +6 -0
  41. package/src/migrations/latest/translate-script-whole-file-writes/metadata.json +3 -0
  42. package/src/migrations/latest/translate-script-whole-file-writes/migration.d.ts +2 -0
  43. package/src/migrations/latest/translate-script-whole-file-writes/migration.js +103 -0
  44. package/src/migrations/latest/translate-script-whole-file-writes/migration.js.map +1 -0
  45. package/src/migrations/latest/translate-script-whole-file-writes/test-fixtures/released-script-first.ts.fixture +430 -0
  46. package/src/migrations/latest/translate-script-whole-file-writes/test-fixtures/released-script.ts.fixture +431 -0
  47. package/src/preset/__snapshots__/generator.spec.ts.snap +2 -0
  48. package/src/ts/astro-docs/files/translation/scripts/translate.ts.template +269 -148
  49. package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +25 -0
  50. package/src/utils/agent-core-constructs/agent-core-constructs.js +59 -0
  51. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  52. package/src/utils/agent-core-constructs/files/cdk/app/agentcore-harness/__nameKebabCase__/__nameKebabCase__.ts.template +366 -0
  53. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-harness/__nameKebabCase__/__nameKebabCase__.tf.template +282 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/utils/agent-core-constructs/agent-core-constructs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { addStarExport } from '../ast';\nimport type { Containers } from '../containers';\nimport {\n type DeclaredPyDependency,\n type DeclaredTsDependency,\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from '../declared-dependencies';\nimport { addDependenciesToPackageJson } from '../dependencies';\nimport type { Iac } from '../iac';\nimport { esmVars } from '../module-format';\nimport { addDependencyToTargetIfNotPresent } from '../nx';\nimport {\n generatedInfrastructure,\n generatedTerraform,\n type IacMetadata,\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../shared-constructs-constants';\nimport {\n type IPyDepVersion,\n type ITsDepVersion,\n PY_VERSIONS,\n terraformProviderVersions,\n withVersions,\n} from '../versions';\n\ntype IACProvider = { iac: Iac };\n\n/**\n * Dependencies a caller must declare to add an AgentCore Gateway construct.\n *\n * Gated on infrastructure having been generated, since the construct helpers only\n * run on that branch.\n */\nexport const AGENT_CORE_CONSTRUCTS_DEPENDENCIES = [\n { name: 'ejs', when: generatedInfrastructure },\n { name: '@aws-sdk/client-bedrock-agentcore', when: generatedInfrastructure },\n { name: '@types/ejs', when: generatedInfrastructure },\n] as const satisfies readonly DeclaredTsDependency<\n ITsDepVersion,\n IacMetadata\n>[];\n\n/**\n * Python versions the generated Terraform pins in an inline `uv run --with`\n * script, rather than in any `pyproject.toml`.\n *\n * Spread through `ownedElsewhere` because nothing installs them into the\n * workspace — the pin is owned so the version sync keeps it current, and gated on\n * Terraform since the CDK branch writes no such script.\n */\nexport const AGENT_CORE_CONSTRUCTS_PY_DEPENDENCIES = [\n { name: 'boto3', when: generatedTerraform },\n { name: 'httpx', when: generatedTerraform },\n { name: 'mcp', when: generatedTerraform },\n] as const satisfies readonly DeclaredPyDependency<\n IPyDepVersion,\n IacMetadata\n>[];\n\nexport type AgentCoreAuth = 'iam' | 'cognito';\n\nexport type AgentCoreSession = 's3' | 'in-memory';\n\nexport interface AddAgentCoreInfraProps {\n nameClassName: string;\n nameKebabCase: string;\n projectName: string;\n dockerImageTag: string;\n dockerOutputDir: string;\n appDirectory: string;\n serverProtocol: 'mcp' | 'http' | 'a2a';\n auth: AgentCoreAuth;\n /** How this runtime's session should be persisted. MCP servers have no session, so pass 'in-memory'. */\n session: AgentCoreSession;\n containers: Containers;\n}\n\nconst addAgentCoreInfra = async (\n tree: Tree,\n options: AddAgentCoreInfraProps & { iac: Iac },\n) => {\n switch (options.iac) {\n case 'cdk':\n await addAgentCoreCDKInfra(tree, options);\n break;\n case 'terraform':\n addAgentCoreTerraformInfra(tree, options);\n break;\n }\n\n // Update shared constructs/terraform project configuration to depend on this project\n updateJson(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n options.iac === 'cdk' ? SHARED_CONSTRUCTS_DIR : SHARED_TERRAFORM_DIR,\n 'project.json',\n ),\n (config: ProjectConfiguration) => {\n addDependencyToTargetIfNotPresent(\n config,\n 'build',\n `${options.projectName}:build`,\n );\n return config;\n },\n );\n};\n\nconst addAgentCoreCDKInfra = async (\n tree: Tree,\n options: AddAgentCoreInfraProps,\n) => {\n // Generate app specific CDK construct\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'cdk', 'app', 'agent-core'),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n options.appDirectory,\n ),\n { ...options, ...esmVars(tree) },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Export app specific CDK construct\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n options.appDirectory,\n 'index.ts',\n ),\n `./${options.nameKebabCase}/${options.nameKebabCase}.js`,\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'index.ts',\n ),\n `./${options.appDirectory}/index.js`,\n );\n};\n\nconst addAgentCoreTerraformInfra = (\n tree: Tree,\n options: AddAgentCoreInfraProps,\n) => {\n // Add the AgentCore shared module\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'core',\n 'agent-core',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'core',\n 'agent-core',\n ),\n {\n containers: options.containers,\n boto3Version: PY_VERSIONS.boto3,\n ...terraformProviderVersions(),\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Generate app specific agent core configuration\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'app',\n 'agent-core',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'app',\n options.appDirectory,\n ),\n { ...options, ...terraformProviderVersions() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n};\n\nexport interface AddMcpServerInfraProps {\n mcpServerNameClassName: string;\n mcpServerNameKebabCase: string;\n projectName: string;\n dockerImageTag: string;\n dockerOutputDir: string;\n auth: AgentCoreAuth;\n containers: Containers;\n}\n\n/**\n * Add an MCP server CDK construct\n */\nexport const addMcpServerInfra = async (\n tree: Tree,\n options: AddMcpServerInfraProps & IACProvider,\n) => {\n await addAgentCoreInfra(tree, {\n nameClassName: options.mcpServerNameClassName,\n nameKebabCase: options.mcpServerNameKebabCase,\n dockerImageTag: options.dockerImageTag,\n dockerOutputDir: options.dockerOutputDir,\n projectName: options.projectName,\n appDirectory: 'mcp-servers',\n serverProtocol: 'mcp',\n iac: options.iac,\n auth: options.auth,\n // MCP servers are stateless (no conversation session to persist).\n session: 'in-memory',\n containers: options.containers,\n });\n};\n\nexport interface AddAgentInfraProps {\n agentNameClassName: string;\n agentNameKebabCase: string;\n projectName: string;\n dockerImageTag: string;\n dockerOutputDir: string;\n auth: AgentCoreAuth;\n session: AgentCoreSession;\n serverProtocol?: 'http' | 'a2a';\n containers: Containers;\n}\n\n/**\n * Add an agent CDK construct\n */\nexport const addAgentInfra = async (\n tree: Tree,\n options: AddAgentInfraProps & IACProvider,\n) => {\n await addAgentCoreInfra(tree, {\n nameClassName: options.agentNameClassName,\n nameKebabCase: options.agentNameKebabCase,\n projectName: options.projectName,\n dockerImageTag: options.dockerImageTag,\n dockerOutputDir: options.dockerOutputDir,\n appDirectory: 'agents',\n session: options.session,\n serverProtocol: options.serverProtocol ?? 'http',\n iac: options.iac,\n auth: options.auth,\n containers: options.containers,\n });\n};\n\nexport interface AddAgentCoreGatewayInfraProps {\n gatewayNameClassName: string;\n gatewayNameKebabCase: string;\n projectName: string;\n projectDirectory: string;\n cedarPolicy: boolean;\n auth: AgentCoreAuth;\n /**\n * The gateway's protocol: mcp aggregates MCP server targets, http proxies\n * agent runtime targets via path-based routing.\n */\n protocol: 'mcp' | 'http';\n}\n\nexport const addAgentCoreGatewayInfra = async <\n const D extends DependencyDeclaration,\n>(\n tree: Tree,\n options: AddAgentCoreGatewayInfraProps & IACProvider,\n declaration: D & MustDeclare<typeof AGENT_CORE_CONSTRUCTS_DEPENDENCIES, D>,\n) => {\n switch (options.iac) {\n case 'cdk':\n await addAgentCoreGatewayCDKInfra(tree, options, declaration);\n break;\n case 'terraform':\n addAgentCoreGatewayTerraformInfra(tree, options);\n break;\n }\n\n updateJson(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n options.iac === 'cdk' ? SHARED_CONSTRUCTS_DIR : SHARED_TERRAFORM_DIR,\n 'project.json',\n ),\n (config: ProjectConfiguration) => {\n addDependencyToTargetIfNotPresent(\n config,\n 'build',\n `${options.projectName}:build`,\n );\n return config;\n },\n );\n};\n\nconst addAgentCoreGatewayCDKInfra = async (\n tree: Tree,\n options: AddAgentCoreGatewayInfraProps,\n declaration: DependencyDeclaration,\n) => {\n // Generic gateway construct (readiness probe, policy engine, Cedar policy\n // loading) shared by all gateways\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'cdk',\n 'core',\n 'agentcore-gateway',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'agentcore-gateway',\n ),\n { ...esmVars(tree) },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'cdk',\n 'app',\n 'agentcore-gateway',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'gateways',\n ),\n {\n nameClassName: options.gatewayNameClassName,\n nameKebabCase: options.gatewayNameKebabCase,\n projectDirectory: options.projectDirectory,\n cedarPolicy: options.cedarPolicy,\n auth: options.auth,\n protocol: options.protocol,\n ...esmVars(tree),\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'index.ts',\n ),\n './agentcore-gateway/agentcore-gateway.js',\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'gateways',\n 'index.ts',\n ),\n `./${options.gatewayNameKebabCase}/${options.gatewayNameKebabCase}.js`,\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'index.ts',\n ),\n './gateways/index.js',\n );\n\n // The gateway construct renders Cedar policies with ejs and its readiness\n // probe uses the AgentCore SDK client; declare both so the lint passes.\n addDependenciesToPackageJson(\n tree,\n withVersions(\n forDependencies<typeof AGENT_CORE_CONSTRUCTS_DEPENDENCIES>(declaration),\n ['ejs', '@aws-sdk/client-bedrock-agentcore'],\n ),\n withVersions(\n forDependencies<typeof AGENT_CORE_CONSTRUCTS_DEPENDENCIES>(declaration),\n ['@types/ejs'],\n ),\n joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'package.json'),\n );\n};\n\nconst addAgentCoreGatewayTerraformInfra = (\n tree: Tree,\n options: AddAgentCoreGatewayInfraProps,\n) => {\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'core',\n 'agentcore-gateway',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'core',\n 'agentcore-gateway',\n ),\n { ...terraformProviderVersions() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'app',\n 'agentcore-gateway',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'app',\n 'gateways',\n ),\n {\n nameClassName: options.gatewayNameClassName,\n nameKebabCase: options.gatewayNameKebabCase,\n projectDirectory: options.projectDirectory,\n cedarPolicy: options.cedarPolicy,\n auth: options.auth,\n protocol: options.protocol,\n boto3Version: PY_VERSIONS.boto3,\n httpxVersion: PY_VERSIONS.httpx,\n mcpVersion: PY_VERSIONS.mcp,\n ...terraformProviderVersions(),\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // The Cedar render script is only needed when policies are enabled\n if (!options.cedarPolicy) {\n const renderScript = joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'app',\n 'gateways',\n options.gatewayNameKebabCase,\n 'render-cedar.cjs',\n );\n if (tree.exists(renderScript)) {\n tree.delete(renderScript);\n }\n }\n};\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateJson","addStarExport","forDependencies","addDependenciesToPackageJson","esmVars","addDependencyToTargetIfNotPresent","generatedInfrastructure","generatedTerraform","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_DIR","PY_VERSIONS","terraformProviderVersions","withVersions","AGENT_CORE_CONSTRUCTS_DEPENDENCIES","name","when","AGENT_CORE_CONSTRUCTS_PY_DEPENDENCIES","addAgentCoreInfra","tree","options","iac","addAgentCoreCDKInfra","addAgentCoreTerraformInfra","config","projectName","dirname","appDirectory","overwriteStrategy","KeepExisting","nameKebabCase","containers","boto3Version","boto3","addMcpServerInfra","nameClassName","mcpServerNameClassName","mcpServerNameKebabCase","dockerImageTag","dockerOutputDir","serverProtocol","auth","session","addAgentInfra","agentNameClassName","agentNameKebabCase","addAgentCoreGatewayInfra","declaration","addAgentCoreGatewayCDKInfra","addAgentCoreGatewayTerraformInfra","gatewayNameClassName","gatewayNameKebabCase","projectDirectory","cedarPolicy","protocol","httpxVersion","httpx","mcpVersion","mcp","renderScript","exists","delete"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/utils/agent-core-constructs/agent-core-constructs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { addStarExport } from '../ast';\nimport type { Containers } from '../containers';\nimport {\n type DeclaredPyDependency,\n type DeclaredTsDependency,\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from '../declared-dependencies';\nimport { addDependenciesToPackageJson } from '../dependencies';\nimport type { Iac } from '../iac';\nimport { esmVars } from '../module-format';\nimport { addDependencyToTargetIfNotPresent } from '../nx';\nimport {\n generatedInfrastructure,\n generatedTerraform,\n type IacMetadata,\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../shared-constructs-constants';\nimport {\n type IPyDepVersion,\n type ITsDepVersion,\n PY_VERSIONS,\n terraformProviderVersions,\n withVersions,\n} from '../versions';\n\ntype IACProvider = { iac: Iac };\n\n/**\n * Dependencies a caller must declare to add an AgentCore Gateway construct.\n *\n * Gated on infrastructure having been generated, since the construct helpers only\n * run on that branch.\n */\nexport const AGENT_CORE_CONSTRUCTS_DEPENDENCIES = [\n { name: 'ejs', when: generatedInfrastructure },\n { name: '@aws-sdk/client-bedrock-agentcore', when: generatedInfrastructure },\n { name: '@types/ejs', when: generatedInfrastructure },\n] as const satisfies readonly DeclaredTsDependency<\n ITsDepVersion,\n IacMetadata\n>[];\n\n/**\n * Python versions the generated Terraform pins in an inline `uv run --with`\n * script, rather than in any `pyproject.toml`.\n *\n * Spread through `ownedElsewhere` because nothing installs them into the\n * workspace — the pin is owned so the version sync keeps it current, and gated on\n * Terraform since the CDK branch writes no such script.\n */\nexport const AGENT_CORE_CONSTRUCTS_PY_DEPENDENCIES = [\n { name: 'boto3', when: generatedTerraform },\n { name: 'httpx', when: generatedTerraform },\n { name: 'mcp', when: generatedTerraform },\n] as const satisfies readonly DeclaredPyDependency<\n IPyDepVersion,\n IacMetadata\n>[];\n\nexport type AgentCoreAuth = 'iam' | 'cognito';\n\nexport type AgentCoreSession = 's3' | 'in-memory';\n\nexport interface AddAgentCoreInfraProps {\n nameClassName: string;\n nameKebabCase: string;\n projectName: string;\n dockerImageTag: string;\n dockerOutputDir: string;\n appDirectory: string;\n serverProtocol: 'mcp' | 'http' | 'a2a';\n auth: AgentCoreAuth;\n /** How this runtime's session should be persisted. MCP servers have no session, so pass 'in-memory'. */\n session: AgentCoreSession;\n containers: Containers;\n}\n\nconst addAgentCoreInfra = async (\n tree: Tree,\n options: AddAgentCoreInfraProps & { iac: Iac },\n) => {\n switch (options.iac) {\n case 'cdk':\n await addAgentCoreCDKInfra(tree, options);\n break;\n case 'terraform':\n addAgentCoreTerraformInfra(tree, options);\n break;\n }\n\n // Update shared constructs/terraform project configuration to depend on this project\n updateJson(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n options.iac === 'cdk' ? SHARED_CONSTRUCTS_DIR : SHARED_TERRAFORM_DIR,\n 'project.json',\n ),\n (config: ProjectConfiguration) => {\n addDependencyToTargetIfNotPresent(\n config,\n 'build',\n `${options.projectName}:build`,\n );\n return config;\n },\n );\n};\n\nconst addAgentCoreCDKInfra = async (\n tree: Tree,\n options: AddAgentCoreInfraProps,\n) => {\n // Generate app specific CDK construct\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'cdk', 'app', 'agent-core'),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n options.appDirectory,\n ),\n { ...options, ...esmVars(tree) },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Export app specific CDK construct\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n options.appDirectory,\n 'index.ts',\n ),\n `./${options.nameKebabCase}/${options.nameKebabCase}.js`,\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'index.ts',\n ),\n `./${options.appDirectory}/index.js`,\n );\n};\n\nconst addAgentCoreTerraformInfra = (\n tree: Tree,\n options: AddAgentCoreInfraProps,\n) => {\n // Add the AgentCore shared module\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'core',\n 'agent-core',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'core',\n 'agent-core',\n ),\n {\n containers: options.containers,\n boto3Version: PY_VERSIONS.boto3,\n ...terraformProviderVersions(),\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Generate app specific agent core configuration\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'app',\n 'agent-core',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'app',\n options.appDirectory,\n ),\n { ...options, ...terraformProviderVersions() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n};\n\nexport interface AddMcpServerInfraProps {\n mcpServerNameClassName: string;\n mcpServerNameKebabCase: string;\n projectName: string;\n dockerImageTag: string;\n dockerOutputDir: string;\n auth: AgentCoreAuth;\n containers: Containers;\n}\n\n/**\n * Add an MCP server CDK construct\n */\nexport const addMcpServerInfra = async (\n tree: Tree,\n options: AddMcpServerInfraProps & IACProvider,\n) => {\n await addAgentCoreInfra(tree, {\n nameClassName: options.mcpServerNameClassName,\n nameKebabCase: options.mcpServerNameKebabCase,\n dockerImageTag: options.dockerImageTag,\n dockerOutputDir: options.dockerOutputDir,\n projectName: options.projectName,\n appDirectory: 'mcp-servers',\n serverProtocol: 'mcp',\n iac: options.iac,\n auth: options.auth,\n // MCP servers are stateless (no conversation session to persist).\n session: 'in-memory',\n containers: options.containers,\n });\n};\n\nexport interface AddAgentInfraProps {\n agentNameClassName: string;\n agentNameKebabCase: string;\n projectName: string;\n dockerImageTag: string;\n dockerOutputDir: string;\n auth: AgentCoreAuth;\n session: AgentCoreSession;\n serverProtocol?: 'http' | 'a2a';\n containers: Containers;\n}\n\n/**\n * Add an agent CDK construct\n */\nexport const addAgentInfra = async (\n tree: Tree,\n options: AddAgentInfraProps & IACProvider,\n) => {\n await addAgentCoreInfra(tree, {\n nameClassName: options.agentNameClassName,\n nameKebabCase: options.agentNameKebabCase,\n projectName: options.projectName,\n dockerImageTag: options.dockerImageTag,\n dockerOutputDir: options.dockerOutputDir,\n appDirectory: 'agents',\n session: options.session,\n serverProtocol: options.serverProtocol ?? 'http',\n iac: options.iac,\n auth: options.auth,\n containers: options.containers,\n });\n};\n\nexport interface AddAgentCoreGatewayInfraProps {\n gatewayNameClassName: string;\n gatewayNameKebabCase: string;\n projectName: string;\n projectDirectory: string;\n cedarPolicy: boolean;\n auth: AgentCoreAuth;\n /**\n * The gateway's protocol: mcp aggregates MCP server targets, http proxies\n * agent runtime targets via path-based routing.\n */\n protocol: 'mcp' | 'http';\n}\n\nexport const addAgentCoreGatewayInfra = async <\n const D extends DependencyDeclaration,\n>(\n tree: Tree,\n options: AddAgentCoreGatewayInfraProps & IACProvider,\n declaration: D & MustDeclare<typeof AGENT_CORE_CONSTRUCTS_DEPENDENCIES, D>,\n) => {\n switch (options.iac) {\n case 'cdk':\n await addAgentCoreGatewayCDKInfra(tree, options, declaration);\n break;\n case 'terraform':\n addAgentCoreGatewayTerraformInfra(tree, options);\n break;\n }\n\n updateJson(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n options.iac === 'cdk' ? SHARED_CONSTRUCTS_DIR : SHARED_TERRAFORM_DIR,\n 'project.json',\n ),\n (config: ProjectConfiguration) => {\n addDependencyToTargetIfNotPresent(\n config,\n 'build',\n `${options.projectName}:build`,\n );\n return config;\n },\n );\n};\n\nconst addAgentCoreGatewayCDKInfra = async (\n tree: Tree,\n options: AddAgentCoreGatewayInfraProps,\n declaration: DependencyDeclaration,\n) => {\n // Generic gateway construct (readiness probe, policy engine, Cedar policy\n // loading) shared by all gateways\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'cdk',\n 'core',\n 'agentcore-gateway',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'agentcore-gateway',\n ),\n { ...esmVars(tree) },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'cdk',\n 'app',\n 'agentcore-gateway',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'gateways',\n ),\n {\n nameClassName: options.gatewayNameClassName,\n nameKebabCase: options.gatewayNameKebabCase,\n projectDirectory: options.projectDirectory,\n cedarPolicy: options.cedarPolicy,\n auth: options.auth,\n protocol: options.protocol,\n ...esmVars(tree),\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'index.ts',\n ),\n './agentcore-gateway/agentcore-gateway.js',\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'gateways',\n 'index.ts',\n ),\n `./${options.gatewayNameKebabCase}/${options.gatewayNameKebabCase}.js`,\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'index.ts',\n ),\n './gateways/index.js',\n );\n\n // The gateway construct renders Cedar policies with ejs and its readiness\n // probe uses the AgentCore SDK client; declare both so the lint passes.\n addDependenciesToPackageJson(\n tree,\n withVersions(\n forDependencies<typeof AGENT_CORE_CONSTRUCTS_DEPENDENCIES>(declaration),\n ['ejs', '@aws-sdk/client-bedrock-agentcore'],\n ),\n withVersions(\n forDependencies<typeof AGENT_CORE_CONSTRUCTS_DEPENDENCIES>(declaration),\n ['@types/ejs'],\n ),\n joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'package.json'),\n );\n};\n\nconst addAgentCoreGatewayTerraformInfra = (\n tree: Tree,\n options: AddAgentCoreGatewayInfraProps,\n) => {\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'core',\n 'agentcore-gateway',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'core',\n 'agentcore-gateway',\n ),\n { ...terraformProviderVersions() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'app',\n 'agentcore-gateway',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'app',\n 'gateways',\n ),\n {\n nameClassName: options.gatewayNameClassName,\n nameKebabCase: options.gatewayNameKebabCase,\n projectDirectory: options.projectDirectory,\n cedarPolicy: options.cedarPolicy,\n auth: options.auth,\n protocol: options.protocol,\n boto3Version: PY_VERSIONS.boto3,\n httpxVersion: PY_VERSIONS.httpx,\n mcpVersion: PY_VERSIONS.mcp,\n ...terraformProviderVersions(),\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // The Cedar render script is only needed when policies are enabled\n if (!options.cedarPolicy) {\n const renderScript = joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'app',\n 'gateways',\n options.gatewayNameKebabCase,\n 'render-cedar.cjs',\n );\n if (tree.exists(renderScript)) {\n tree.delete(renderScript);\n }\n }\n};\n\nexport interface AddAgentCoreHarnessInfraProps {\n harnessNameClassName: string;\n harnessNameKebabCase: string;\n /**\n * Workspace-root-relative harness project root, eg `packages/my-harness`.\n * The `src/PROMPT.md` path both templates read is derived from it.\n */\n projectRoot: string;\n /** Leading-letter-guaranteed, 31-char-truncated resource name prefix. */\n harnessNamePrefix: string;\n}\n\n/**\n * Template substitution context shared by the CDK and Terraform harness\n * branches. Both prompt path fields carry the same workspace-root-relative\n * path, named per provider so each template's usage reads on its own.\n */\ninterface HarnessTemplateContext {\n nameClassName: string;\n nameKebabCase: string;\n harnessNamePrefix: string;\n /** Joined onto `findWorkspaceRoot()` in the CDK construct. */\n promptPathFromCdk: string;\n /** Appended to the `path.module` walk to the workspace root in Terraform. */\n promptPathFromTerraform: string;\n}\n\n/**\n * Add AgentCore Harness infrastructure for the selected IaC provider.\n *\n * Renders the provider-specific Harness infrastructure (a CDK construct or\n * a Terraform module) into the Shared Infrastructure Project with\n * `KeepExisting`, so existing files become user-owned and are never\n * rewritten by reruns.\n *\n * Unlike agents, MCP servers and gateways, no build dependency is added\n * from the shared infrastructure project to the Harness Project: generated\n * Harness infrastructure does not import Harness Project source, so a\n * dependency would only create false rebuild coupling.\n */\nexport const addAgentCoreHarnessInfra = async (\n tree: Tree,\n options: AddAgentCoreHarnessInfraProps & IACProvider,\n): Promise<void> => {\n // One resolved template context, built once and passed to both provider\n // branches. The prompt path is derived from the same projectRoot the\n // Harness Project is written to, so explicit placement needs no extra logic.\n const promptPath = joinPathFragments(options.projectRoot, 'src', 'PROMPT.md');\n const templateContext: HarnessTemplateContext = {\n nameClassName: options.harnessNameClassName,\n nameKebabCase: options.harnessNameKebabCase,\n harnessNamePrefix: options.harnessNamePrefix,\n promptPathFromCdk: promptPath,\n promptPathFromTerraform: promptPath,\n };\n\n switch (options.iac) {\n case 'cdk':\n await addAgentCoreHarnessCDKInfra(tree, templateContext);\n break;\n case 'terraform':\n addAgentCoreHarnessTerraformInfra(tree, templateContext);\n break;\n }\n};\n\nconst addAgentCoreHarnessCDKInfra = async (\n tree: Tree,\n templateContext: HarnessTemplateContext,\n) => {\n // Generate the app specific CDK construct under\n // src/app/harnesses/<kebab-case-name>/\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'cdk',\n 'app',\n 'agentcore-harness',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'harnesses',\n ),\n { ...templateContext, ...esmVars(tree) },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Export the construct through the harnesses app index and the shared\n // app index. addStarExport creates a missing index file and semantically\n // deduplicates equivalent exports on reruns.\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'harnesses',\n 'index.ts',\n ),\n `./${templateContext.nameKebabCase}/${templateContext.nameKebabCase}.js`,\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'index.ts',\n ),\n './harnesses/index.js',\n );\n};\n\nconst addAgentCoreHarnessTerraformInfra = (\n tree: Tree,\n templateContext: HarnessTemplateContext,\n) => {\n // Generate the app specific Terraform module under\n // src/app/harnesses/<kebab-case-name>/. No CDK files or exports are\n // created on this path.\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'app',\n 'agentcore-harness',\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'app',\n 'harnesses',\n ),\n { ...templateContext, ...terraformProviderVersions() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n};\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateJson","addStarExport","forDependencies","addDependenciesToPackageJson","esmVars","addDependencyToTargetIfNotPresent","generatedInfrastructure","generatedTerraform","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_DIR","PY_VERSIONS","terraformProviderVersions","withVersions","AGENT_CORE_CONSTRUCTS_DEPENDENCIES","name","when","AGENT_CORE_CONSTRUCTS_PY_DEPENDENCIES","addAgentCoreInfra","tree","options","iac","addAgentCoreCDKInfra","addAgentCoreTerraformInfra","config","projectName","dirname","appDirectory","overwriteStrategy","KeepExisting","nameKebabCase","containers","boto3Version","boto3","addMcpServerInfra","nameClassName","mcpServerNameClassName","mcpServerNameKebabCase","dockerImageTag","dockerOutputDir","serverProtocol","auth","session","addAgentInfra","agentNameClassName","agentNameKebabCase","addAgentCoreGatewayInfra","declaration","addAgentCoreGatewayCDKInfra","addAgentCoreGatewayTerraformInfra","gatewayNameClassName","gatewayNameKebabCase","projectDirectory","cedarPolicy","protocol","httpxVersion","httpx","mcpVersion","mcp","renderScript","exists","delete","addAgentCoreHarnessInfra","promptPath","projectRoot","templateContext","harnessNameClassName","harnessNameKebabCase","harnessNamePrefix","promptPathFromCdk","promptPathFromTerraform","addAgentCoreHarnessCDKInfra","addAgentCoreHarnessTerraformInfra"],"mappings":"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"}
@@ -0,0 +1,366 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as url from 'node:url';
4
+ import { CfnOutput, Lazy, Names, Stack } from 'aws-cdk-lib';
5
+ import * as agentcore from 'aws-cdk-lib/aws-bedrockagentcore';
6
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
7
+ import * as iam from 'aws-cdk-lib/aws-iam';
8
+ import { Construct, IConstruct } from 'constructs';
9
+ import { suppressRules } from '../../../core/checkov<% if (esm) { %>.js<% } %>';
10
+ import { RuntimeConfig } from '../../../core/runtime-config<% if (esm) { %>.js<% } %>';
11
+ import { findWorkspaceRoot } from '../../../core/workspace<% if (esm) { %>.js<% } %>';
12
+
13
+ // Checkov rules flagging IAM statements whose resource cannot be scoped.
14
+ const WILDCARD_IAM_RULES = ['CKV_AWS_107', 'CKV_AWS_111', 'CKV_AWS_356'];
15
+
16
+ // Read at synth time, anchored on the workspace root so it still resolves once
17
+ // this file compiles to dist/.
18
+ const systemPrompt = fs.readFileSync(
19
+ path.join(
20
+ findWorkspaceRoot(url.fileURLToPath(new URL(<% if (esm) { %>import.meta.url<% } else { %>require('url').pathToFileURL(__filename).href<% } %>))),
21
+ '<%- promptPathFromCdk %>',
22
+ ),
23
+ 'utf-8',
24
+ );
25
+
26
+ /**
27
+ * Properties for the <%- nameClassName %> Harness. Any native Harness field
28
+ * supplied here takes precedence over the generated defaults.
29
+ */
30
+ export interface <%- nameClassName %>Props
31
+ extends Partial<
32
+ Omit<agentcore.CfnHarnessProps, 'executionRoleArn' | 'allowedTools'>
33
+ > {
34
+ /** Existing execution role to use instead of the generated role. */
35
+ executionRole?: iam.IRole;
36
+ /** Model resources the generated execution role may invoke. */
37
+ modelResourceArns?: string[];
38
+ /** Tools the Harness may use. Deploys with none unless supplied here. */
39
+ allowedTools?: agentcore.CfnHarnessProps['allowedTools'];
40
+ /**
41
+ * Run the Harness in a VPC so it can reach private resources. Selects private
42
+ * subnets with egress unless `vpcSubnets` narrows it, and creates a security
43
+ * group unless `securityGroups` supplies them.
44
+ */
45
+ vpc?: ec2.IVpc;
46
+ /** Subnets to place the Harness in. Requires `vpc`. */
47
+ vpcSubnets?: ec2.SubnetSelection;
48
+ /** Security groups for the Harness. Requires `vpc`. */
49
+ securityGroups?: ec2.ISecurityGroup[];
50
+ }
51
+
52
+ /** A managed Amazon Bedrock AgentCore Harness, using IAM inbound auth. */
53
+ export class <%- nameClassName %>
54
+ extends Construct
55
+ implements iam.IGrantable, ec2.IConnectable
56
+ {
57
+ public readonly harness: agentcore.CfnHarness;
58
+ public readonly executionRole: iam.IRole;
59
+ private readonly _connections?: ec2.Connections;
60
+
61
+ constructor(scope: Construct, id: string, props?: <%- nameClassName %>Props) {
62
+ super(scope, id);
63
+
64
+ const stack = Stack.of(this);
65
+ const {
66
+ executionRole,
67
+ modelResourceArns = [
68
+ `arn:${stack.partition}:bedrock:*::foundation-model/*`,
69
+ `arn:${stack.partition}:bedrock:${stack.region}:${stack.account}:*`,
70
+ ],
71
+ vpc,
72
+ vpcSubnets,
73
+ securityGroups,
74
+ ...harnessProps
75
+ } = props ?? {};
76
+
77
+ if (!vpc && (vpcSubnets || securityGroups)) {
78
+ throw new Error(
79
+ 'vpcSubnets and securityGroups require vpc to be supplied.',
80
+ );
81
+ }
82
+
83
+ if (vpc) {
84
+ this._connections = new ec2.Connections({
85
+ securityGroups: securityGroups ?? [
86
+ new ec2.SecurityGroup(this, 'SecurityGroup', {
87
+ vpc,
88
+ description: `Harness ${id}`,
89
+ }),
90
+ ],
91
+ });
92
+ }
93
+
94
+ // Harness names allow ASCII letters, digits and underscores, must start
95
+ // with a letter, and are at most 40 characters.
96
+ const uniqueName = Names.uniqueResourceName(this, {
97
+ maxLength: 39,
98
+ separator: '_',
99
+ allowedSpecialCharacters: '_',
100
+ });
101
+ const harnessName =
102
+ harnessProps.harnessName ??
103
+ (/^[A-Za-z]/.test(uniqueName) ? uniqueName : `H${uniqueName}`);
104
+
105
+ this.executionRole =
106
+ executionRole ??
107
+ new iam.Role(this, 'ExecutionRole', {
108
+ assumedBy: new iam.ServicePrincipal('bedrock-agentcore.amazonaws.com', {
109
+ conditions: {
110
+ StringEquals: { 'aws:SourceAccount': stack.account },
111
+ ArnLike: {
112
+ 'aws:SourceArn': `arn:${stack.partition}:bedrock-agentcore:${stack.region}:${stack.account}:*`,
113
+ },
114
+ },
115
+ }),
116
+ });
117
+
118
+ if (!executionRole) {
119
+ // Baseline permissions from the AgentCore Harness security guidance:
120
+ // https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness-security.html
121
+ [
122
+ new iam.PolicyStatement({
123
+ sid: 'BedrockModelInvocation',
124
+ actions: [
125
+ 'bedrock:InvokeModel',
126
+ 'bedrock:InvokeModelWithResponseStream',
127
+ ],
128
+ resources: modelResourceArns,
129
+ }),
130
+ new iam.PolicyStatement({
131
+ sid: 'EcrPublicTokenAccess',
132
+ actions: ['ecr-public:GetAuthorizationToken'],
133
+ resources: ['*'],
134
+ }),
135
+ new iam.PolicyStatement({
136
+ sid: 'StsForEcrPublicPull',
137
+ actions: ['sts:GetServiceBearerToken'],
138
+ resources: ['*'],
139
+ }),
140
+ new iam.PolicyStatement({
141
+ sid: 'XRayTracingAccess',
142
+ actions: [
143
+ 'xray:PutTraceSegments',
144
+ 'xray:PutTelemetryRecords',
145
+ 'xray:GetSamplingRules',
146
+ 'xray:GetSamplingTargets',
147
+ ],
148
+ resources: ['*'],
149
+ }),
150
+ new iam.PolicyStatement({
151
+ sid: 'CloudWatchLogsGroup',
152
+ actions: ['logs:CreateLogGroup', 'logs:DescribeLogStreams'],
153
+ resources: [
154
+ `arn:${stack.partition}:logs:${stack.region}:${stack.account}:log-group:/aws/bedrock-agentcore/runtimes/*`,
155
+ ],
156
+ }),
157
+ new iam.PolicyStatement({
158
+ sid: 'CloudWatchLogsDescribeGroups',
159
+ actions: ['logs:DescribeLogGroups'],
160
+ resources: [
161
+ `arn:${stack.partition}:logs:${stack.region}:${stack.account}:log-group:*`,
162
+ ],
163
+ }),
164
+ new iam.PolicyStatement({
165
+ sid: 'CloudWatchLogsStream',
166
+ actions: ['logs:CreateLogStream', 'logs:PutLogEvents'],
167
+ resources: [
168
+ `arn:${stack.partition}:logs:${stack.region}:${stack.account}:log-group:/aws/bedrock-agentcore/runtimes/*:log-stream:*`,
169
+ ],
170
+ }),
171
+ new iam.PolicyStatement({
172
+ sid: 'CloudWatchMetricsPublish',
173
+ actions: ['cloudwatch:PutMetricData'],
174
+ resources: ['*'],
175
+ conditions: {
176
+ StringEquals: { 'cloudwatch:namespace': 'bedrock-agentcore' },
177
+ },
178
+ }),
179
+ new iam.PolicyStatement({
180
+ sid: 'AgentCoreWorkloadIdentity',
181
+ actions: [
182
+ 'bedrock-agentcore:GetWorkloadAccessToken',
183
+ 'bedrock-agentcore:GetWorkloadAccessTokenForJWT',
184
+ ],
185
+ resources: [
186
+ `arn:${stack.partition}:bedrock-agentcore:${stack.region}:${stack.account}:workload-identity-directory/default`,
187
+ `arn:${stack.partition}:bedrock-agentcore:${stack.region}:${stack.account}:workload-identity-directory/default/workload-identity/harness_${harnessName}-*`,
188
+ ],
189
+ }),
190
+ new iam.PolicyStatement({
191
+ sid: 'AgentCoreBrowserDefault',
192
+ actions: [
193
+ 'bedrock-agentcore:StartBrowserSession',
194
+ 'bedrock-agentcore:StopBrowserSession',
195
+ 'bedrock-agentcore:GetBrowserSession',
196
+ 'bedrock-agentcore:ListBrowserSessions',
197
+ 'bedrock-agentcore:UpdateBrowserStream',
198
+ 'bedrock-agentcore:ConnectBrowserAutomationStream',
199
+ 'bedrock-agentcore:ConnectBrowserLiveViewStream',
200
+ ],
201
+ resources: [
202
+ `arn:${stack.partition}:bedrock-agentcore:${stack.region}:aws:browser/*`,
203
+ ],
204
+ }),
205
+ new iam.PolicyStatement({
206
+ sid: 'AgentCoreCodeInterpreterDefault',
207
+ actions: [
208
+ 'bedrock-agentcore:StartCodeInterpreterSession',
209
+ 'bedrock-agentcore:StopCodeInterpreterSession',
210
+ 'bedrock-agentcore:GetCodeInterpreterSession',
211
+ 'bedrock-agentcore:ListCodeInterpreterSessions',
212
+ 'bedrock-agentcore:InvokeCodeInterpreter',
213
+ ],
214
+ resources: [
215
+ `arn:${stack.partition}:bedrock-agentcore:${stack.region}:aws:code-interpreter/*`,
216
+ ],
217
+ }),
218
+ ].forEach((statement) =>
219
+ this.executionRole.addToPrincipalPolicy(statement),
220
+ );
221
+
222
+ // These statements take no resource-level permission.
223
+ const isPolicy = (c: IConstruct) => c instanceof iam.Policy;
224
+ suppressRules(
225
+ this.executionRole,
226
+ WILDCARD_IAM_RULES,
227
+ 'EcrPublicTokenAccess: ecr-public:GetAuthorizationToken has no resource-level permission.',
228
+ isPolicy,
229
+ );
230
+ suppressRules(
231
+ this.executionRole,
232
+ WILDCARD_IAM_RULES,
233
+ 'StsForEcrPublicPull: sts:GetServiceBearerToken has no resource-level permission.',
234
+ isPolicy,
235
+ );
236
+ suppressRules(
237
+ this.executionRole,
238
+ WILDCARD_IAM_RULES,
239
+ 'XRayTracingAccess: X-Ray segment and sampling APIs have no resource-level permission.',
240
+ isPolicy,
241
+ );
242
+ }
243
+
244
+ // Rendered lazily so security groups added through `connections` after
245
+ // construction are still picked up.
246
+ const environment: agentcore.CfnHarnessProps['environment'] | undefined = vpc
247
+ ? Lazy.any({
248
+ produce: () => ({
249
+ ...(harnessProps.environment as
250
+ | agentcore.CfnHarness.HarnessEnvironmentProviderProperty
251
+ | undefined),
252
+ agentCoreRuntimeEnvironment: {
253
+ ...(
254
+ harnessProps.environment as
255
+ | agentcore.CfnHarness.HarnessEnvironmentProviderProperty
256
+ | undefined
257
+ )?.agentCoreRuntimeEnvironment,
258
+ networkConfiguration: {
259
+ networkMode: 'VPC',
260
+ networkModeConfig: {
261
+ subnets: vpc.selectSubnets(
262
+ vpcSubnets ?? {
263
+ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
264
+ },
265
+ ).subnetIds,
266
+ securityGroups: this._connections!.securityGroups.map(
267
+ (group) => group.securityGroupId,
268
+ ),
269
+ },
270
+ },
271
+ },
272
+ }),
273
+ })
274
+ : harnessProps.environment;
275
+
276
+ this.harness = new agentcore.CfnHarness(this, 'Harness', {
277
+ model: {
278
+ bedrockModelConfig: {
279
+ modelId: 'global.anthropic.claude-sonnet-4-6',
280
+ },
281
+ },
282
+ systemPrompt: [{ text: systemPrompt }],
283
+ ...harnessProps,
284
+ // Set after harnessProps so the deployed name always matches the
285
+ // execution role's workload-identity resource pattern.
286
+ harnessName,
287
+ executionRoleArn: this.executionRole.roleArn,
288
+ // Carries the VPC network configuration when `vpc` is supplied, and is
289
+ // the caller's own `environment` otherwise.
290
+ environment,
291
+ });
292
+
293
+ // The Harness provisions managed memory unless `memory` is supplied, and
294
+ // the service names it, so the grant scopes to the resulting ARN.
295
+ if (!executionRole && harnessProps.memory === undefined) {
296
+ this.executionRole.addToPrincipalPolicy(
297
+ new iam.PolicyStatement({
298
+ sid: 'AgentCoreManagedMemory',
299
+ actions: [
300
+ 'bedrock-agentcore:CreateEvent',
301
+ 'bedrock-agentcore:DeleteEvent',
302
+ 'bedrock-agentcore:GetEvent',
303
+ 'bedrock-agentcore:ListEvents',
304
+ 'bedrock-agentcore:RetrieveMemoryRecords',
305
+ ],
306
+ resources: [
307
+ this.harness.attrMemoryManagedMemoryConfigurationArn,
308
+ ],
309
+ }),
310
+ );
311
+ }
312
+
313
+ const rc = RuntimeConfig.ensure(this);
314
+ rc.set('agentcore', 'harnesses', {
315
+ ...rc.get('agentcore').harnesses,
316
+ <%- nameClassName %>: this.harness.attrArn,
317
+ });
318
+
319
+ // Materialises the AppConfig resources so the entry above is deployed and
320
+ // the chat script's RUNTIME_CONFIG_APP_ID lookup resolves.
321
+ void rc.appConfigApplicationId;
322
+
323
+ new CfnOutput(this, 'HarnessArn', { value: this.harness.attrArn });
324
+ }
325
+
326
+ public get grantPrincipal(): iam.IPrincipal {
327
+ return this.executionRole.grantPrincipal;
328
+ }
329
+
330
+ /**
331
+ * Network connections for this Harness, for granting access to resources such
332
+ * as a database. Only available when the Harness runs in a VPC.
333
+ */
334
+ public get connections(): ec2.Connections {
335
+ if (!this._connections) {
336
+ throw new Error(
337
+ 'Connections are only available when the Harness runs in a VPC. Supply the vpc prop.',
338
+ );
339
+ }
340
+ return this._connections;
341
+ }
342
+
343
+ /** The deployed Harness ARN. */
344
+ public get harnessArn(): string {
345
+ return this.harness.attrArn;
346
+ }
347
+
348
+ /** Add permissions required by tools, skills, memory, or custom models. */
349
+ public addToRolePolicy(
350
+ statement: iam.PolicyStatement,
351
+ ): iam.AddToPrincipalPolicyResult {
352
+ return this.executionRole.addToPrincipalPolicy(statement);
353
+ }
354
+
355
+ /** Grant an IAM principal permission to invoke this Harness. */
356
+ public grantInvokeAccess(grantee: iam.IGrantable): iam.Grant {
357
+ return iam.Grant.addToPrincipal({
358
+ grantee,
359
+ actions: [
360
+ 'bedrock-agentcore:InvokeHarness',
361
+ 'bedrock-agentcore:InvokeAgentRuntime',
362
+ ],
363
+ resourceArns: [this.harness.attrArn],
364
+ });
365
+ }
366
+ }