@aws/nx-plugin 1.0.0-rc.96 → 1.0.0-rc.97

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 (159) hide show
  1. package/migrations.json +33 -3
  2. package/package.json +1 -1
  3. package/src/agentcore-gateway/__snapshots__/generator.spec.ts.snap +1 -1
  4. package/src/agentcore-gateway/generator.js +6 -0
  5. package/src/agentcore-gateway/generator.js.map +1 -1
  6. package/src/agentcore-gateway/react-connection/__snapshots__/generator.spec.ts.snap +4 -1
  7. package/src/agentcore-harness/__snapshots__/generator.spec.ts.snap +68 -4
  8. package/src/agentcore-harness/generator.js +6 -0
  9. package/src/agentcore-harness/generator.js.map +1 -1
  10. package/src/connection/gateway-runtime-config.js +1 -1
  11. package/src/connection/gateway-runtime-config.js.map +1 -1
  12. package/src/infra/app/__snapshots__/generator.spec.ts.snap +6 -6
  13. package/src/infra/app/generator.js +34 -7
  14. package/src/infra/app/generator.js.map +1 -1
  15. package/src/init/generator.d.ts +1 -1
  16. package/src/init/generator.js +8 -6
  17. package/src/init/generator.js.map +1 -1
  18. package/src/init/schema.d.js.map +1 -1
  19. package/src/init/schema.d.ts +1 -0
  20. package/src/init/schema.json +5 -0
  21. package/src/mcp-server/server.js +2 -0
  22. package/src/mcp-server/server.js.map +1 -1
  23. package/src/mcp-server/tools/best-practices.d.ts +28 -0
  24. package/src/mcp-server/tools/best-practices.js +43 -0
  25. package/src/mcp-server/tools/best-practices.js.map +1 -0
  26. package/src/mcp-server/tools/general-guidance.d.ts +1 -1
  27. package/src/mcp-server/tools/general-guidance.js +13 -4
  28. package/src/mcp-server/tools/general-guidance.js.map +1 -1
  29. package/src/migrations/latest/checkov-scan-cache-inputs/metadata.json +3 -0
  30. package/src/migrations/latest/checkov-scan-cache-inputs/migration.d.ts +6 -0
  31. package/src/migrations/latest/checkov-scan-cache-inputs/migration.js +58 -0
  32. package/src/migrations/latest/checkov-scan-cache-inputs/migration.js.map +1 -0
  33. package/src/migrations/latest/gateway-url-accessor/__snapshots__/migration.spec.ts.snap +84 -0
  34. package/src/migrations/latest/gateway-url-accessor/metadata.json +3 -0
  35. package/src/migrations/latest/gateway-url-accessor/migration.d.ts +6 -0
  36. package/src/migrations/latest/gateway-url-accessor/migration.js +94 -0
  37. package/src/migrations/latest/gateway-url-accessor/migration.js.map +1 -0
  38. package/src/migrations/latest/infra-deploy-express-mode/metadata.json +1 -1
  39. package/src/migrations/latest/infra-deploy-express-mode/migration.js +26 -28
  40. package/src/migrations/latest/infra-deploy-express-mode/migration.js.map +1 -1
  41. package/src/migrations/latest/py-lambda-powertools-context/metadata.json +3 -0
  42. package/src/migrations/latest/py-lambda-powertools-context/migration.d.ts +6 -0
  43. package/src/migrations/latest/py-lambda-powertools-context/migration.js +58 -0
  44. package/src/migrations/latest/py-lambda-powertools-context/migration.js.map +1 -0
  45. package/src/migrations/latest/script-project-quality-gates/metadata.json +3 -0
  46. package/src/migrations/latest/script-project-quality-gates/migration.d.ts +6 -0
  47. package/src/migrations/latest/script-project-quality-gates/migration.js +53 -0
  48. package/src/migrations/latest/script-project-quality-gates/migration.js.map +1 -0
  49. package/src/migrations/latest/smithy-extension-trait-aliases/__snapshots__/migration.spec.ts.snap +25 -0
  50. package/src/migrations/latest/smithy-extension-trait-aliases/metadata.json +3 -0
  51. package/src/migrations/latest/smithy-extension-trait-aliases/migration.d.ts +28 -0
  52. package/src/migrations/latest/smithy-extension-trait-aliases/migration.js +75 -0
  53. package/src/migrations/latest/smithy-extension-trait-aliases/migration.js.map +1 -0
  54. package/src/migrations/latest/terraform-validate-without-backend/metadata.json +3 -0
  55. package/src/migrations/latest/terraform-validate-without-backend/migration.d.ts +6 -0
  56. package/src/migrations/latest/terraform-validate-without-backend/migration.js +84 -0
  57. package/src/migrations/latest/terraform-validate-without-backend/migration.js.map +1 -0
  58. package/src/preset/generator.js +4 -25
  59. package/src/preset/generator.js.map +1 -1
  60. package/src/py/agent/a2a-connection/generator.d.ts +1 -1
  61. package/src/py/agent/gateway-connection/generator.d.ts +1 -1
  62. package/src/py/agent/mcp-connection/generator.d.ts +1 -1
  63. package/src/py/agent/react-connection/__snapshots__/generator.spec.ts.snap +4 -1
  64. package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +8 -10
  65. package/src/py/dynamodb/generator.js +34 -7
  66. package/src/py/dynamodb/generator.js.map +1 -1
  67. package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +2 -1
  68. package/src/py/lambda-function/files/handler/__lambdaFunctionSnakeCase__.py.template +2 -1
  69. package/src/py/project/schema.json +3 -1
  70. package/src/py/rdb/__snapshots__/generator.spec.ts.snap +28 -12
  71. package/src/py/rdb/files/Dockerfile.create-db-user.template +7 -3
  72. package/src/py/rdb/files/Dockerfile.migration.template +7 -3
  73. package/src/py/rdb/generator.js +29 -28
  74. package/src/py/rdb/generator.js.map +1 -1
  75. package/src/smithy/react-connection/files/model/extensions.smithy.template +3 -3
  76. package/src/smithy/ts/api/generator.js +7 -2
  77. package/src/smithy/ts/api/generator.js.map +1 -1
  78. package/src/terraform/project/generator.js +34 -10
  79. package/src/terraform/project/generator.js.map +1 -1
  80. package/src/trpc/backend/generator.js +7 -1
  81. package/src/trpc/backend/generator.js.map +1 -1
  82. package/src/trpc/react/generator.js +6 -0
  83. package/src/trpc/react/generator.js.map +1 -1
  84. package/src/ts/agent/generator.js +3 -3
  85. package/src/ts/agent/generator.js.map +1 -1
  86. package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +2 -0
  87. package/src/ts/dynamodb/generator.js +30 -6
  88. package/src/ts/dynamodb/generator.js.map +1 -1
  89. package/src/ts/lib/biome.d.ts +15 -1
  90. package/src/ts/lib/biome.js +79 -63
  91. package/src/ts/lib/biome.js.map +1 -1
  92. package/src/ts/lib/generator.js +11 -7
  93. package/src/ts/lib/generator.js.map +1 -1
  94. package/src/ts/lib/ts-project-utils.d.ts +14 -0
  95. package/src/ts/lib/ts-project-utils.js +24 -0
  96. package/src/ts/lib/ts-project-utils.js.map +1 -1
  97. package/src/ts/mcp-server/generator.js +3 -3
  98. package/src/ts/mcp-server/generator.js.map +1 -1
  99. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +5 -0
  100. package/src/ts/rdb/files/Dockerfile.template +5 -0
  101. package/src/ts/rdb/generator.d.ts +8 -0
  102. package/src/ts/rdb/generator.js +28 -24
  103. package/src/ts/rdb/generator.js.map +1 -1
  104. package/src/ts/rdb/trpc-connection/__snapshots__/generator.spec.ts.snap +39 -0
  105. package/src/ts/rdb/trpc-connection/generator.js +13 -0
  106. package/src/ts/rdb/trpc-connection/generator.js.map +1 -1
  107. package/src/ts/react-website/agui/files/common/src/components/__agentNameKebabCase__-chat.tsx.template +9 -0
  108. package/src/ts/react-website/agui/files/common/src/hooks/useAgui__agentNameClassName__.tsx.template +4 -1
  109. package/src/ts/react-website/agui/generator.js +6 -2
  110. package/src/ts/react-website/agui/generator.js.map +1 -1
  111. package/src/ts/react-website/app/generator.js +3 -8
  112. package/src/ts/react-website/app/generator.js.map +1 -1
  113. package/src/utils/agent-connection/agent-connection.d.ts +2 -1
  114. package/src/utils/agent-connection/agent-connection.js +6 -1
  115. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  116. package/src/utils/agent-core-constructs/files/cdk/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.ts.template +11 -7
  117. package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +14 -6
  118. package/src/utils/agent-core-packaging.js +5 -5
  119. package/src/utils/agent-core-packaging.js.map +1 -1
  120. package/src/utils/api-constructs/api-constructs.d.ts +5 -0
  121. package/src/utils/api-constructs/api-constructs.js +8 -0
  122. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  123. package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +4 -2
  124. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +4 -2
  125. package/src/utils/ast.d.ts +10 -0
  126. package/src/utils/ast.js +33 -0
  127. package/src/utils/ast.js.map +1 -1
  128. package/src/utils/docker.d.ts +11 -0
  129. package/src/utils/docker.js +16 -3
  130. package/src/utils/docker.js.map +1 -1
  131. package/src/utils/dynamodb-config.d.ts +48 -0
  132. package/src/utils/dynamodb-config.js +44 -0
  133. package/src/utils/dynamodb-config.js.map +1 -0
  134. package/src/utils/dynamodb-constructs/files/cdk/app/dynamodb/__nameKebabCase__.ts.template +8 -4
  135. package/src/utils/git-secrets.d.ts +28 -0
  136. package/src/utils/git-secrets.js +66 -0
  137. package/src/utils/git-secrets.js.map +1 -0
  138. package/src/utils/init.js +7 -6
  139. package/src/utils/init.js.map +1 -1
  140. package/src/utils/local-project-dependency.d.ts +28 -0
  141. package/src/utils/local-project-dependency.js +40 -0
  142. package/src/utils/local-project-dependency.js.map +1 -0
  143. package/src/utils/nx.d.ts +14 -0
  144. package/src/utils/nx.js +30 -0
  145. package/src/utils/nx.js.map +1 -1
  146. package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +11 -6
  147. package/src/utils/script-project-targets.d.ts +26 -0
  148. package/src/utils/script-project-targets.js +75 -0
  149. package/src/utils/script-project-targets.js.map +1 -0
  150. package/src/utils/versions.d.ts +3 -0
  151. package/src/utils/versions.js +7 -0
  152. package/src/utils/versions.js.map +1 -1
  153. package/src/utils/website-constructs/files/cdk/app/static-websites/__websiteNameKebabCase__.ts.template +8 -4
  154. package/src/py/dynamodb/files/__name__/__init__.py.template +0 -6
  155. package/src/py/dynamodb/files/__name__/entities/__init__.py.template +0 -4
  156. package/src/py/dynamodb/files/config.json.template +0 -24
  157. package/src/ts/dynamodb/files/config.json.template +0 -24
  158. package/src/ts/dynamodb/files/src/entities/index.ts.template +0 -1
  159. package/src/ts/dynamodb/files/src/index.ts.template +0 -2
package/migrations.json CHANGED
@@ -54,7 +54,7 @@
54
54
  },
55
55
  "latest-infra-deploy-express-mode": {
56
56
  "version": "1.0.0-rc.94",
57
- "description": "Deploy using CloudFormation express mode from the deploy and deploy-sandbox targets of ts#infra projects",
57
+ "description": "Deploy using CloudFormation express mode from the deploy-sandbox target of ts#infra projects, and wait for full stabilization from deploy",
58
58
  "implementation": "./src/migrations/latest/infra-deploy-express-mode/migration"
59
59
  },
60
60
  "latest-shx-fs-commands": {
@@ -87,6 +87,36 @@
87
87
  "description": "Move the shared shadcn package from a tsconfig paths alias to package.json imports/exports, matching the shadcn CLI's own monorepo resolution",
88
88
  "implementation": "./src/migrations/latest/shadcn-package-imports-exports/migration"
89
89
  },
90
+ "latest-gateway-url-accessor": {
91
+ "version": "1.0.0-rc.97",
92
+ "description": "Expose a non-optional gatewayUrl accessor on the vended AgentCoreGateway construct",
93
+ "implementation": "./src/migrations/latest/gateway-url-accessor/migration"
94
+ },
95
+ "latest-checkov-scan-cache-inputs": {
96
+ "version": "1.0.0-rc.97",
97
+ "description": "Scope the CDK infrastructure checkov target's cache inputs so the security scan cannot serve a stale pass",
98
+ "implementation": "./src/migrations/latest/checkov-scan-cache-inputs/migration"
99
+ },
100
+ "latest-terraform-validate-without-backend": {
101
+ "version": "1.0.0-rc.97",
102
+ "description": "Run the Terraform validate target with -backend=false so it works before bootstrap",
103
+ "implementation": "./src/migrations/latest/terraform-validate-without-backend/migration"
104
+ },
105
+ "latest-py-lambda-powertools-context": {
106
+ "version": "1.0.0-rc.97",
107
+ "description": "Add powertools Lambda context injection and cold start metrics to Python Lambda handlers",
108
+ "implementation": "./src/migrations/latest/py-lambda-powertools-context/migration"
109
+ },
110
+ "latest-smithy-extension-trait-aliases": {
111
+ "version": "1.0.0-rc.97",
112
+ "description": "Alias the extensions.smithy vendor-extension traits so Smithy emits x-query / x-mutation / x-cursor",
113
+ "implementation": "./src/migrations/latest/smithy-extension-trait-aliases/migration"
114
+ },
115
+ "latest-script-project-quality-gates": {
116
+ "version": "1.0.0-rc.97",
117
+ "description": "Add build, lint, format and typecheck targets plus a tsconfig.json to AgentCore Gateway and Harness projects",
118
+ "implementation": "./src/migrations/latest/script-project-quality-gates/migration"
119
+ },
90
120
  "v1.0.0-rc.50-0001-modernize-function-props-cast": {
91
121
  "version": "1.0.0-rc.50",
92
122
  "description": "Replace the legacy angle-bracket FunctionProps type assertion with the modern as syntax in generated API constructs",
@@ -328,7 +358,7 @@
328
358
  "implementation": "./src/migrations/v1.0.0-rc.89/0001-nx-parallel-default/migration"
329
359
  },
330
360
  "sync-vended-versions": {
331
- "version": "1.0.0-rc.96",
361
+ "version": "1.0.0-rc.97",
332
362
  "description": "Sync vended dependency versions and the tracked plugin version to those vended by this release",
333
363
  "implementation": "./src/utils/version-upgrade-migration/migration"
334
364
  }
@@ -401,7 +431,7 @@
401
431
  }
402
432
  },
403
433
  "nx-23.2.0-nx-packages": {
404
- "version": "1.0.0-rc.96",
434
+ "version": "1.0.0-rc.97",
405
435
  "packages": {
406
436
  "nx": {
407
437
  "version": "23.2.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws/nx-plugin",
3
- "version": "1.0.0-rc.96",
3
+ "version": "1.0.0-rc.97",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/awslabs/nx-plugin-for-aws.git",
@@ -336,7 +336,7 @@ export class MyGateway extends AgentCoreGateway {
336
336
  const rc = RuntimeConfig.ensure(this);
337
337
  rc.set('agentcore', 'gateways', {
338
338
  ...rc.get('agentcore').gateways,
339
- MyGateway: this.gateway.gatewayUrl,
339
+ MyGateway: this.gatewayUrl,
340
340
  });
341
341
  }
342
342
  }
@@ -14,6 +14,7 @@ import { getNpmScopePrefix } from "../utils/npm-scope.js";
14
14
  import { addGeneratorMetadata, getGeneratorInfo, projectExists, readProjectConfigurationUnqualified } from "../utils/nx.js";
15
15
  import { assignPort } from "../utils/port.js";
16
16
  import { ensureProjectPackageJson } from "../utils/project-package-json.js";
17
+ import { addScriptProjectTargets } from "../utils/script-project-targets.js";
17
18
  import { SHARED_CONSTRUCTS_DEPENDENCIES, sharedConstructsGenerator } from "../utils/shared-constructs.js";
18
19
  // The gateway's local-dev server needs these whatever the auth; only the MCP
19
20
  // SDK is protocol-specific (the http local gateway is a plain proxy).
@@ -117,6 +118,11 @@ export const agentcoreGatewayGenerator = async (tree, options)=>{
117
118
  project.targets ??= {};
118
119
  project.targets['serve'] ??= localGatewayTarget(port);
119
120
  project.targets['dev'] ??= localGatewayTarget(port);
121
+ // local-dev.ts is TypeScript the connection generators edit and the user is
122
+ // invited to tune, so it goes through the workspace's build sweep.
123
+ addScriptProjectTargets(tree, {
124
+ project
125
+ });
120
126
  updateProjectConfiguration(tree, project.name, project);
121
127
  // Scaffold the gateway project: local-dev.ts (+ Cedar policies if requested)
122
128
  generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'project', protocol), projectRoot, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/agentcore-gateway/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addProjectConfiguration,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n logger,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { addTsDependencies } from '../utils/add-dependencies.js';\nimport {\n AGENT_CORE_CONSTRUCTS_DEPENDENCIES,\n AGENT_CORE_CONSTRUCTS_PY_DEPENDENCIES,\n addAgentCoreGatewayInfra,\n} from '../utils/agent-core-constructs/agent-core-constructs.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../utils/format.js';\nimport { resolveIac } from '../utils/iac.js';\nimport { installDependencies } from '../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../utils/metrics.js';\nimport { kebabCase, toClassName } from '../utils/names.js';\nimport { getNpmScopePrefix } from '../utils/npm-scope.js';\nimport {\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n readProjectConfigurationUnqualified,\n} from '../utils/nx.js';\nimport { assignPort } from '../utils/port.js';\nimport { ensureProjectPackageJson } from '../utils/project-package-json.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../utils/shared-constructs.js';\nimport type { IacMetadata } from '../utils/shared-constructs-constants.js';\nimport type { AgentcoreGatewayGeneratorSchema } from './schema';\n\n// The gateway's local-dev server needs these whatever the auth; only the MCP\n// SDK is protocol-specific (the http local gateway is a plain proxy).\nexport const DEPENDENCIES = declareDependencies<AgentCoreGatewayMetadata>()({\n ts: [\n { name: '@modelcontextprotocol/sdk', when: (m) => m.protocol === 'mcp' },\n { name: 'express' },\n { name: '@types/express', dev: true },\n // local-dev.ts runs via tsx, which is shared tooling.\n { name: 'tsx', dev: true, root: true },\n ...ownedElsewhere(AGENT_CORE_CONSTRUCTS_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n py: ownedElsewhere(AGENT_CORE_CONSTRUCTS_PY_DEPENDENCIES),\n});\n\nexport const AGENTCORE_GATEWAY_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\nexport const agentcoreGatewayGenerator = async (\n tree: Tree,\n options: AgentcoreGatewayGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const name = kebabCase(options.name);\n const nameClassName = toClassName(name);\n const parentDir = options.directory ?? 'packages';\n const subDir = options.subDirectory ?? name;\n const projectRoot = joinPathFragments(parentDir, subDir);\n const fullyQualifiedName = `${getNpmScopePrefix(tree)}${name}`;\n\n // Protocol is mcp (aggregate MCP server targets into one MCP endpoint) or\n // http (proxy agent runtime targets via path-based routing). Persisted in\n // metadata so connection generators can validate it.\n const protocol = options.protocol ?? 'mcp';\n // Inbound auth is iam (default) or cognito. Persisted in metadata so\n // connection generators can validate it (agent -> gateway connections\n // require an IAM gateway).\n const auth = options.auth ?? 'iam';\n // Cedar policies authorize MCP tool actions, which an http gateway has none\n // of — its runtime targets are plain proxied endpoints — so the policy\n // engine only applies to mcp gateways. cedarPolicy defaults to true in the\n // schema, so an http gateway quietly drops it rather than requiring\n // --cedarPolicy=false.\n if (protocol === 'http' && options.cedarPolicy) {\n logger.warn(\n 'Cedar policies authorize MCP tool actions, so cedarPolicy is ignored for http-protocol gateways.',\n );\n }\n const cedarPolicy = protocol === 'mcp' && (options.cedarPolicy ?? true);\n const infra = options.infra ?? 'agentcore';\n\n // local-dev.ts is the local gateway: a continuous MCP aggregator chaining\n // onto attached MCP servers' dev targets (added by the mcp-connection\n // generator), so a single `nx dev <gateway>` boots the gateway and every\n // attached MCP server together.\n //\n // `serve` exists for parity with other generators; the deployed Gateway is\n // a managed AWS resource, so `serve`-mode agents talk to it via runtime\n // config and the local gateway sits idle.\n const localGatewayTarget = (port: number) => ({\n executor: 'nx:run-commands' as const,\n continuous: true,\n options: {\n command: 'tsx local-dev.ts',\n cwd: '{projectRoot}',\n env: { PORT: `${port}` },\n },\n dependsOn: [] as Array<string | { projects: string[]; target: string }>,\n });\n let project: ProjectConfiguration;\n if (projectExists(tree, fullyQualifiedName)) {\n project = readProjectConfigurationUnqualified(tree, fullyQualifiedName);\n } else {\n addProjectConfiguration(tree, fullyQualifiedName, {\n name: fullyQualifiedName,\n root: projectRoot,\n projectType: 'library',\n sourceRoot: projectRoot,\n tags: [],\n targets: {},\n metadata: {\n generator: AGENTCORE_GATEWAY_GENERATOR_INFO.id,\n } as any,\n });\n project = readProjectConfigurationUnqualified(tree, fullyQualifiedName);\n }\n // Ensure the project has its own package.json so its runtime dependencies\n // (added below) are declared in it rather than the workspace root.\n ensureProjectPackageJson(tree, {\n dir: projectRoot,\n fullyQualifiedName,\n });\n const port = assignPort(tree, project, 8100);\n // A gateway is its own standalone project, so it uses plain `serve` / `dev`\n // targets. Re-run: keep existing targets (their dependsOn may have been\n // populated by the mcp-connection generator), just ensure both exist.\n project.targets ??= {};\n project.targets['serve'] ??= localGatewayTarget(port);\n project.targets['dev'] ??= localGatewayTarget(port);\n updateProjectConfiguration(tree, project.name, project);\n\n // Scaffold the gateway project: local-dev.ts (+ Cedar policies if requested)\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'project', protocol),\n projectRoot,\n {\n nameClassName,\n nameKebabCase: name,\n port,\n attachedMcpServers: [],\n attachedAgents: [],\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n if (cedarPolicy) {\n // The default permit-all policy differs by auth type: AgentCore represents\n // IAM callers as `AgentCore::IamEntity` and Cognito/JWT callers as\n // `AgentCore::OAuthUser`, so the two policies match different principals.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'cedar'),\n projectRoot,\n { nameClassName, auth },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n }\n\n // Recorded in the metadata below so the version sync can tell a CDK\n // project from a Terraform one; undefined when no infrastructure was\n // generated, in which case neither provider's packages were added.\n const iac =\n infra !== 'none' ? await resolveIac(tree, options.iac) : undefined;\n\n // Recorded below and read by the declaration's predicates, so the packages\n // added here are exactly the ones the version sync will own.\n const metadata: AgentCoreGatewayMetadata = {\n name,\n rc: nameClassName,\n protocol,\n auth,\n port,\n ...(iac ? { iac } : {}),\n };\n\n addGeneratorMetadata(\n tree,\n fullyQualifiedName,\n AGENTCORE_GATEWAY_GENERATOR_INFO,\n metadata,\n );\n\n addTsDependencies(tree, DEPENDENCIES, { metadata, projectRoot });\n\n // Wire up infra (CDK or Terraform); re-running with infra=agentcore adds\n // the infrastructure to a previously infra-less gateway.\n\n if (infra === 'agentcore') {\n await sharedConstructsGenerator(tree, { iac }, DEPENDENCIES);\n\n await addAgentCoreGatewayInfra(\n tree,\n {\n gatewayNameClassName: nameClassName,\n gatewayNameKebabCase: name,\n projectName: fullyQualifiedName,\n projectDirectory: projectRoot,\n cedarPolicy,\n auth,\n protocol,\n iac,\n },\n DEPENDENCIES,\n );\n }\n\n await addGeneratorMetricsIfApplicable(tree, [\n AGENTCORE_GATEWAY_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\n/**\n * Gateway details stored in the gateway project's metadata.\n */\nexport interface AgentCoreGatewayMetadata extends IacMetadata {\n name: string;\n rc: string;\n protocol: string;\n auth: string;\n port: number;\n}\n\n/**\n * Read a gateway project's metadata, validating it was generated by the\n * agentcore-gateway generator.\n */\nexport const readAgentCoreGatewayMetadata = (\n project: ProjectConfiguration,\n): AgentCoreGatewayMetadata => {\n const metadata = project.metadata as any;\n if (metadata?.generator !== AGENTCORE_GATEWAY_GENERATOR_INFO.id) {\n throw new Error(\n `Project '${project.name}' was not generated by the '${AGENTCORE_GATEWAY_GENERATOR_INFO.id}' generator.`,\n );\n }\n return metadata as AgentCoreGatewayMetadata;\n};\n\nexport default agentcoreGatewayGenerator;\n"],"names":["addProjectConfiguration","generateFiles","joinPathFragments","logger","OverwriteStrategy","updateProjectConfiguration","addTsDependencies","AGENT_CORE_CONSTRUCTS_DEPENDENCIES","AGENT_CORE_CONSTRUCTS_PY_DEPENDENCIES","addAgentCoreGatewayInfra","declareDependencies","ownedElsewhere","formatFilesInSubtree","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","getNpmScopePrefix","addGeneratorMetadata","getGeneratorInfo","projectExists","readProjectConfigurationUnqualified","assignPort","ensureProjectPackageJson","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","DEPENDENCIES","ts","name","when","m","protocol","dev","root","py","AGENTCORE_GATEWAY_GENERATOR_INFO","filename","agentcoreGatewayGenerator","tree","options","nameClassName","parentDir","directory","subDir","subDirectory","projectRoot","fullyQualifiedName","auth","cedarPolicy","warn","infra","localGatewayTarget","port","executor","continuous","command","cwd","env","PORT","dependsOn","project","projectType","sourceRoot","tags","targets","metadata","generator","id","dir","dirname","nameKebabCase","attachedMcpServers","attachedAgents","overwriteStrategy","KeepExisting","iac","undefined","rc","gatewayNameClassName","gatewayNameKebabCase","projectName","projectDirectory","preferInstallDependencies","languages","readAgentCoreGatewayMetadata","Error"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/agentcore-gateway/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addProjectConfiguration,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n logger,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { addTsDependencies } from '../utils/add-dependencies.js';\nimport {\n AGENT_CORE_CONSTRUCTS_DEPENDENCIES,\n AGENT_CORE_CONSTRUCTS_PY_DEPENDENCIES,\n addAgentCoreGatewayInfra,\n} from '../utils/agent-core-constructs/agent-core-constructs.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../utils/format.js';\nimport { resolveIac } from '../utils/iac.js';\nimport { installDependencies } from '../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../utils/metrics.js';\nimport { kebabCase, toClassName } from '../utils/names.js';\nimport { getNpmScopePrefix } from '../utils/npm-scope.js';\nimport {\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n readProjectConfigurationUnqualified,\n} from '../utils/nx.js';\nimport { assignPort } from '../utils/port.js';\nimport { ensureProjectPackageJson } from '../utils/project-package-json.js';\nimport { addScriptProjectTargets } from '../utils/script-project-targets.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../utils/shared-constructs.js';\nimport type { IacMetadata } from '../utils/shared-constructs-constants.js';\nimport type { AgentcoreGatewayGeneratorSchema } from './schema';\n\n// The gateway's local-dev server needs these whatever the auth; only the MCP\n// SDK is protocol-specific (the http local gateway is a plain proxy).\nexport const DEPENDENCIES = declareDependencies<AgentCoreGatewayMetadata>()({\n ts: [\n { name: '@modelcontextprotocol/sdk', when: (m) => m.protocol === 'mcp' },\n { name: 'express' },\n { name: '@types/express', dev: true },\n // local-dev.ts runs via tsx, which is shared tooling.\n { name: 'tsx', dev: true, root: true },\n ...ownedElsewhere(AGENT_CORE_CONSTRUCTS_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n py: ownedElsewhere(AGENT_CORE_CONSTRUCTS_PY_DEPENDENCIES),\n});\n\nexport const AGENTCORE_GATEWAY_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\nexport const agentcoreGatewayGenerator = async (\n tree: Tree,\n options: AgentcoreGatewayGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const name = kebabCase(options.name);\n const nameClassName = toClassName(name);\n const parentDir = options.directory ?? 'packages';\n const subDir = options.subDirectory ?? name;\n const projectRoot = joinPathFragments(parentDir, subDir);\n const fullyQualifiedName = `${getNpmScopePrefix(tree)}${name}`;\n\n // Protocol is mcp (aggregate MCP server targets into one MCP endpoint) or\n // http (proxy agent runtime targets via path-based routing). Persisted in\n // metadata so connection generators can validate it.\n const protocol = options.protocol ?? 'mcp';\n // Inbound auth is iam (default) or cognito. Persisted in metadata so\n // connection generators can validate it (agent -> gateway connections\n // require an IAM gateway).\n const auth = options.auth ?? 'iam';\n // Cedar policies authorize MCP tool actions, which an http gateway has none\n // of — its runtime targets are plain proxied endpoints — so the policy\n // engine only applies to mcp gateways. cedarPolicy defaults to true in the\n // schema, so an http gateway quietly drops it rather than requiring\n // --cedarPolicy=false.\n if (protocol === 'http' && options.cedarPolicy) {\n logger.warn(\n 'Cedar policies authorize MCP tool actions, so cedarPolicy is ignored for http-protocol gateways.',\n );\n }\n const cedarPolicy = protocol === 'mcp' && (options.cedarPolicy ?? true);\n const infra = options.infra ?? 'agentcore';\n\n // local-dev.ts is the local gateway: a continuous MCP aggregator chaining\n // onto attached MCP servers' dev targets (added by the mcp-connection\n // generator), so a single `nx dev <gateway>` boots the gateway and every\n // attached MCP server together.\n //\n // `serve` exists for parity with other generators; the deployed Gateway is\n // a managed AWS resource, so `serve`-mode agents talk to it via runtime\n // config and the local gateway sits idle.\n const localGatewayTarget = (port: number) => ({\n executor: 'nx:run-commands' as const,\n continuous: true,\n options: {\n command: 'tsx local-dev.ts',\n cwd: '{projectRoot}',\n env: { PORT: `${port}` },\n },\n dependsOn: [] as Array<string | { projects: string[]; target: string }>,\n });\n let project: ProjectConfiguration;\n if (projectExists(tree, fullyQualifiedName)) {\n project = readProjectConfigurationUnqualified(tree, fullyQualifiedName);\n } else {\n addProjectConfiguration(tree, fullyQualifiedName, {\n name: fullyQualifiedName,\n root: projectRoot,\n projectType: 'library',\n sourceRoot: projectRoot,\n tags: [],\n targets: {},\n metadata: {\n generator: AGENTCORE_GATEWAY_GENERATOR_INFO.id,\n } as any,\n });\n project = readProjectConfigurationUnqualified(tree, fullyQualifiedName);\n }\n // Ensure the project has its own package.json so its runtime dependencies\n // (added below) are declared in it rather than the workspace root.\n ensureProjectPackageJson(tree, {\n dir: projectRoot,\n fullyQualifiedName,\n });\n const port = assignPort(tree, project, 8100);\n // A gateway is its own standalone project, so it uses plain `serve` / `dev`\n // targets. Re-run: keep existing targets (their dependsOn may have been\n // populated by the mcp-connection generator), just ensure both exist.\n project.targets ??= {};\n project.targets['serve'] ??= localGatewayTarget(port);\n project.targets['dev'] ??= localGatewayTarget(port);\n // local-dev.ts is TypeScript the connection generators edit and the user is\n // invited to tune, so it goes through the workspace's build sweep.\n addScriptProjectTargets(tree, { project });\n updateProjectConfiguration(tree, project.name, project);\n\n // Scaffold the gateway project: local-dev.ts (+ Cedar policies if requested)\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'project', protocol),\n projectRoot,\n {\n nameClassName,\n nameKebabCase: name,\n port,\n attachedMcpServers: [],\n attachedAgents: [],\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n if (cedarPolicy) {\n // The default permit-all policy differs by auth type: AgentCore represents\n // IAM callers as `AgentCore::IamEntity` and Cognito/JWT callers as\n // `AgentCore::OAuthUser`, so the two policies match different principals.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'cedar'),\n projectRoot,\n { nameClassName, auth },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n }\n\n // Recorded in the metadata below so the version sync can tell a CDK\n // project from a Terraform one; undefined when no infrastructure was\n // generated, in which case neither provider's packages were added.\n const iac =\n infra !== 'none' ? await resolveIac(tree, options.iac) : undefined;\n\n // Recorded below and read by the declaration's predicates, so the packages\n // added here are exactly the ones the version sync will own.\n const metadata: AgentCoreGatewayMetadata = {\n name,\n rc: nameClassName,\n protocol,\n auth,\n port,\n ...(iac ? { iac } : {}),\n };\n\n addGeneratorMetadata(\n tree,\n fullyQualifiedName,\n AGENTCORE_GATEWAY_GENERATOR_INFO,\n metadata,\n );\n\n addTsDependencies(tree, DEPENDENCIES, { metadata, projectRoot });\n\n // Wire up infra (CDK or Terraform); re-running with infra=agentcore adds\n // the infrastructure to a previously infra-less gateway.\n\n if (infra === 'agentcore') {\n await sharedConstructsGenerator(tree, { iac }, DEPENDENCIES);\n\n await addAgentCoreGatewayInfra(\n tree,\n {\n gatewayNameClassName: nameClassName,\n gatewayNameKebabCase: name,\n projectName: fullyQualifiedName,\n projectDirectory: projectRoot,\n cedarPolicy,\n auth,\n protocol,\n iac,\n },\n DEPENDENCIES,\n );\n }\n\n await addGeneratorMetricsIfApplicable(tree, [\n AGENTCORE_GATEWAY_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\n/**\n * Gateway details stored in the gateway project's metadata.\n */\nexport interface AgentCoreGatewayMetadata extends IacMetadata {\n name: string;\n rc: string;\n protocol: string;\n auth: string;\n port: number;\n}\n\n/**\n * Read a gateway project's metadata, validating it was generated by the\n * agentcore-gateway generator.\n */\nexport const readAgentCoreGatewayMetadata = (\n project: ProjectConfiguration,\n): AgentCoreGatewayMetadata => {\n const metadata = project.metadata as any;\n if (metadata?.generator !== AGENTCORE_GATEWAY_GENERATOR_INFO.id) {\n throw new Error(\n `Project '${project.name}' was not generated by the '${AGENTCORE_GATEWAY_GENERATOR_INFO.id}' generator.`,\n );\n }\n return metadata as AgentCoreGatewayMetadata;\n};\n\nexport default agentcoreGatewayGenerator;\n"],"names":["addProjectConfiguration","generateFiles","joinPathFragments","logger","OverwriteStrategy","updateProjectConfiguration","addTsDependencies","AGENT_CORE_CONSTRUCTS_DEPENDENCIES","AGENT_CORE_CONSTRUCTS_PY_DEPENDENCIES","addAgentCoreGatewayInfra","declareDependencies","ownedElsewhere","formatFilesInSubtree","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","getNpmScopePrefix","addGeneratorMetadata","getGeneratorInfo","projectExists","readProjectConfigurationUnqualified","assignPort","ensureProjectPackageJson","addScriptProjectTargets","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","DEPENDENCIES","ts","name","when","m","protocol","dev","root","py","AGENTCORE_GATEWAY_GENERATOR_INFO","filename","agentcoreGatewayGenerator","tree","options","nameClassName","parentDir","directory","subDir","subDirectory","projectRoot","fullyQualifiedName","auth","cedarPolicy","warn","infra","localGatewayTarget","port","executor","continuous","command","cwd","env","PORT","dependsOn","project","projectType","sourceRoot","tags","targets","metadata","generator","id","dir","dirname","nameKebabCase","attachedMcpServers","attachedAgents","overwriteStrategy","KeepExisting","iac","undefined","rc","gatewayNameClassName","gatewayNameKebabCase","projectName","projectDirectory","preferInstallDependencies","languages","readAgentCoreGatewayMetadata","Error"],"mappings":"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"}
@@ -51,6 +51,9 @@ class SigV4HttpAgent extends HttpAgent {
51
51
  }
52
52
  }
53
53
 
54
+ // The id this agent is registered under, used as \`agentId\` by CopilotKit components.
55
+ export const MY_AGENT_ID = 'my-agent';
56
+
54
57
  export const useAguiMyAgent = (): Record<string, AbstractAgent> => {
55
58
  const runtimeConfig = useRuntimeConfig();
56
59
  const gatewayUrl = runtimeConfig.gateways.MyGateway;
@@ -61,7 +64,7 @@ export const useAguiMyAgent = (): Record<string, AbstractAgent> => {
61
64
  return useMemo((): Record<string, AbstractAgent> => {
62
65
  const agent = new SigV4HttpAgent({ url }, sigv4);
63
66
 
64
- return { 'my-agent': agent };
67
+ return { [MY_AGENT_ID]: agent };
65
68
  }, [url, sigv4]);
66
69
  };
67
70
  "
@@ -1,6 +1,6 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`agentcore-harness generator > snapshot > snapshots the four rendered harness project files > packages/my-harness/README.md 1`] = `
3
+ exports[`agentcore-harness generator > snapshot > snapshots the rendered harness project files > packages/my-harness/README.md 1`] = `
4
4
  "# @proj/my-harness
5
5
 
6
6
  An [Amazon Bedrock AgentCore Harness](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness.html)
@@ -86,7 +86,7 @@ files and to \`src/PROMPT.md\` are preserved.
86
86
  "
87
87
  `;
88
88
 
89
- exports[`agentcore-harness generator > snapshot > snapshots the four rendered harness project files > packages/my-harness/project.json 1`] = `
89
+ exports[`agentcore-harness generator > snapshot > snapshots the rendered harness project files > packages/my-harness/project.json 1`] = `
90
90
  "{
91
91
  "name": "@proj/my-harness",
92
92
  "$schema": "../../node_modules/nx/schemas/project-schema.json",
@@ -101,19 +101,64 @@ exports[`agentcore-harness generator > snapshot > snapshots the four rendered ha
101
101
  "iac": "cdk"
102
102
  },
103
103
  "targets": {
104
+ "build": {
105
+ "dependsOn": ["lint", "typecheck"]
106
+ },
104
107
  "chat": {
105
108
  "executor": "nx:run-commands",
106
109
  "options": {
107
110
  "commands": ["tsx ./scripts/chat.ts"],
108
111
  "cwd": "{projectRoot}"
109
112
  }
113
+ },
114
+ "format": {
115
+ "executor": "nx:run-commands",
116
+ "cache": true,
117
+ "inputs": ["biome"],
118
+ "options": {
119
+ "command": "biome format {projectRoot}"
120
+ },
121
+ "configurations": {
122
+ "fix": {
123
+ "command": "biome format --write {projectRoot}"
124
+ },
125
+ "skip-lint": {
126
+ "command": "node -e \\"\\""
127
+ }
128
+ }
129
+ },
130
+ "lint": {
131
+ "executor": "nx:run-commands",
132
+ "cache": true,
133
+ "inputs": ["biome"],
134
+ "dependsOn": ["format"],
135
+ "options": {
136
+ "command": "biome lint {projectRoot}"
137
+ },
138
+ "configurations": {
139
+ "fix": {
140
+ "command": "biome check --write {projectRoot}"
141
+ },
142
+ "skip-lint": {
143
+ "command": "node -e \\"\\""
144
+ }
145
+ }
146
+ },
147
+ "typecheck": {
148
+ "executor": "nx:run-commands",
149
+ "cache": true,
150
+ "inputs": ["default", "^default"],
151
+ "options": {
152
+ "command": "tsc --noEmit -p tsconfig.json",
153
+ "cwd": "{projectRoot}"
154
+ }
110
155
  }
111
156
  }
112
157
  }
113
158
  "
114
159
  `;
115
160
 
116
- exports[`agentcore-harness generator > snapshot > snapshots the four rendered harness project files > packages/my-harness/scripts/chat.ts 1`] = `
161
+ exports[`agentcore-harness generator > snapshot > snapshots the rendered harness project files > packages/my-harness/scripts/chat.ts 1`] = `
117
162
  "// Chat CLI for MyHarness. Invokes the deployed Harness with InvokeHarness.
118
163
  import { randomUUID } from 'node:crypto';
119
164
  import { getAppConfig } from '@aws-lambda-powertools/parameters/appconfig';
@@ -216,7 +261,7 @@ await chatLoop(new HarnessAdapter(), '');
216
261
  "
217
262
  `;
218
263
 
219
- exports[`agentcore-harness generator > snapshot > snapshots the four rendered harness project files > packages/my-harness/src/PROMPT.md 1`] = `
264
+ exports[`agentcore-harness generator > snapshot > snapshots the rendered harness project files > packages/my-harness/src/PROMPT.md 1`] = `
220
265
  "# MyHarness
221
266
 
222
267
  You are a helpful AI assistant.
@@ -235,3 +280,22 @@ When tools are available, prefer them over recollection for anything you can
235
280
  look up, and report what a tool returned, including when it fails.
236
281
  "
237
282
  `;
283
+
284
+ exports[`agentcore-harness generator > snapshot > snapshots the rendered harness project files > packages/my-harness/tsconfig.json 1`] = `
285
+ "{
286
+ "extends": "../../tsconfig.base.json",
287
+ "compilerOptions": {
288
+ "composite": false,
289
+ "declarationMap": false,
290
+ "emitDeclarationOnly": false,
291
+ "noEmit": true,
292
+ "types": [
293
+ "node"
294
+ ]
295
+ },
296
+ "include": [
297
+ "**/*.ts"
298
+ ]
299
+ }
300
+ "
301
+ `;
@@ -12,6 +12,7 @@ import { addGeneratorMetricsIfApplicable } from "../utils/metrics.js";
12
12
  import { kebabCase, toClassName } from "../utils/names.js";
13
13
  import { getNpmScopePrefix } from "../utils/npm-scope.js";
14
14
  import { addGeneratorMetadata, getGeneratorInfo, projectExists, readProjectConfigurationUnqualified } from "../utils/nx.js";
15
+ import { addScriptProjectTargets } from "../utils/script-project-targets.js";
15
16
  import { SHARED_CONSTRUCTS_DEPENDENCIES, sharedConstructsGenerator } from "../utils/shared-constructs.js";
16
17
  // scripts/chat.ts needs all of these whatever the infrastructure choice, so no
17
18
  // entry is conditional. The harness project holds no manifest of its own, so
@@ -91,6 +92,11 @@ export const agentcoreHarnessGenerator = async (tree, options)=>{
91
92
  cwd: '{projectRoot}'
92
93
  }
93
94
  };
95
+ // scripts/chat.ts is TypeScript the user runs and customises, so it goes
96
+ // through the workspace's build sweep.
97
+ addScriptProjectTargets(tree, {
98
+ project
99
+ });
94
100
  updateProjectConfiguration(tree, project.name, project);
95
101
  generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'project'), projectRoot, {
96
102
  nameClassName,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/agentcore-harness/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addProjectConfiguration,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { addTsDependencies } from '../utils/add-dependencies.js';\nimport { addAgentCoreHarnessInfra } from '../utils/agent-core-constructs/agent-core-constructs.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../utils/format.js';\nimport { resolveIac } from '../utils/iac.js';\nimport { installDependencies } from '../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../utils/metrics.js';\nimport { kebabCase, toClassName } from '../utils/names.js';\nimport { getNpmScopePrefix } from '../utils/npm-scope.js';\nimport {\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n readProjectConfigurationUnqualified,\n} from '../utils/nx.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../utils/shared-constructs.js';\nimport type { IacMetadata } from '../utils/shared-constructs-constants.js';\nimport type { AgentcoreHarnessGeneratorSchema } from './schema';\n\n// scripts/chat.ts needs all of these whatever the infrastructure choice, so no\n// entry is conditional. The harness project holds no manifest of its own, so\n// every entry is declared against the workspace root.\nexport const DEPENDENCIES = declareDependencies<AgentCoreHarnessMetadata>()({\n ts: [\n { name: '@aws-sdk/client-bedrock-agentcore', root: true },\n { name: '@aws-sdk/client-appconfigdata', root: true },\n { name: '@aws-lambda-powertools/parameters', root: true },\n { name: 'agent-chat-cli', root: true },\n // tsx runs the chat script via the `chat` target; both are shared tooling.\n { name: '@types/node', dev: true, root: true },\n { name: 'tsx', dev: true, root: true },\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n});\n\nexport const AGENTCORE_HARNESS_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\nexport const agentcoreHarnessGenerator = async (\n tree: Tree,\n options: AgentcoreHarnessGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const nameKebabCase = kebabCase(options.name);\n const nameClassName = toClassName(nameKebabCase);\n const parentDir = options.directory ?? 'packages';\n const subDir = options.subDirectory ?? nameKebabCase;\n const projectRoot = joinPathFragments(parentDir, subDir);\n const fullyQualifiedProjectName = `${getNpmScopePrefix(tree)}${nameKebabCase}`;\n const infra = options.infra ?? 'agentcore';\n\n // AgentCore harness names must start with an ASCII letter and stay within 40\n // characters once the \"_<8 hex>\" suffix is appended, so cap the prefix at 31.\n // toClassName prefixes `_` (not a letter) for digit-leading names.\n const harnessNamePrefix = (\n /^[A-Za-z]/.test(nameClassName) ? nameClassName : `H${nameClassName}`\n ).slice(0, 31);\n\n // Reuse an existing project configuration; create it otherwise.\n let project: ProjectConfiguration;\n if (projectExists(tree, fullyQualifiedProjectName)) {\n project = readProjectConfigurationUnqualified(\n tree,\n fullyQualifiedProjectName,\n );\n } else {\n addProjectConfiguration(tree, fullyQualifiedProjectName, {\n name: fullyQualifiedProjectName,\n root: projectRoot,\n projectType: 'application',\n sourceRoot: projectRoot,\n tags: [],\n targets: {},\n metadata: {\n generator: AGENTCORE_HARNESS_GENERATOR_INFO.id,\n } as any,\n });\n project = readProjectConfigurationUnqualified(\n tree,\n fullyQualifiedProjectName,\n );\n }\n\n // `chat` runs the vended chat script against the deployed Harness. Re-run:\n // keep an existing target so user edits survive.\n project.targets ??= {};\n project.targets['chat'] ??= {\n executor: 'nx:run-commands',\n options: {\n commands: ['tsx ./scripts/chat.ts'],\n cwd: '{projectRoot}',\n },\n };\n updateProjectConfiguration(tree, project.name, project);\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'project'),\n projectRoot,\n {\n nameClassName,\n nameKebabCase,\n fullyQualifiedName: fullyQualifiedProjectName,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // Resolved before the metadata write because the recorded value is what the\n // declaration's predicates read; undefined when no infrastructure is written,\n // in which case neither provider's packages were added.\n const iac =\n infra === 'agentcore' ? await resolveIac(tree, options.iac) : undefined;\n\n // Record only what cannot drift once the user owns the generated\n // infrastructure: the project identity, its runtime config key, its auth mode\n // and which provider's infrastructure was written.\n const metadata: Omit<AgentCoreHarnessMetadata, 'generator'> = {\n name: nameKebabCase,\n rc: nameClassName,\n auth: 'iam',\n ...(iac ? { iac } : {}),\n };\n\n addGeneratorMetadata(\n tree,\n fullyQualifiedProjectName,\n AGENTCORE_HARNESS_GENERATOR_INFO,\n metadata,\n );\n\n // scripts/chat.ts dependencies; tsx runs it via the `chat` target.\n addTsDependencies(tree, DEPENDENCIES, { metadata });\n\n // Harness infrastructure is written only for `infra: agentcore`. A later\n // `infra: agentcore` rerun adds it without replacing project files.\n if (iac) {\n await sharedConstructsGenerator(tree, { iac }, DEPENDENCIES);\n await addAgentCoreHarnessInfra(tree, {\n harnessNameClassName: nameClassName,\n harnessNameKebabCase: nameKebabCase,\n projectRoot,\n harnessNamePrefix,\n iac,\n });\n }\n\n await addGeneratorMetricsIfApplicable(tree, [\n AGENTCORE_HARNESS_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\n/**\n * Harness details stored in the Harness Project's metadata. `iac` records which\n * provider's infrastructure was written, so the version sync can tell which\n * shared constructs packages this project owns.\n */\nexport interface AgentCoreHarnessMetadata extends IacMetadata {\n generator: string;\n name: string;\n rc: string;\n auth: 'iam';\n}\n\n/**\n * Read a Harness Project's metadata, validating it was generated by the\n * agentcore-harness generator before returning typed data.\n */\nexport const readAgentCoreHarnessMetadata = (\n project: ProjectConfiguration,\n): AgentCoreHarnessMetadata => {\n const metadata = project.metadata as any;\n if (metadata?.generator !== AGENTCORE_HARNESS_GENERATOR_INFO.id) {\n throw new Error(\n `Project '${project.name}' was not generated by the '${AGENTCORE_HARNESS_GENERATOR_INFO.id}' generator.`,\n );\n }\n return metadata as AgentCoreHarnessMetadata;\n};\n\nexport default agentcoreHarnessGenerator;\n"],"names":["addProjectConfiguration","generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","addTsDependencies","addAgentCoreHarnessInfra","declareDependencies","ownedElsewhere","formatFilesInSubtree","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","getNpmScopePrefix","addGeneratorMetadata","getGeneratorInfo","projectExists","readProjectConfigurationUnqualified","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","DEPENDENCIES","ts","name","root","dev","AGENTCORE_HARNESS_GENERATOR_INFO","filename","agentcoreHarnessGenerator","tree","options","nameKebabCase","nameClassName","parentDir","directory","subDir","subDirectory","projectRoot","fullyQualifiedProjectName","infra","harnessNamePrefix","test","slice","project","projectType","sourceRoot","tags","targets","metadata","generator","id","executor","commands","cwd","dirname","fullyQualifiedName","overwriteStrategy","KeepExisting","iac","undefined","rc","auth","harnessNameClassName","harnessNameKebabCase","preferInstallDependencies","languages","readAgentCoreHarnessMetadata","Error"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/agentcore-harness/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addProjectConfiguration,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { addTsDependencies } from '../utils/add-dependencies.js';\nimport { addAgentCoreHarnessInfra } from '../utils/agent-core-constructs/agent-core-constructs.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../utils/format.js';\nimport { resolveIac } from '../utils/iac.js';\nimport { installDependencies } from '../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../utils/metrics.js';\nimport { kebabCase, toClassName } from '../utils/names.js';\nimport { getNpmScopePrefix } from '../utils/npm-scope.js';\nimport {\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n readProjectConfigurationUnqualified,\n} from '../utils/nx.js';\nimport { addScriptProjectTargets } from '../utils/script-project-targets.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../utils/shared-constructs.js';\nimport type { IacMetadata } from '../utils/shared-constructs-constants.js';\nimport type { AgentcoreHarnessGeneratorSchema } from './schema';\n\n// scripts/chat.ts needs all of these whatever the infrastructure choice, so no\n// entry is conditional. The harness project holds no manifest of its own, so\n// every entry is declared against the workspace root.\nexport const DEPENDENCIES = declareDependencies<AgentCoreHarnessMetadata>()({\n ts: [\n { name: '@aws-sdk/client-bedrock-agentcore', root: true },\n { name: '@aws-sdk/client-appconfigdata', root: true },\n { name: '@aws-lambda-powertools/parameters', root: true },\n { name: 'agent-chat-cli', root: true },\n // tsx runs the chat script via the `chat` target; both are shared tooling.\n { name: '@types/node', dev: true, root: true },\n { name: 'tsx', dev: true, root: true },\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n});\n\nexport const AGENTCORE_HARNESS_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\nexport const agentcoreHarnessGenerator = async (\n tree: Tree,\n options: AgentcoreHarnessGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const nameKebabCase = kebabCase(options.name);\n const nameClassName = toClassName(nameKebabCase);\n const parentDir = options.directory ?? 'packages';\n const subDir = options.subDirectory ?? nameKebabCase;\n const projectRoot = joinPathFragments(parentDir, subDir);\n const fullyQualifiedProjectName = `${getNpmScopePrefix(tree)}${nameKebabCase}`;\n const infra = options.infra ?? 'agentcore';\n\n // AgentCore harness names must start with an ASCII letter and stay within 40\n // characters once the \"_<8 hex>\" suffix is appended, so cap the prefix at 31.\n // toClassName prefixes `_` (not a letter) for digit-leading names.\n const harnessNamePrefix = (\n /^[A-Za-z]/.test(nameClassName) ? nameClassName : `H${nameClassName}`\n ).slice(0, 31);\n\n // Reuse an existing project configuration; create it otherwise.\n let project: ProjectConfiguration;\n if (projectExists(tree, fullyQualifiedProjectName)) {\n project = readProjectConfigurationUnqualified(\n tree,\n fullyQualifiedProjectName,\n );\n } else {\n addProjectConfiguration(tree, fullyQualifiedProjectName, {\n name: fullyQualifiedProjectName,\n root: projectRoot,\n projectType: 'application',\n sourceRoot: projectRoot,\n tags: [],\n targets: {},\n metadata: {\n generator: AGENTCORE_HARNESS_GENERATOR_INFO.id,\n } as any,\n });\n project = readProjectConfigurationUnqualified(\n tree,\n fullyQualifiedProjectName,\n );\n }\n\n // `chat` runs the vended chat script against the deployed Harness. Re-run:\n // keep an existing target so user edits survive.\n project.targets ??= {};\n project.targets['chat'] ??= {\n executor: 'nx:run-commands',\n options: {\n commands: ['tsx ./scripts/chat.ts'],\n cwd: '{projectRoot}',\n },\n };\n // scripts/chat.ts is TypeScript the user runs and customises, so it goes\n // through the workspace's build sweep.\n addScriptProjectTargets(tree, { project });\n updateProjectConfiguration(tree, project.name, project);\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'project'),\n projectRoot,\n {\n nameClassName,\n nameKebabCase,\n fullyQualifiedName: fullyQualifiedProjectName,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // Resolved before the metadata write because the recorded value is what the\n // declaration's predicates read; undefined when no infrastructure is written,\n // in which case neither provider's packages were added.\n const iac =\n infra === 'agentcore' ? await resolveIac(tree, options.iac) : undefined;\n\n // Record only what cannot drift once the user owns the generated\n // infrastructure: the project identity, its runtime config key, its auth mode\n // and which provider's infrastructure was written.\n const metadata: Omit<AgentCoreHarnessMetadata, 'generator'> = {\n name: nameKebabCase,\n rc: nameClassName,\n auth: 'iam',\n ...(iac ? { iac } : {}),\n };\n\n addGeneratorMetadata(\n tree,\n fullyQualifiedProjectName,\n AGENTCORE_HARNESS_GENERATOR_INFO,\n metadata,\n );\n\n // scripts/chat.ts dependencies; tsx runs it via the `chat` target.\n addTsDependencies(tree, DEPENDENCIES, { metadata });\n\n // Harness infrastructure is written only for `infra: agentcore`. A later\n // `infra: agentcore` rerun adds it without replacing project files.\n if (iac) {\n await sharedConstructsGenerator(tree, { iac }, DEPENDENCIES);\n await addAgentCoreHarnessInfra(tree, {\n harnessNameClassName: nameClassName,\n harnessNameKebabCase: nameKebabCase,\n projectRoot,\n harnessNamePrefix,\n iac,\n });\n }\n\n await addGeneratorMetricsIfApplicable(tree, [\n AGENTCORE_HARNESS_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\n/**\n * Harness details stored in the Harness Project's metadata. `iac` records which\n * provider's infrastructure was written, so the version sync can tell which\n * shared constructs packages this project owns.\n */\nexport interface AgentCoreHarnessMetadata extends IacMetadata {\n generator: string;\n name: string;\n rc: string;\n auth: 'iam';\n}\n\n/**\n * Read a Harness Project's metadata, validating it was generated by the\n * agentcore-harness generator before returning typed data.\n */\nexport const readAgentCoreHarnessMetadata = (\n project: ProjectConfiguration,\n): AgentCoreHarnessMetadata => {\n const metadata = project.metadata as any;\n if (metadata?.generator !== AGENTCORE_HARNESS_GENERATOR_INFO.id) {\n throw new Error(\n `Project '${project.name}' was not generated by the '${AGENTCORE_HARNESS_GENERATOR_INFO.id}' generator.`,\n );\n }\n return metadata as AgentCoreHarnessMetadata;\n};\n\nexport default agentcoreHarnessGenerator;\n"],"names":["addProjectConfiguration","generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","addTsDependencies","addAgentCoreHarnessInfra","declareDependencies","ownedElsewhere","formatFilesInSubtree","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","getNpmScopePrefix","addGeneratorMetadata","getGeneratorInfo","projectExists","readProjectConfigurationUnqualified","addScriptProjectTargets","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","DEPENDENCIES","ts","name","root","dev","AGENTCORE_HARNESS_GENERATOR_INFO","filename","agentcoreHarnessGenerator","tree","options","nameKebabCase","nameClassName","parentDir","directory","subDir","subDirectory","projectRoot","fullyQualifiedProjectName","infra","harnessNamePrefix","test","slice","project","projectType","sourceRoot","tags","targets","metadata","generator","id","executor","commands","cwd","dirname","fullyQualifiedName","overwriteStrategy","KeepExisting","iac","undefined","rc","auth","harnessNameClassName","harnessNameKebabCase","preferInstallDependencies","languages","readAgentCoreHarnessMetadata","Error"],"mappings":"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"}
@@ -19,7 +19,7 @@ const CONNECTION_TF_MODULE_NAME = 'add_gateway_url_to_connection_runtime_config'
19
19
 
20
20
  rc.set('connection', 'gateways', {
21
21
  ...rc.get('connection').gateways,
22
- ${options.gatewayNameClassName}: this.gateway.gatewayUrl,
22
+ ${options.gatewayNameClassName}: this.gatewayUrl,
23
23
  });\` where { $program <: not contains \`rc.set('connection', 'gateways', $_)\` }`);
24
24
  }
25
25
  const terraformConstructPath = joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'app', 'gateways', options.gatewayNameKebabCase, `${options.gatewayNameKebabCase}.tf`);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/connection/gateway-runtime-config.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { joinPathFragments, type Tree } from '@nx/devkit';\nimport { applyGritQL, matchGritQL } from '../utils/ast.js';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../utils/shared-constructs-constants.js';\n\nconst CONNECTION_TF_MODULE_NAME =\n 'add_gateway_url_to_connection_runtime_config';\n\n/**\n * Register the gateway's URL in the 'connection' namespace so it is published\n * to the website's runtime-config.json. Patches the generated CDK and\n * Terraform constructs in-place; idempotent.\n *\n * Note: the 'connection' namespace is stage-scoped — every StaticWebsite in\n * the stage will see this URL, not just the one the user connected.\n */\nexport const addGatewayUrlToConnectionNamespace = async (\n tree: Tree,\n options: {\n /** The kebab-case directory name that holds the construct, e.g. 'my-gateway'. */\n gatewayNameKebabCase: string;\n /** The class name of the gateway, e.g. 'MyGateway'. */\n gatewayNameClassName: string;\n },\n) => {\n const cdkConstructPath = joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'gateways',\n options.gatewayNameKebabCase,\n `${options.gatewayNameKebabCase}.ts`,\n );\n if (tree.exists(cdkConstructPath)) {\n await applyGritQL(\n tree,\n cdkConstructPath,\n `\\`rc.set('agentcore', 'gateways', $args);\\` => raw\\`rc.set('agentcore', 'gateways', $args);\n\n rc.set('connection', 'gateways', {\n ...rc.get('connection').gateways,\n ${options.gatewayNameClassName}: this.gateway.gatewayUrl,\n });\\` where { $program <: not contains \\`rc.set('connection', 'gateways', $_)\\` }`,\n );\n }\n\n const terraformConstructPath = joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'app',\n 'gateways',\n options.gatewayNameKebabCase,\n `${options.gatewayNameKebabCase}.tf`,\n );\n if (tree.exists(terraformConstructPath)) {\n const alreadyPatched = await matchGritQL(\n tree,\n terraformConstructPath,\n `language hcl\\n\\`module \"${CONNECTION_TF_MODULE_NAME}\" { $_ }\\``,\n );\n if (!alreadyPatched) {\n const source = tree.read(terraformConstructPath, 'utf-8')!;\n tree.write(\n terraformConstructPath,\n `${source.trimEnd()}\n\n# Also expose the gateway URL to the frontend via the 'connection' namespace\nmodule \"${CONNECTION_TF_MODULE_NAME}\" {\n source = \"../../../core/runtime-config/entry\"\n\n namespace = \"connection\"\n key = \"gateways\"\n value = { \"${options.gatewayNameClassName}\" = aws_bedrockagentcore_gateway.this.gateway_url }\n\n depends_on = [aws_bedrockagentcore_gateway.this]\n}\n`,\n );\n }\n }\n};\n"],"names":["joinPathFragments","applyGritQL","matchGritQL","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_DIR","CONNECTION_TF_MODULE_NAME","addGatewayUrlToConnectionNamespace","tree","options","cdkConstructPath","gatewayNameKebabCase","exists","gatewayNameClassName","terraformConstructPath","alreadyPatched","source","read","write","trimEnd"],"mappings":"AAAA;;;CAGC,GACD,SAASA,iBAAiB,QAAmB,aAAa;AAC1D,SAASC,WAAW,EAAEC,WAAW,QAAQ,kBAAkB;AAC3D,SACEC,YAAY,EACZC,qBAAqB,EACrBC,oBAAoB,QACf,0CAA0C;AAEjD,MAAMC,4BACJ;AAEF;;;;;;;CAOC,GACD,OAAO,MAAMC,qCAAqC,OAChDC,MACAC;IAOA,MAAMC,mBAAmBV,kBACvBG,cACAC,uBACA,OACA,OACA,YACAK,QAAQE,oBAAoB,EAC5B,GAAGF,QAAQE,oBAAoB,CAAC,GAAG,CAAC;IAEtC,IAAIH,KAAKI,MAAM,CAACF,mBAAmB;QACjC,MAAMT,YACJO,MACAE,kBACA,CAAC;;;;MAID,EAAED,QAAQI,oBAAoB,CAAC;qFACgD,CAAC;IAEpF;IAEA,MAAMC,yBAAyBd,kBAC7BG,cACAE,sBACA,OACA,OACA,YACAI,QAAQE,oBAAoB,EAC5B,GAAGF,QAAQE,oBAAoB,CAAC,GAAG,CAAC;IAEtC,IAAIH,KAAKI,MAAM,CAACE,yBAAyB;QACvC,MAAMC,iBAAiB,MAAMb,YAC3BM,MACAM,wBACA,CAAC,wBAAwB,EAAER,0BAA0B,UAAU,CAAC;QAElE,IAAI,CAACS,gBAAgB;YACnB,MAAMC,SAASR,KAAKS,IAAI,CAACH,wBAAwB;YACjDN,KAAKU,KAAK,CACRJ,wBACA,GAAGE,OAAOG,OAAO,GAAG;;;QAGpB,EAAEb,0BAA0B;;;;;iBAKnB,EAAEG,QAAQI,oBAAoB,CAAC;;;;AAIhD,CAAC;QAEG;IACF;AACF,EAAE"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/connection/gateway-runtime-config.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { joinPathFragments, type Tree } from '@nx/devkit';\nimport { applyGritQL, matchGritQL } from '../utils/ast.js';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../utils/shared-constructs-constants.js';\n\nconst CONNECTION_TF_MODULE_NAME =\n 'add_gateway_url_to_connection_runtime_config';\n\n/**\n * Register the gateway's URL in the 'connection' namespace so it is published\n * to the website's runtime-config.json. Patches the generated CDK and\n * Terraform constructs in-place; idempotent.\n *\n * Note: the 'connection' namespace is stage-scoped — every StaticWebsite in\n * the stage will see this URL, not just the one the user connected.\n */\nexport const addGatewayUrlToConnectionNamespace = async (\n tree: Tree,\n options: {\n /** The kebab-case directory name that holds the construct, e.g. 'my-gateway'. */\n gatewayNameKebabCase: string;\n /** The class name of the gateway, e.g. 'MyGateway'. */\n gatewayNameClassName: string;\n },\n) => {\n const cdkConstructPath = joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'gateways',\n options.gatewayNameKebabCase,\n `${options.gatewayNameKebabCase}.ts`,\n );\n if (tree.exists(cdkConstructPath)) {\n await applyGritQL(\n tree,\n cdkConstructPath,\n `\\`rc.set('agentcore', 'gateways', $args);\\` => raw\\`rc.set('agentcore', 'gateways', $args);\n\n rc.set('connection', 'gateways', {\n ...rc.get('connection').gateways,\n ${options.gatewayNameClassName}: this.gatewayUrl,\n });\\` where { $program <: not contains \\`rc.set('connection', 'gateways', $_)\\` }`,\n );\n }\n\n const terraformConstructPath = joinPathFragments(\n PACKAGES_DIR,\n SHARED_TERRAFORM_DIR,\n 'src',\n 'app',\n 'gateways',\n options.gatewayNameKebabCase,\n `${options.gatewayNameKebabCase}.tf`,\n );\n if (tree.exists(terraformConstructPath)) {\n const alreadyPatched = await matchGritQL(\n tree,\n terraformConstructPath,\n `language hcl\\n\\`module \"${CONNECTION_TF_MODULE_NAME}\" { $_ }\\``,\n );\n if (!alreadyPatched) {\n const source = tree.read(terraformConstructPath, 'utf-8')!;\n tree.write(\n terraformConstructPath,\n `${source.trimEnd()}\n\n# Also expose the gateway URL to the frontend via the 'connection' namespace\nmodule \"${CONNECTION_TF_MODULE_NAME}\" {\n source = \"../../../core/runtime-config/entry\"\n\n namespace = \"connection\"\n key = \"gateways\"\n value = { \"${options.gatewayNameClassName}\" = aws_bedrockagentcore_gateway.this.gateway_url }\n\n depends_on = [aws_bedrockagentcore_gateway.this]\n}\n`,\n );\n }\n }\n};\n"],"names":["joinPathFragments","applyGritQL","matchGritQL","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_DIR","CONNECTION_TF_MODULE_NAME","addGatewayUrlToConnectionNamespace","tree","options","cdkConstructPath","gatewayNameKebabCase","exists","gatewayNameClassName","terraformConstructPath","alreadyPatched","source","read","write","trimEnd"],"mappings":"AAAA;;;CAGC,GACD,SAASA,iBAAiB,QAAmB,aAAa;AAC1D,SAASC,WAAW,EAAEC,WAAW,QAAQ,kBAAkB;AAC3D,SACEC,YAAY,EACZC,qBAAqB,EACrBC,oBAAoB,QACf,0CAA0C;AAEjD,MAAMC,4BACJ;AAEF;;;;;;;CAOC,GACD,OAAO,MAAMC,qCAAqC,OAChDC,MACAC;IAOA,MAAMC,mBAAmBV,kBACvBG,cACAC,uBACA,OACA,OACA,YACAK,QAAQE,oBAAoB,EAC5B,GAAGF,QAAQE,oBAAoB,CAAC,GAAG,CAAC;IAEtC,IAAIH,KAAKI,MAAM,CAACF,mBAAmB;QACjC,MAAMT,YACJO,MACAE,kBACA,CAAC;;;;MAID,EAAED,QAAQI,oBAAoB,CAAC;qFACgD,CAAC;IAEpF;IAEA,MAAMC,yBAAyBd,kBAC7BG,cACAE,sBACA,OACA,OACA,YACAI,QAAQE,oBAAoB,EAC5B,GAAGF,QAAQE,oBAAoB,CAAC,GAAG,CAAC;IAEtC,IAAIH,KAAKI,MAAM,CAACE,yBAAyB;QACvC,MAAMC,iBAAiB,MAAMb,YAC3BM,MACAM,wBACA,CAAC,wBAAwB,EAAER,0BAA0B,UAAU,CAAC;QAElE,IAAI,CAACS,gBAAgB;YACnB,MAAMC,SAASR,KAAKS,IAAI,CAACH,wBAAwB;YACjDN,KAAKU,KAAK,CACRJ,wBACA,GAAGE,OAAOG,OAAO,GAAG;;;QAGpB,EAAEb,0BAA0B;;;;;iBAKnB,EAAEG,QAAQI,oBAAoB,CAAC;;;;AAIhD,CAAC;QAEG;IACF;AACF,EAAE"}
@@ -47,7 +47,7 @@ exports[`infra generator > should configure Checkov target correctly > checkov-t
47
47
  ],
48
48
  "executor": "nx:run-commands",
49
49
  "inputs": [
50
- "{workspaceRoot}/dist/{projectRoot}/cdk.out",
50
+ "default",
51
51
  ],
52
52
  "options": {
53
53
  "command": "uvx --from checkov==3.3.16 checkov --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
@@ -78,7 +78,7 @@ exports[`infra generator > should configure project.json with correct targets >
78
78
  ],
79
79
  "executor": "nx:run-commands",
80
80
  "options": {
81
- "command": "cdk deploy --require-approval=never --express",
81
+ "command": "cdk deploy --require-approval=never",
82
82
  "cwd": "{projectRoot}",
83
83
  },
84
84
  }
@@ -147,7 +147,7 @@ exports[`infra generator > should configure project.json with correct targets >
147
147
  ],
148
148
  "executor": "nx:run-commands",
149
149
  "inputs": [
150
- "{workspaceRoot}/dist/{projectRoot}/cdk.out",
150
+ "default",
151
151
  ],
152
152
  "options": {
153
153
  "command": "uvx --from checkov==3.3.16 checkov --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
@@ -173,7 +173,7 @@ exports[`infra generator > should configure project.json with correct targets >
173
173
  ],
174
174
  "executor": "nx:run-commands",
175
175
  "options": {
176
- "command": "cdk deploy --require-approval=never --express",
176
+ "command": "cdk deploy --require-approval=never",
177
177
  "cwd": "{projectRoot}",
178
178
  },
179
179
  },
@@ -759,7 +759,7 @@ exports[`infra generator > should handle custom project names correctly > custom
759
759
  ],
760
760
  "executor": "nx:run-commands",
761
761
  "inputs": [
762
- "{workspaceRoot}/dist/{projectRoot}/cdk.out",
762
+ "default",
763
763
  ],
764
764
  "options": {
765
765
  "command": "uvx --from checkov==3.3.16 checkov --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
@@ -785,7 +785,7 @@ exports[`infra generator > should handle custom project names correctly > custom
785
785
  ],
786
786
  "executor": "nx:run-commands",
787
787
  "options": {
788
- "command": "cdk deploy --require-approval=never --express",
788
+ "command": "cdk deploy --require-approval=never",
789
789
  "cwd": "{projectRoot}",
790
790
  },
791
791
  },
@@ -10,6 +10,7 @@ import { resolveContainers } from "../../utils/containers.js";
10
10
  import { declareDependencies, ownedElsewhere } from "../../utils/declared-dependencies.js";
11
11
  import { formatFilesInSubtree } from "../../utils/format.js";
12
12
  import { installDependencies } from "../../utils/install.js";
13
+ import { addLocalProjectDependency } from "../../utils/local-project-dependency.js";
13
14
  import { addGeneratorMetricsIfApplicable } from "../../utils/metrics.js";
14
15
  import { esmVars } from "../../utils/module-format.js";
15
16
  import { kebabCase } from "../../utils/names.js";
@@ -59,7 +60,8 @@ export const DEPENDENCIES = declareDependencies()({
59
60
  export const INFRA_APP_GENERATOR_INFO = getGeneratorInfo(import.meta.filename);
60
61
  export async function tsInfraGenerator(tree, schema) {
61
62
  const lib = getTsLibDetails(tree, schema);
62
- if (!projectExists(tree, lib.fullyQualifiedName)) {
63
+ const isNewProject = !projectExists(tree, lib.fullyQualifiedName);
64
+ if (isNewProject) {
63
65
  await tsProjectGenerator(tree, {
64
66
  ...schema,
65
67
  preferInstallDependencies: false
@@ -108,7 +110,14 @@ export async function tsInfraGenerator(tree, schema) {
108
110
  const namespace = kebabCase(fullyQualifiedName);
109
111
  // The stage instantiated in main.ts. Quoted so the shell does not glob `*`.
110
112
  const sandboxStagePattern = `"${namespace}-sandbox/*"`;
111
- tree.delete(joinPathFragments(libraryRoot, 'src'));
113
+ // `tsProjectGenerator` scaffolds a library `src`, which the CDK app layout
114
+ // replaces. Only on creation — on a re-run this is the user's infrastructure.
115
+ if (isNewProject) {
116
+ tree.delete(joinPathFragments(libraryRoot, 'src'));
117
+ }
118
+ // The guide walks through declaring resources in
119
+ // `src/stacks/application-stack.ts` and adding stages to `src/main.ts`, so
120
+ // everything here is scaffolded once and then left alone.
112
121
  generateFiles(tree, joinPathFragments(import.meta.dirname, './files/app'), libraryRoot, {
113
122
  synthDir: synthDirFromProject,
114
123
  scopeAlias: scopeAlias,
@@ -120,7 +129,7 @@ export async function tsInfraGenerator(tree, schema) {
120
129
  ...schema,
121
130
  ...esmVars(tree)
122
131
  }, {
123
- overwriteStrategy: OverwriteStrategy.Overwrite
132
+ overwriteStrategy: OverwriteStrategy.KeepExisting
124
133
  });
125
134
  updateJson(tree, `${libraryRoot}/project.json`, (config)=>{
126
135
  config.projectType = 'application';
@@ -149,11 +158,17 @@ export async function tsInfraGenerator(tree, schema) {
149
158
  command: 'cdk synth'
150
159
  })
151
160
  };
161
+ // `default` rather than the synth directory: `dist` is gitignored, so a
162
+ // fileset input pointed at it matches no tracked file and hashes to a
163
+ // constant — the scan would cache-hit forever and pass on infrastructure
164
+ // it never read. `default` carries the project's own sources plus the
165
+ // transitive `dependentTasksOutputFiles` entry, which resolves against
166
+ // the upstream `synth` task and so hashes the template actually scanned.
152
167
  config.targets.checkov = {
153
168
  cache: true,
154
169
  executor: 'nx:run-commands',
155
170
  inputs: [
156
- '{workspaceRoot}/dist/{projectRoot}/cdk.out'
171
+ 'default'
157
172
  ],
158
173
  outputs: [
159
174
  '{workspaceRoot}/dist/{projectRoot}/checkov'
@@ -171,13 +186,14 @@ export async function tsInfraGenerator(tree, schema) {
171
186
  '^assemble',
172
187
  'compile'
173
188
  ],
174
- // No --express here when stages are configured: this target deploys
175
- // whichever stage is named, including beta and prod.
189
+ // No --express: this target deploys whichever stage is named, including
190
+ // beta and prod, so it waits for full resource stabilization. Express
191
+ // mode belongs to `deploy-sandbox`, which only ever deploys a sandbox.
176
192
  options: stageConfig ? withCdkEnv({
177
193
  command: `tsx packages/common/scripts/src/infra/infra-deploy.ts ${libraryRoot}`
178
194
  }) : withCdkEnv({
179
195
  cwd: '{projectRoot}',
180
- command: 'cdk deploy --require-approval=never --express'
196
+ command: 'cdk deploy --require-approval=never'
181
197
  })
182
198
  };
183
199
  config.targets['deploy-sandbox'] = {
@@ -266,6 +282,17 @@ export async function tsInfraGenerator(tree, schema) {
266
282
  ] : []
267
283
  ])
268
284
  }));
285
+ // `main.ts` and the application stack import the shared constructs.
286
+ addLocalProjectDependency(tree, {
287
+ consumerRoot: libraryRoot,
288
+ dependencyRoot: joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR)
289
+ });
290
+ if (stageConfig) {
291
+ addLocalProjectDependency(tree, {
292
+ consumerRoot: libraryRoot,
293
+ dependencyRoot: joinPathFragments(PACKAGES_DIR, SHARED_INFRA_CONFIG_DIR)
294
+ });
295
+ }
269
296
  await addGeneratorMetricsIfApplicable(tree, [
270
297
  INFRA_APP_GENERATOR_INFO
271
298
  ]);