@aws/nx-plugin 1.0.0-rc.37 → 1.0.0-rc.39

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 (60) hide show
  1. package/generators.json +7 -0
  2. package/package.json +1 -1
  3. package/src/init/generator.d.ts +18 -0
  4. package/src/init/generator.js +35 -0
  5. package/src/init/generator.js.map +1 -0
  6. package/src/init/schema.d.js +6 -0
  7. package/src/init/schema.d.js.map +1 -0
  8. package/src/init/schema.d.ts +16 -0
  9. package/src/init/schema.json +35 -0
  10. package/src/mcp-server/generator-info.js +27 -13
  11. package/src/mcp-server/generator-info.js.map +1 -1
  12. package/src/mcp-server/guide-pipeline.js +16 -1
  13. package/src/mcp-server/guide-pipeline.js.map +1 -1
  14. package/src/mcp-server/server.js +2 -0
  15. package/src/mcp-server/server.js.map +1 -1
  16. package/src/mcp-server/tools/add-to-existing-project.d.ts +12 -0
  17. package/src/mcp-server/tools/add-to-existing-project.js +36 -0
  18. package/src/mcp-server/tools/add-to-existing-project.js.map +1 -0
  19. package/src/mcp-server/tools/general-guidance.d.ts +1 -1
  20. package/src/mcp-server/tools/general-guidance.js +1 -0
  21. package/src/mcp-server/tools/general-guidance.js.map +1 -1
  22. package/src/preset/__snapshots__/generator.spec.ts.snap +3 -0
  23. package/src/preset/generator.js +19 -129
  24. package/src/preset/generator.js.map +1 -1
  25. package/src/py/agent/files/deploy/Dockerfile.template +1 -1
  26. package/src/py/agent/generator.js +13 -2
  27. package/src/py/agent/generator.js.map +1 -1
  28. package/src/py/mcp-server/files/deploy/Dockerfile.template +1 -1
  29. package/src/py/mcp-server/generator.js +13 -2
  30. package/src/py/mcp-server/generator.js.map +1 -1
  31. package/src/py/rdb/generator.js +11 -0
  32. package/src/py/rdb/generator.js.map +1 -1
  33. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +4 -1
  34. package/src/ts/agent/files/deploy/Dockerfile.template +4 -1
  35. package/src/ts/agent/generator.js +13 -1
  36. package/src/ts/agent/generator.js.map +1 -1
  37. package/src/ts/lib/ts-project-utils.js +0 -7
  38. package/src/ts/lib/ts-project-utils.js.map +1 -1
  39. package/src/ts/mcp-server/files/Dockerfile.template +4 -1
  40. package/src/ts/mcp-server/generator.js +14 -2
  41. package/src/ts/mcp-server/generator.js.map +1 -1
  42. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +8 -1
  43. package/src/ts/rdb/files/Dockerfile.template +8 -1
  44. package/src/ts/rdb/generator.js +11 -0
  45. package/src/ts/rdb/generator.js.map +1 -1
  46. package/src/utils/base-tsconfig.d.ts +30 -0
  47. package/src/utils/base-tsconfig.js +32 -0
  48. package/src/utils/base-tsconfig.js.map +1 -0
  49. package/src/utils/commands.d.ts +9 -2
  50. package/src/utils/commands.js +19 -9
  51. package/src/utils/commands.js.map +1 -1
  52. package/src/utils/docker.d.ts +44 -0
  53. package/src/utils/docker.js +81 -0
  54. package/src/utils/docker.js.map +1 -0
  55. package/src/utils/init.d.ts +53 -0
  56. package/src/utils/init.js +251 -0
  57. package/src/utils/init.js.map +1 -0
  58. package/src/utils/versions.d.ts +18 -1
  59. package/src/utils/versions.js +16 -0
  60. package/src/utils/versions.js.map +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/mcp-server/tools/add-to-existing-project.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { NxGeneratorInfo } from '../../utils/generators';\nimport { fetchGuidePages } from '../generator-info';\nimport { PackageManagerSchema } from '../schema';\n\n/**\n * The guide page (under `get_started/`) that backs this tool, so the tool and\n * the published docs never drift.\n */\nconst EXISTING_PROJECT_GUIDE = 'existing-project';\n\n/**\n * Add a tool which guides an agent through adding @aws/nx-plugin to an\n * existing Nx or non-Nx workspace. Returns the `existing-project` docs page,\n * which includes the full adoption steps and troubleshooting reference.\n */\nexport const addToExistingProjectTool = (\n server: McpServer,\n generators: NxGeneratorInfo[],\n) => {\n server.registerTool(\n 'add-to-existing-project',\n {\n title: 'Add to Existing Project',\n description:\n 'Tool for adding the Nx Plugin for AWS to an existing Nx workspace or non-Nx monorepo. Use this when a user wants to adopt @aws/nx-plugin in a project that was not created with the plugin preset, or hits configuration errors when running generators in such a workspace.',\n inputSchema: {\n packageManager: PackageManagerSchema.optional(),\n },\n },\n async ({ packageManager }) => {\n const guide = await fetchGuidePages(\n [EXISTING_PROJECT_GUIDE],\n generators,\n packageManager,\n );\n return {\n content: [\n {\n type: 'text' as const,\n text: guide,\n },\n ],\n };\n },\n );\n};\n"],"names":["fetchGuidePages","PackageManagerSchema","EXISTING_PROJECT_GUIDE","addToExistingProjectTool","server","generators","registerTool","title","description","inputSchema","packageManager","optional","guide","content","type","text"],"mappings":"AAAA;;;CAGC,GAGD,SAASA,eAAe,QAAQ,uBAAoB;AACpD,SAASC,oBAAoB,QAAQ,eAAY;AAEjD;;;CAGC,GACD,MAAMC,yBAAyB;AAE/B;;;;CAIC,GACD,OAAO,MAAMC,2BAA2B,CACtCC,QACAC;IAEAD,OAAOE,YAAY,CACjB,2BACA;QACEC,OAAO;QACPC,aACE;QACFC,aAAa;YACXC,gBAAgBT,qBAAqBU,QAAQ;QAC/C;IACF,GACA,OAAO,EAAED,cAAc,EAAE;QACvB,MAAME,QAAQ,MAAMZ,gBAClB;YAACE;SAAuB,EACxBG,YACAK;QAEF,OAAO;YACLG,SAAS;gBACP;oBACEC,MAAM;oBACNC,MAAMH;gBACR;aACD;QACH;IACF;AAEJ,EAAE"}
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
6
6
  import type { NxGeneratorInfo } from '../../utils/generators';
7
- export declare const TOOL_SELECTION_GUIDE = "## Tool Selection Guide\n\n- Use the `general-guidance` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.\n- Use the `create-workspace-command` tool to discover how to create a workspace to start a new project.\n- Use the `list-generators` tool to discover the available generators and how to run them.\n- Use the `generator-guide` tool to retrieve detailed information about a specific generator.";
7
+ export declare const TOOL_SELECTION_GUIDE = "## Tool Selection Guide\n\n- Use the `general-guidance` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.\n- Use the `create-workspace-command` tool to discover how to create a workspace to start a new project.\n- Use the `add-to-existing-project` tool when adding the plugin to an existing Nx workspace or non-Nx monorepo, or when troubleshooting configuration errors in such a workspace.\n- Use the `list-generators` tool to discover the available generators and how to run them.\n- Use the `generator-guide` tool to retrieve detailed information about a specific generator.";
8
8
  /**
9
9
  * Add a tool which provides general guidance for using Nx and the Nx Plugin for AWS
10
10
  */
@@ -8,6 +8,7 @@ export const TOOL_SELECTION_GUIDE = `## Tool Selection Guide
8
8
 
9
9
  - Use the \`general-guidance\` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.
10
10
  - Use the \`create-workspace-command\` tool to discover how to create a workspace to start a new project.
11
+ - Use the \`add-to-existing-project\` tool when adding the plugin to an existing Nx workspace or non-Nx monorepo, or when troubleshooting configuration errors in such a workspace.
11
12
  - Use the \`list-generators\` tool to discover the available generators and how to run them.
12
13
  - Use the \`generator-guide\` tool to retrieve detailed information about a specific generator.`;
13
14
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/mcp-server/tools/general-guidance.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { NxGeneratorInfo } from '../../utils/generators';\nimport { IAC_PROVIDERS } from '../../utils/iac-providers';\nimport { buildNxCommand, fetchGuidePages } from '../generator-info';\nimport { PACKAGE_MANAGERS } from '../schema';\n\nexport const TOOL_SELECTION_GUIDE = `## Tool Selection Guide\n\n- Use the \\`general-guidance\\` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.\n- Use the \\`create-workspace-command\\` tool to discover how to create a workspace to start a new project.\n- Use the \\`list-generators\\` tool to discover the available generators and how to run them.\n- Use the \\`generator-guide\\` tool to retrieve detailed information about a specific generator.`;\n\n/**\n * Add a tool which provides general guidance for using Nx and the Nx Plugin for AWS\n */\nexport const addGeneralGuidanceTool = (\n server: McpServer,\n generators: NxGeneratorInfo[],\n) => {\n server.registerTool(\n 'general-guidance',\n {\n title: 'General Guidance',\n description:\n 'Tool for guidance and best practices for working with Nx and the Nx Plugin for AWS',\n },\n async () => ({\n content: [\n {\n type: 'text' as const,\n text: `# Nx Plugin for AWS Guidance\n\n${TOOL_SELECTION_GUIDE}\n\n## Getting Started\n\n- Choose a package manager first. You can choose between ${PACKAGE_MANAGERS.join(', ')}. It's recommended to use \"pnpm\" if the user has no preference\n- Choose an infrastructure as code (IaC) provider next. You can choose between ${IAC_PROVIDERS.join(', ')}. It's recommended to use CDK if the user has no preference\n- Next, you must create an Nx workspace. Use the \\`create-workspace-command\\` tool for more details, and provide it with your chosen package manager\n- After this, you can start scaffolding the main components of your application using generators. Use the \\`list-generators\\` tool to discover available generators, and the \\`generator-guide\\` tool for more detailed information about a specific generator\n\n## Nx Primer\n\n- Prefix nx commands with the appropriate prefix for your package manager, for example:\n${PACKAGE_MANAGERS.map((pm) => buildNxCommand('<options>', pm)).join(' - \\n')}\n- Each project in your workspace has a file named \\`project.json\\` which contains important project information such as its name, and defines the \"targets\" which can be run for that project, for example building or testing the project\n- Use the command \\`nx reset\\` to reset the Nx daemon when unexpected issues arise\n- After adding dependencies between TypeScript projects, use \\`nx sync\\` to ensure project references are set up correctly\n\n## General Instructions\n\n- Workspaces contain a single \\`package.json\\` file at the root which defines the dependencies for all projects. Therefore when installing dependencies, you must add these to the root workspace using the appropriate command for your package manager:\n - pnpm add -w -D <package>\n - yarn add -D <package>\n - npm install --legacy-peer-deps -D <package>\n - bun install -D <package>\n - (Omit -D for production dependencies)\n- When specifying project names as arguments to generators, prefer the _fully qualified_ project name, for example \\`@workspace-name/project-name\\`. Check the \\`project.json\\` file for the specific package to find its fully qualified name\n- When no generator exists for a specific framework required, use the base \\`ts#project\\` and \\`py#project\\` generators and build on top.\n- Leave the \\`--infra\\` option at its default value unless the user has explicitly instructed otherwise. Generators choose a sensible default type of infrastructure to deploy the project with, so only override \\`--infra\\` when the user has specified a particular requirement.\n\n## Useful Commands\n\n- Fix lint issues with \\`nx run-many --target lint --configuration=fix --all --output-style=stream\\`\n- Build all projects with \\`nx run-many --target build --all --output-style=stream\\`\n- Prefer importing the CDK constructs vended by generators in \\`packages/common/constructs\\` over writing your own\n\n## Best Practices\n\n- After running a generator, use the \\`nx show projects\\` command to check which projects have been added (if any)\n- Carefully examine the files that have been generated and always refer back to the generator guide when working in a generated project\n- Generate all projects into the \\`packages/\\` directory\n- After making changes to your projects, fix linting issues, then run a full build\n- When it's time to start testing a project, suggest to the user that infrastructure is deployed to AWS. For websites, if a runtime-config.json is needed, use the load:runtime-config target after a deployment to point a local website at a sandbox stack.\n\n## Batching Generators\n\nWhen scaffolding several projects in one go, chain generators to avoid a slow dependency install after every generator:\n\n- **Chain generators** with \\`&&\\` in a single command. Pass \\`--prefer-install-dependencies=false\\` on each generator except the last so dependencies install once at the end, for example:\n\n${PACKAGE_MANAGERS.map(\n (pm) => ` \\`\\`\\`bash\n ${buildNxCommand('g @aws/nx-plugin:ts#trpc-api --no-interactive --name=my-app-api --auth=IAM --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:ts#react-website --no-interactive --name=my-app-website --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:connection --no-interactive --sourceProject=@my-app/my-app-website --targetProject=@my-app/my-app-api --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:ts#infra --no-interactive --name=infra', pm)} && \\\\\n ${buildNxCommand('sync', pm)}\n \\`\\`\\``,\n).join('\\n')}\n\n- **\\`--prefer-install-dependencies=false\\`** asks a generator to defer its dependency install so the batch installs once at the end (the final generator above omits the flag and installs everything).\n- **\\`nx sync\\`** is required before building — generators modify TypeScript project references.\n\n## Detailed Guides\n\nPlease refer to the below documentation for important details regarding workspaces and working with TypeScript or Python projects.\n\n${await fetchGuidePages(['workspace', 'typescript-project', 'python-project'], generators)}\n\n `,\n },\n ],\n }),\n );\n};\n"],"names":["IAC_PROVIDERS","buildNxCommand","fetchGuidePages","PACKAGE_MANAGERS","TOOL_SELECTION_GUIDE","addGeneralGuidanceTool","server","generators","registerTool","title","description","content","type","text","join","map","pm"],"mappings":"AAAA;;;CAGC,GAGD,SAASA,aAAa,QAAQ,+BAA4B;AAC1D,SAASC,cAAc,EAAEC,eAAe,QAAQ,uBAAoB;AACpE,SAASC,gBAAgB,QAAQ,eAAY;AAE7C,OAAO,MAAMC,uBAAuB,CAAC;;;;;+FAK0D,CAAC,CAAC;AAEjG;;CAEC,GACD,OAAO,MAAMC,yBAAyB,CACpCC,QACAC;IAEAD,OAAOE,YAAY,CACjB,oBACA;QACEC,OAAO;QACPC,aACE;IACJ,GACA,UAAa,CAAA;YACXC,SAAS;gBACP;oBACEC,MAAM;oBACNC,MAAM,CAAC;;AAEjB,EAAET,qBAAqB;;;;yDAIkC,EAAED,iBAAiBW,IAAI,CAAC,MAAM;+EACR,EAAEd,cAAcc,IAAI,CAAC,MAAM;;;;;;;AAO1G,EAAEX,iBAAiBY,GAAG,CAAC,CAACC,KAAOf,eAAe,aAAae,KAAKF,IAAI,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqC9E,EAAEX,iBAAiBY,GAAG,CACpB,CAACC,KAAO,CAAC;EACT,EAAEf,eAAe,kHAAkHe,IAAI;IACrI,EAAEf,eAAe,gHAAgHe,IAAI;IACrI,EAAEf,eAAe,8JAA8Je,IAAI;IACnL,EAAEf,eAAe,2DAA2De,IAAI;IAChF,EAAEf,eAAe,QAAQe,IAAI;QACzB,CAAC,EACPF,IAAI,CAAC,MAAM;;;;;;;;;AASb,EAAE,MAAMZ,gBAAgB;wBAAC;wBAAa;wBAAsB;qBAAiB,EAAEK,YAAY;;IAEvF,CAAC;gBACG;aACD;QACH,CAAA;AAEJ,EAAE"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/mcp-server/tools/general-guidance.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { NxGeneratorInfo } from '../../utils/generators';\nimport { IAC_PROVIDERS } from '../../utils/iac-providers';\nimport { buildNxCommand, fetchGuidePages } from '../generator-info';\nimport { PACKAGE_MANAGERS } from '../schema';\n\nexport const TOOL_SELECTION_GUIDE = `## Tool Selection Guide\n\n- Use the \\`general-guidance\\` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.\n- Use the \\`create-workspace-command\\` tool to discover how to create a workspace to start a new project.\n- Use the \\`add-to-existing-project\\` tool when adding the plugin to an existing Nx workspace or non-Nx monorepo, or when troubleshooting configuration errors in such a workspace.\n- Use the \\`list-generators\\` tool to discover the available generators and how to run them.\n- Use the \\`generator-guide\\` tool to retrieve detailed information about a specific generator.`;\n\n/**\n * Add a tool which provides general guidance for using Nx and the Nx Plugin for AWS\n */\nexport const addGeneralGuidanceTool = (\n server: McpServer,\n generators: NxGeneratorInfo[],\n) => {\n server.registerTool(\n 'general-guidance',\n {\n title: 'General Guidance',\n description:\n 'Tool for guidance and best practices for working with Nx and the Nx Plugin for AWS',\n },\n async () => ({\n content: [\n {\n type: 'text' as const,\n text: `# Nx Plugin for AWS Guidance\n\n${TOOL_SELECTION_GUIDE}\n\n## Getting Started\n\n- Choose a package manager first. You can choose between ${PACKAGE_MANAGERS.join(', ')}. It's recommended to use \"pnpm\" if the user has no preference\n- Choose an infrastructure as code (IaC) provider next. You can choose between ${IAC_PROVIDERS.join(', ')}. It's recommended to use CDK if the user has no preference\n- Next, you must create an Nx workspace. Use the \\`create-workspace-command\\` tool for more details, and provide it with your chosen package manager\n- After this, you can start scaffolding the main components of your application using generators. Use the \\`list-generators\\` tool to discover available generators, and the \\`generator-guide\\` tool for more detailed information about a specific generator\n\n## Nx Primer\n\n- Prefix nx commands with the appropriate prefix for your package manager, for example:\n${PACKAGE_MANAGERS.map((pm) => buildNxCommand('<options>', pm)).join(' - \\n')}\n- Each project in your workspace has a file named \\`project.json\\` which contains important project information such as its name, and defines the \"targets\" which can be run for that project, for example building or testing the project\n- Use the command \\`nx reset\\` to reset the Nx daemon when unexpected issues arise\n- After adding dependencies between TypeScript projects, use \\`nx sync\\` to ensure project references are set up correctly\n\n## General Instructions\n\n- Workspaces contain a single \\`package.json\\` file at the root which defines the dependencies for all projects. Therefore when installing dependencies, you must add these to the root workspace using the appropriate command for your package manager:\n - pnpm add -w -D <package>\n - yarn add -D <package>\n - npm install --legacy-peer-deps -D <package>\n - bun install -D <package>\n - (Omit -D for production dependencies)\n- When specifying project names as arguments to generators, prefer the _fully qualified_ project name, for example \\`@workspace-name/project-name\\`. Check the \\`project.json\\` file for the specific package to find its fully qualified name\n- When no generator exists for a specific framework required, use the base \\`ts#project\\` and \\`py#project\\` generators and build on top.\n- Leave the \\`--infra\\` option at its default value unless the user has explicitly instructed otherwise. Generators choose a sensible default type of infrastructure to deploy the project with, so only override \\`--infra\\` when the user has specified a particular requirement.\n\n## Useful Commands\n\n- Fix lint issues with \\`nx run-many --target lint --configuration=fix --all --output-style=stream\\`\n- Build all projects with \\`nx run-many --target build --all --output-style=stream\\`\n- Prefer importing the CDK constructs vended by generators in \\`packages/common/constructs\\` over writing your own\n\n## Best Practices\n\n- After running a generator, use the \\`nx show projects\\` command to check which projects have been added (if any)\n- Carefully examine the files that have been generated and always refer back to the generator guide when working in a generated project\n- Generate all projects into the \\`packages/\\` directory\n- After making changes to your projects, fix linting issues, then run a full build\n- When it's time to start testing a project, suggest to the user that infrastructure is deployed to AWS. For websites, if a runtime-config.json is needed, use the load:runtime-config target after a deployment to point a local website at a sandbox stack.\n\n## Batching Generators\n\nWhen scaffolding several projects in one go, chain generators to avoid a slow dependency install after every generator:\n\n- **Chain generators** with \\`&&\\` in a single command. Pass \\`--prefer-install-dependencies=false\\` on each generator except the last so dependencies install once at the end, for example:\n\n${PACKAGE_MANAGERS.map(\n (pm) => ` \\`\\`\\`bash\n ${buildNxCommand('g @aws/nx-plugin:ts#trpc-api --no-interactive --name=my-app-api --auth=IAM --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:ts#react-website --no-interactive --name=my-app-website --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:connection --no-interactive --sourceProject=@my-app/my-app-website --targetProject=@my-app/my-app-api --prefer-install-dependencies=false', pm)} && \\\\\n ${buildNxCommand('g @aws/nx-plugin:ts#infra --no-interactive --name=infra', pm)} && \\\\\n ${buildNxCommand('sync', pm)}\n \\`\\`\\``,\n).join('\\n')}\n\n- **\\`--prefer-install-dependencies=false\\`** asks a generator to defer its dependency install so the batch installs once at the end (the final generator above omits the flag and installs everything).\n- **\\`nx sync\\`** is required before building — generators modify TypeScript project references.\n\n## Detailed Guides\n\nPlease refer to the below documentation for important details regarding workspaces and working with TypeScript or Python projects.\n\n${await fetchGuidePages(['workspace', 'typescript-project', 'python-project'], generators)}\n\n `,\n },\n ],\n }),\n );\n};\n"],"names":["IAC_PROVIDERS","buildNxCommand","fetchGuidePages","PACKAGE_MANAGERS","TOOL_SELECTION_GUIDE","addGeneralGuidanceTool","server","generators","registerTool","title","description","content","type","text","join","map","pm"],"mappings":"AAAA;;;CAGC,GAGD,SAASA,aAAa,QAAQ,+BAA4B;AAC1D,SAASC,cAAc,EAAEC,eAAe,QAAQ,uBAAoB;AACpE,SAASC,gBAAgB,QAAQ,eAAY;AAE7C,OAAO,MAAMC,uBAAuB,CAAC;;;;;;+FAM0D,CAAC,CAAC;AAEjG;;CAEC,GACD,OAAO,MAAMC,yBAAyB,CACpCC,QACAC;IAEAD,OAAOE,YAAY,CACjB,oBACA;QACEC,OAAO;QACPC,aACE;IACJ,GACA,UAAa,CAAA;YACXC,SAAS;gBACP;oBACEC,MAAM;oBACNC,MAAM,CAAC;;AAEjB,EAAET,qBAAqB;;;;yDAIkC,EAAED,iBAAiBW,IAAI,CAAC,MAAM;+EACR,EAAEd,cAAcc,IAAI,CAAC,MAAM;;;;;;;AAO1G,EAAEX,iBAAiBY,GAAG,CAAC,CAACC,KAAOf,eAAe,aAAae,KAAKF,IAAI,CAAC,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqC9E,EAAEX,iBAAiBY,GAAG,CACpB,CAACC,KAAO,CAAC;EACT,EAAEf,eAAe,kHAAkHe,IAAI;IACrI,EAAEf,eAAe,gHAAgHe,IAAI;IACrI,EAAEf,eAAe,8JAA8Je,IAAI;IACnL,EAAEf,eAAe,2DAA2De,IAAI;IAChF,EAAEf,eAAe,QAAQe,IAAI;QACzB,CAAC,EACPF,IAAI,CAAC,MAAM;;;;;;;;;AASb,EAAE,MAAMZ,gBAAgB;wBAAC;wBAAa;wBAAsB;qBAAiB,EAAEK,YAAY;;IAEvF,CAAC;gBACG;aACD;QACH,CAAA;AAEJ,EAAE"}
@@ -90,6 +90,8 @@ Nx Console is an editor extension that enriches your developer experience. It le
90
90
  The following list of generators are what is currently available in the \`@aws/nx-plugin\`:
91
91
 
92
92
 
93
+ - **init**: Configure an existing Nx workspace to use the @aws/nx-plugin
94
+
93
95
  - **agentcore-gateway**: Generate an AgentCore Gateway project
94
96
 
95
97
  - **connection**: Integrates a source project with a target project
@@ -340,6 +342,7 @@ exports[`preset generator > should run successfully > package.json 1`] = `
340
342
  "@nx/js": "23.0.2",
341
343
  "@nx/workspace": "23.0.2",
342
344
  "@swc/helpers": "~0.5.18",
345
+ "nx": "23.0.2",
343
346
  "typescript": "6.0.3"
344
347
  },
345
348
  "type": "module",
@@ -1,61 +1,17 @@
1
1
  /**
2
2
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
- */ import { addDependenciesToPackageJson, detectPackageManager, generateFiles, joinPathFragments, OverwriteStrategy, readNxJson, updateJson, updateNxJson } from "@nx/devkit";
5
- import { initGenerator } from "@nx/js";
4
+ */ import { addDependenciesToPackageJson, joinPathFragments, OverwriteStrategy, updateJson } from "@nx/devkit";
6
5
  import { execSync } from "child_process";
7
6
  import enquirer from "enquirer";
8
7
  import { readFileSync } from "fs";
9
- import yaml from "js-yaml";
10
- import { readModulePackageJson } from "nx/src/utils/package-json";
11
- import GeneratorsJson from "../../generators.json" with {
12
- type: 'json'
13
- };
14
- import { SYNC_GENERATOR_NAME as TS_SYNC_GENERATOR_NAME } from "../ts/sync/generator.js";
15
8
  import { ensureAwsNxPluginConfig, updateAwsNxPluginConfig } from "../utils/config/utils.js";
16
- import { inferContainers } from "../utils/containers.js";
17
- import { DEFAULT_BIOME_CONFIG, formatFilesInSubtree } from "../utils/format.js";
9
+ import { formatFilesInSubtree } from "../utils/format.js";
10
+ import { applyWorkspaceInit } from "../utils/init.js";
18
11
  import { installDependencies } from "../utils/install.js";
19
- import { configureMcpServers } from "../utils/mcp.js";
20
- import { getNpmScope } from "../utils/npm-scope.js";
21
12
  import { getGeneratorInfo } from "../utils/nx.js";
22
- import { getPackageManagerDisplayCommands } from "../utils/pkg-manager.js";
23
13
  import { withVersions } from "../utils/versions.js";
24
- const WORKSPACES = [
25
- 'packages/*'
26
- ];
27
- const NX_TYPESCRIPT_SYNC_GENERATOR = '@nx/js:typescript-sync';
28
- // Built dependencies whose install scripts the generated workspace trusts.
29
- // `onlyBuiltDependencies` is the pnpm 10 key (silently ignored by pnpm 11);
30
- // pnpm 11 reads `allowBuilds` instead. Any dep NOT in this allowlist will
31
- // have its install scripts skipped with a warning — matching pnpm 10's
32
- // default behaviour. The user can opt-in later via `pnpm approve-builds`.
33
- const PNPM_BUILT_DEPENDENCIES = [
34
- '@swc/core',
35
- 'esbuild',
36
- 'nx',
37
- 'sharp'
38
- ];
39
14
  export const PRESET_GENERATOR_INFO = getGeneratorInfo(import.meta.filename);
40
- const setUpWorkspaces = (tree)=>{
41
- if (detectPackageManager() === 'pnpm') {
42
- tree.write('pnpm-workspace.yaml', yaml.dump({
43
- packages: WORKSPACES,
44
- allowBuilds: Object.fromEntries(PNPM_BUILT_DEPENDENCIES.map((dep)=>[
45
- dep,
46
- true
47
- ])),
48
- onlyBuiltDependencies: PNPM_BUILT_DEPENDENCIES
49
- }, {
50
- quotingType: "'"
51
- }));
52
- } else {
53
- updateJson(tree, 'package.json', (json)=>{
54
- json.workspaces = WORKSPACES;
55
- return json;
56
- });
57
- }
58
- };
59
15
  /**
60
16
  * Determines if the current user is an Amazon employee based on their git configuration.
61
17
  *
@@ -120,8 +76,6 @@ const setUpGitSecrets = (tree)=>{
120
76
  ]));
121
77
  };
122
78
  export const presetGenerator = async (tree, { iac, gitSecrets, mcp, containers, module, preferInstallDependencies })=>{
123
- const resolvedContainers = !containers || containers === 'infer' ? inferContainers() : containers;
124
- const esm = (module ?? 'esm') === 'esm';
125
79
  if (isAmazonian() && !process.env.VITEST && !process.env.CI && process.env.NX_DRY_RUN !== 'true' && process.env.NX_INTERACTIVE !== 'false') {
126
80
  const { engagementId } = await enquirer.prompt([
127
81
  {
@@ -140,93 +94,29 @@ export const presetGenerator = async (tree, { iac, gitSecrets, mcp, containers,
140
94
  });
141
95
  }
142
96
  }
143
- // Write IaC provider and container engine to plugin config
144
- await ensureAwsNxPluginConfig(tree);
145
- await updateAwsNxPluginConfig(tree, {
146
- iac: {
147
- provider: iac
148
- },
149
- containers: {
150
- engine: resolvedContainers
151
- }
152
- });
153
- await initGenerator(tree, {
154
- formatter: 'none',
155
- addTsPlugin: true
156
- });
157
- tree.delete('apps/.gitkeep');
158
- tree.delete('libs/.gitkeep');
159
- tree.write('packages/.gitkeep', '');
160
- setUpWorkspaces(tree);
161
- const nxJson = readNxJson(tree);
162
- updateNxJson(tree, {
163
- ...nxJson,
164
- analytics: false,
165
- targetDefaults: {
166
- ...nxJson.targetDefaults,
167
- compile: {
168
- ...nxJson.targetDefaults?.compile,
169
- syncGenerators: [
170
- ...(nxJson.targetDefaults?.compile?.syncGenerators ?? []).filter((g)=>![
171
- TS_SYNC_GENERATOR_NAME,
172
- NX_TYPESCRIPT_SYNC_GENERATOR
173
- ].includes(g)),
174
- NX_TYPESCRIPT_SYNC_GENERATOR,
175
- TS_SYNC_GENERATOR_NAME
176
- ]
177
- }
178
- }
179
- });
97
+ // The preset owns the greenfield workspace's module format: write the root
98
+ // `type` explicitly from the chosen `--module` so later generators can
99
+ // infer it. The `init` generator never touches an existing workspace's
100
+ // `type` field.
180
101
  updateJson(tree, 'package.json', (packageJson)=>({
181
102
  ...packageJson,
182
- // Written explicitly so later generators can infer the workspace's module
183
- // format from the root `type`.
184
- type: esm ? 'module' : 'commonjs',
185
- scripts: {
186
- ...packageJson.scripts,
187
- dev: 'nx run-many --target dev',
188
- build: 'nx run-many --target build',
189
- lint: 'nx run-many --target lint --configuration=fix',
190
- test: 'nx run-many --target test --all',
191
- 'build:skip-lint': 'nx run-many --target build --configuration=skip-lint',
192
- 'build:all': 'nx run-many --target build --all',
193
- 'affected:all': 'nx affected --target build'
194
- }
103
+ type: (module ?? 'esm') === 'esm' ? 'module' : 'commonjs'
195
104
  }));
196
- addDependenciesToPackageJson(tree, {}, {
197
- '@nx/workspace': readModulePackageJson('@nx/js').packageJson.version,
198
- ...withVersions([
199
- 'typescript',
200
- '@biomejs/biome'
201
- ])
202
- });
203
- // Write biome.json for formatting and linting
204
- if (!tree.exists('biome.json')) {
205
- tree.write('biome.json', JSON.stringify(DEFAULT_BIOME_CONFIG, null, 2));
206
- }
207
- generateFiles(tree, joinPathFragments(import.meta.dirname, 'files'), '.', {
208
- projectName: getNpmScope(tree),
209
- generators: Object.entries(GeneratorsJson.generators).filter(([_, v])=>!v['hidden']).map(([k, v])=>({
210
- name: k,
211
- description: v.description
212
- })),
213
- ...(()=>{
214
- const cmds = getPackageManagerDisplayCommands();
215
- return {
216
- pkgMgrCmd: cmds.exec,
217
- buildCmd: `${cmds.run} build`,
218
- lintCmd: `${cmds.run} lint`
219
- };
220
- })()
221
- }, {
222
- overwriteStrategy: OverwriteStrategy.Overwrite
105
+ // Apply the deterministic workspace configuration shared with the `init`
106
+ // generator. The preset owns the README of a greenfield workspace.
107
+ await applyWorkspaceInit(tree, {
108
+ iac,
109
+ containers,
110
+ mcp,
111
+ readmeOverwriteStrategy: OverwriteStrategy.Overwrite,
112
+ overwriteScripts: true
223
113
  });
114
+ tree.delete('apps/.gitkeep');
115
+ tree.delete('libs/.gitkeep');
116
+ tree.write('packages/.gitkeep', '');
224
117
  if (gitSecrets !== false) {
225
118
  setUpGitSecrets(tree);
226
119
  }
227
- if (mcp !== false) {
228
- configureMcpServers(tree);
229
- }
230
120
  await formatFilesInSubtree(tree);
231
121
  return ()=>installDependencies(tree, preferInstallDependencies, {
232
122
  languages: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/preset/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addDependenciesToPackageJson,\n detectPackageManager,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n readNxJson,\n type Tree,\n updateJson,\n updateNxJson,\n} from '@nx/devkit';\nimport { initGenerator } from '@nx/js';\nimport { execSync } from 'child_process';\nimport enquirer from 'enquirer';\nimport { readFileSync } from 'fs';\nimport yaml from 'js-yaml';\nimport { readModulePackageJson } from 'nx/src/utils/package-json';\nimport GeneratorsJson from '../../generators.json' with { type: 'json' };\nimport { SYNC_GENERATOR_NAME as TS_SYNC_GENERATOR_NAME } from '../ts/sync/generator';\nimport {\n ensureAwsNxPluginConfig,\n updateAwsNxPluginConfig,\n} from '../utils/config/utils';\nimport { inferContainers } from '../utils/containers';\nimport { DEFAULT_BIOME_CONFIG, formatFilesInSubtree } from '../utils/format';\nimport { installDependencies } from '../utils/install';\nimport { configureMcpServers } from '../utils/mcp';\nimport { addGeneratorMetricsIfApplicable } from '../utils/metrics';\nimport { getNpmScope } from '../utils/npm-scope';\nimport { getGeneratorInfo, type NxGeneratorInfo } from '../utils/nx';\nimport { getPackageManagerDisplayCommands } from '../utils/pkg-manager';\nimport { withVersions } from '../utils/versions';\nimport type { PresetGeneratorSchema } from './schema';\n\nconst WORKSPACES = ['packages/*'];\nconst NX_TYPESCRIPT_SYNC_GENERATOR = '@nx/js:typescript-sync';\n\n// Built dependencies whose install scripts the generated workspace trusts.\n// `onlyBuiltDependencies` is the pnpm 10 key (silently ignored by pnpm 11);\n// pnpm 11 reads `allowBuilds` instead. Any dep NOT in this allowlist will\n// have its install scripts skipped with a warning — matching pnpm 10's\n// default behaviour. The user can opt-in later via `pnpm approve-builds`.\nconst PNPM_BUILT_DEPENDENCIES = ['@swc/core', 'esbuild', 'nx', 'sharp'];\n\nexport const PRESET_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nconst setUpWorkspaces = (tree: Tree) => {\n if (detectPackageManager() === 'pnpm') {\n tree.write(\n 'pnpm-workspace.yaml',\n yaml.dump(\n {\n packages: WORKSPACES,\n allowBuilds: Object.fromEntries(\n PNPM_BUILT_DEPENDENCIES.map((dep) => [dep, true]),\n ),\n onlyBuiltDependencies: PNPM_BUILT_DEPENDENCIES,\n },\n { quotingType: \"'\" },\n ),\n );\n } else {\n updateJson(tree, 'package.json', (json) => {\n json.workspaces = WORKSPACES;\n return json;\n });\n }\n};\n\n/**\n * Determines if the current user is an Amazon employee based on their git configuration.\n *\n * This function checks the git user email configuration to identify Amazon employees\n * by looking for email addresses with Amazon domains (e.g., @amazon.com, @amazon.co.uk).\n *\n * @returns {boolean} True if the user's git email has an Amazon domain, false otherwise\n *\n * @example\n * // Returns true for Amazon employee emails\n * // git config user.email = \"john.doe@amazon.com\"\n * isAmazonian(); // true\n *\n * @example\n * // Returns false for non-Amazon emails\n * // git config user.email = \"user@example.com\"\n * isAmazonian(); // false\n *\n * @example\n * // Returns false when git config is not available or throws an error\n * isAmazonian(); // false\n */\nexport function isAmazonian(): boolean {\n try {\n // Execute git command to retrieve the user's configured email address\n const gitEmail = execSync('git config user.email', {\n encoding: 'utf8',\n }).trim();\n\n // Return false if no email is configured\n if (!gitEmail) {\n return false;\n }\n\n // Split email address to extract domain part\n const emailParts = gitEmail.split('@');\n if (emailParts.length < 2) {\n return false;\n }\n\n // Extract domain and normalize to lowercase for comparison\n const domain = emailParts[1].toLowerCase();\n\n // Check if domain starts with 'amazon.' (covers amazon.com, amazon.co.uk, etc.)\n return domain.startsWith('amazon.');\n } catch (error) {\n // Return false if git command fails or any other error occurs\n // This handles cases where git is not installed or configured\n return false;\n }\n}\n\nconst setUpGitSecrets = (tree: Tree) => {\n const gitSecretsDir = joinPathFragments(\n import.meta.dirname,\n 'git-secrets-files',\n 'git-secrets-dir',\n );\n const huskyDir = joinPathFragments(\n import.meta.dirname,\n 'git-secrets-files',\n 'husky-dir',\n );\n\n tree.write(\n '.git-secrets/git-secrets',\n readFileSync(joinPathFragments(gitSecretsDir, 'git-secrets'), 'utf-8'),\n );\n tree.write(\n '.husky/pre-commit',\n readFileSync(joinPathFragments(huskyDir, 'pre-commit'), 'utf-8'),\n );\n tree.write('.gitallowed', '\\\\.git-secrets/git-secrets:\\n');\n\n updateJson(tree, 'package.json', (json) => ({\n ...json,\n scripts: {\n ...json.scripts,\n prepare: 'husky',\n },\n }));\n\n addDependenciesToPackageJson(tree, {}, withVersions(['husky']));\n};\n\nexport const presetGenerator = async (\n tree: Tree,\n {\n iac,\n gitSecrets,\n mcp,\n containers,\n module,\n preferInstallDependencies,\n }: PresetGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const resolvedContainers =\n !containers || containers === 'infer' ? inferContainers() : containers;\n const esm = (module ?? 'esm') === 'esm';\n if (\n isAmazonian() &&\n !process.env.VITEST &&\n !process.env.CI &&\n process.env.NX_DRY_RUN !== 'true' &&\n process.env.NX_INTERACTIVE !== 'false'\n ) {\n const { engagementId } = await enquirer.prompt<{ engagementId?: string }>([\n {\n name: 'engagementId',\n message: 'Please enter your engagementId (if known)',\n type: 'input',\n initial: 'None',\n },\n ]);\n\n if (engagementId != 'None') {\n await ensureAwsNxPluginConfig(tree);\n await updateAwsNxPluginConfig(tree, { tags: [engagementId] });\n }\n }\n\n // Write IaC provider and container engine to plugin config\n await ensureAwsNxPluginConfig(tree);\n await updateAwsNxPluginConfig(tree, {\n iac: { provider: iac },\n containers: { engine: resolvedContainers },\n });\n\n await initGenerator(tree, {\n formatter: 'none',\n addTsPlugin: true,\n });\n\n tree.delete('apps/.gitkeep');\n tree.delete('libs/.gitkeep');\n tree.write('packages/.gitkeep', '');\n\n setUpWorkspaces(tree);\n\n const nxJson = readNxJson(tree);\n updateNxJson(tree, {\n ...nxJson,\n analytics: false,\n targetDefaults: {\n ...nxJson.targetDefaults,\n compile: {\n ...nxJson.targetDefaults?.compile,\n syncGenerators: [\n ...(nxJson.targetDefaults?.compile?.syncGenerators ?? []).filter(\n (g) =>\n ![TS_SYNC_GENERATOR_NAME, NX_TYPESCRIPT_SYNC_GENERATOR].includes(\n g,\n ),\n ),\n NX_TYPESCRIPT_SYNC_GENERATOR,\n TS_SYNC_GENERATOR_NAME,\n ],\n },\n },\n });\n\n updateJson(tree, 'package.json', (packageJson) => ({\n ...packageJson,\n // Written explicitly so later generators can infer the workspace's module\n // format from the root `type`.\n type: esm ? 'module' : 'commonjs',\n scripts: {\n ...packageJson.scripts,\n dev: 'nx run-many --target dev',\n build: 'nx run-many --target build',\n lint: 'nx run-many --target lint --configuration=fix',\n test: 'nx run-many --target test --all',\n 'build:skip-lint': 'nx run-many --target build --configuration=skip-lint',\n 'build:all': 'nx run-many --target build --all',\n 'affected:all': 'nx affected --target build',\n },\n }));\n\n addDependenciesToPackageJson(\n tree,\n {},\n {\n '@nx/workspace': readModulePackageJson('@nx/js').packageJson.version,\n ...withVersions(['typescript', '@biomejs/biome']),\n },\n );\n\n // Write biome.json for formatting and linting\n if (!tree.exists('biome.json')) {\n tree.write('biome.json', JSON.stringify(DEFAULT_BIOME_CONFIG, null, 2));\n }\n\n generateFiles(\n tree, // the virtual file system\n joinPathFragments(import.meta.dirname, 'files'),\n '.',\n {\n projectName: getNpmScope(tree),\n generators: Object.entries(GeneratorsJson.generators)\n .filter(([_, v]) => !v['hidden'])\n .map(([k, v]) => ({ name: k, description: v.description })),\n ...(() => {\n const cmds = getPackageManagerDisplayCommands();\n return {\n pkgMgrCmd: cmds.exec,\n buildCmd: `${cmds.run} build`,\n lintCmd: `${cmds.run} lint`,\n };\n })(),\n },\n {\n overwriteStrategy: OverwriteStrategy.Overwrite,\n },\n );\n\n if (gitSecrets !== false) {\n setUpGitSecrets(tree);\n }\n\n if (mcp !== false) {\n configureMcpServers(tree);\n }\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nexport default presetGenerator;\n"],"names":["addDependenciesToPackageJson","detectPackageManager","generateFiles","joinPathFragments","OverwriteStrategy","readNxJson","updateJson","updateNxJson","initGenerator","execSync","enquirer","readFileSync","yaml","readModulePackageJson","GeneratorsJson","type","SYNC_GENERATOR_NAME","TS_SYNC_GENERATOR_NAME","ensureAwsNxPluginConfig","updateAwsNxPluginConfig","inferContainers","DEFAULT_BIOME_CONFIG","formatFilesInSubtree","installDependencies","configureMcpServers","getNpmScope","getGeneratorInfo","getPackageManagerDisplayCommands","withVersions","WORKSPACES","NX_TYPESCRIPT_SYNC_GENERATOR","PNPM_BUILT_DEPENDENCIES","PRESET_GENERATOR_INFO","filename","setUpWorkspaces","tree","write","dump","packages","allowBuilds","Object","fromEntries","map","dep","onlyBuiltDependencies","quotingType","json","workspaces","isAmazonian","gitEmail","encoding","trim","emailParts","split","length","domain","toLowerCase","startsWith","error","setUpGitSecrets","gitSecretsDir","dirname","huskyDir","scripts","prepare","presetGenerator","iac","gitSecrets","mcp","containers","module","preferInstallDependencies","resolvedContainers","esm","process","env","VITEST","CI","NX_DRY_RUN","NX_INTERACTIVE","engagementId","prompt","name","message","initial","tags","provider","engine","formatter","addTsPlugin","delete","nxJson","analytics","targetDefaults","compile","syncGenerators","filter","g","includes","packageJson","dev","build","lint","test","version","exists","JSON","stringify","projectName","generators","entries","_","v","k","description","cmds","pkgMgrCmd","exec","buildCmd","run","lintCmd","overwriteStrategy","Overwrite","languages"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/preset/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addDependenciesToPackageJson,\n type GeneratorCallback,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { execSync } from 'child_process';\nimport enquirer from 'enquirer';\nimport { readFileSync } from 'fs';\nimport {\n ensureAwsNxPluginConfig,\n updateAwsNxPluginConfig,\n} from '../utils/config/utils';\nimport { formatFilesInSubtree } from '../utils/format';\nimport { applyWorkspaceInit } from '../utils/init';\nimport { installDependencies } from '../utils/install';\nimport { getGeneratorInfo, type NxGeneratorInfo } from '../utils/nx';\nimport { withVersions } from '../utils/versions';\nimport type { PresetGeneratorSchema } from './schema';\n\nexport const PRESET_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\n/**\n * Determines if the current user is an Amazon employee based on their git configuration.\n *\n * This function checks the git user email configuration to identify Amazon employees\n * by looking for email addresses with Amazon domains (e.g., @amazon.com, @amazon.co.uk).\n *\n * @returns {boolean} True if the user's git email has an Amazon domain, false otherwise\n *\n * @example\n * // Returns true for Amazon employee emails\n * // git config user.email = \"john.doe@amazon.com\"\n * isAmazonian(); // true\n *\n * @example\n * // Returns false for non-Amazon emails\n * // git config user.email = \"user@example.com\"\n * isAmazonian(); // false\n *\n * @example\n * // Returns false when git config is not available or throws an error\n * isAmazonian(); // false\n */\nexport function isAmazonian(): boolean {\n try {\n // Execute git command to retrieve the user's configured email address\n const gitEmail = execSync('git config user.email', {\n encoding: 'utf8',\n }).trim();\n\n // Return false if no email is configured\n if (!gitEmail) {\n return false;\n }\n\n // Split email address to extract domain part\n const emailParts = gitEmail.split('@');\n if (emailParts.length < 2) {\n return false;\n }\n\n // Extract domain and normalize to lowercase for comparison\n const domain = emailParts[1].toLowerCase();\n\n // Check if domain starts with 'amazon.' (covers amazon.com, amazon.co.uk, etc.)\n return domain.startsWith('amazon.');\n } catch (error) {\n // Return false if git command fails or any other error occurs\n // This handles cases where git is not installed or configured\n return false;\n }\n}\n\nconst setUpGitSecrets = (tree: Tree) => {\n const gitSecretsDir = joinPathFragments(\n import.meta.dirname,\n 'git-secrets-files',\n 'git-secrets-dir',\n );\n const huskyDir = joinPathFragments(\n import.meta.dirname,\n 'git-secrets-files',\n 'husky-dir',\n );\n\n tree.write(\n '.git-secrets/git-secrets',\n readFileSync(joinPathFragments(gitSecretsDir, 'git-secrets'), 'utf-8'),\n );\n tree.write(\n '.husky/pre-commit',\n readFileSync(joinPathFragments(huskyDir, 'pre-commit'), 'utf-8'),\n );\n tree.write('.gitallowed', '\\\\.git-secrets/git-secrets:\\n');\n\n updateJson(tree, 'package.json', (json) => ({\n ...json,\n scripts: {\n ...json.scripts,\n prepare: 'husky',\n },\n }));\n\n addDependenciesToPackageJson(tree, {}, withVersions(['husky']));\n};\n\nexport const presetGenerator = async (\n tree: Tree,\n {\n iac,\n gitSecrets,\n mcp,\n containers,\n module,\n preferInstallDependencies,\n }: PresetGeneratorSchema,\n): Promise<GeneratorCallback> => {\n if (\n isAmazonian() &&\n !process.env.VITEST &&\n !process.env.CI &&\n process.env.NX_DRY_RUN !== 'true' &&\n process.env.NX_INTERACTIVE !== 'false'\n ) {\n const { engagementId } = await enquirer.prompt<{ engagementId?: string }>([\n {\n name: 'engagementId',\n message: 'Please enter your engagementId (if known)',\n type: 'input',\n initial: 'None',\n },\n ]);\n\n if (engagementId != 'None') {\n await ensureAwsNxPluginConfig(tree);\n await updateAwsNxPluginConfig(tree, { tags: [engagementId] });\n }\n }\n\n // The preset owns the greenfield workspace's module format: write the root\n // `type` explicitly from the chosen `--module` so later generators can\n // infer it. The `init` generator never touches an existing workspace's\n // `type` field.\n updateJson(tree, 'package.json', (packageJson) => ({\n ...packageJson,\n type: (module ?? 'esm') === 'esm' ? 'module' : 'commonjs',\n }));\n\n // Apply the deterministic workspace configuration shared with the `init`\n // generator. The preset owns the README of a greenfield workspace.\n await applyWorkspaceInit(tree, {\n iac,\n containers,\n mcp,\n readmeOverwriteStrategy: OverwriteStrategy.Overwrite,\n overwriteScripts: true,\n });\n\n tree.delete('apps/.gitkeep');\n tree.delete('libs/.gitkeep');\n tree.write('packages/.gitkeep', '');\n\n if (gitSecrets !== false) {\n setUpGitSecrets(tree);\n }\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nexport default presetGenerator;\n"],"names":["addDependenciesToPackageJson","joinPathFragments","OverwriteStrategy","updateJson","execSync","enquirer","readFileSync","ensureAwsNxPluginConfig","updateAwsNxPluginConfig","formatFilesInSubtree","applyWorkspaceInit","installDependencies","getGeneratorInfo","withVersions","PRESET_GENERATOR_INFO","filename","isAmazonian","gitEmail","encoding","trim","emailParts","split","length","domain","toLowerCase","startsWith","error","setUpGitSecrets","tree","gitSecretsDir","dirname","huskyDir","write","json","scripts","prepare","presetGenerator","iac","gitSecrets","mcp","containers","module","preferInstallDependencies","process","env","VITEST","CI","NX_DRY_RUN","NX_INTERACTIVE","engagementId","prompt","name","message","type","initial","tags","packageJson","readmeOverwriteStrategy","Overwrite","overwriteScripts","delete","languages"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- FROM public.ecr.aws/docker/library/python:3.14-slim
1
+ FROM <%- pythonBaseImage %>
2
2
 
3
3
  WORKDIR /app
4
4
 
@@ -9,6 +9,7 @@ import { addPythonFrameworkBase, ensurePythonAgentConnectionProject, getPythonAg
9
9
  import { addAgentInfra } from "../../utils/agent-core-constructs/agent-core-constructs.js";
10
10
  import { addPythonBundleTarget } from "../../utils/bundle/bundle.js";
11
11
  import { resolveContainers } from "../../utils/containers.js";
12
+ import { addDockerScanTarget } from "../../utils/docker.js";
12
13
  import { formatFilesInSubtree } from "../../utils/format.js";
13
14
  import { FsCommands } from "../../utils/fs.js";
14
15
  import { updateGitIgnore } from "../../utils/git.js";
@@ -23,7 +24,7 @@ import { toProjectRelativePath } from "../../utils/paths.js";
23
24
  import { assignPort } from "../../utils/port.js";
24
25
  import { addDependenciesToDependencyGroupInPyProjectToml, addDependenciesToPyProjectToml, addWorkspaceDependencyToPyProject } from "../../utils/py.js";
25
26
  import { sharedConstructsGenerator } from "../../utils/shared-constructs.js";
26
- import { withVersions } from "../../utils/versions.js";
27
+ import { BASE_IMAGES, withVersions } from "../../utils/versions.js";
27
28
  export const PY_AGENT_GENERATOR_INFO = getGeneratorInfo(import.meta.filename);
28
29
  export const pyAgentGenerator = async (tree, options)=>{
29
30
  const project = readProjectConfigurationUnqualified(tree, options.project);
@@ -152,7 +153,8 @@ export const pyAgentGenerator = async (tree, options)=>{
152
153
  agentNameSnakeCase,
153
154
  moduleName,
154
155
  bundleOutputDir,
155
- protocol
156
+ protocol,
157
+ pythonBaseImage: BASE_IMAGES.python
156
158
  }, {
157
159
  overwriteStrategy: OverwriteStrategy.KeepExisting
158
160
  });
@@ -179,6 +181,15 @@ export const pyAgentGenerator = async (tree, options)=>{
179
181
  };
180
182
  addDependencyToTargetIfNotPresent(project, 'docker', dockerTargetName);
181
183
  addDependencyToTargetIfNotPresent(project, 'build', 'docker');
184
+ addDockerScanTarget(tree, {
185
+ project,
186
+ containerEngine: containers,
187
+ trivyTargetName: `${agentTargetPrefix}-trivy`,
188
+ dockerTargetName,
189
+ imageTags: [
190
+ dockerImageTag
191
+ ]
192
+ });
182
193
  // Add shared constructs
183
194
  const iac = await resolveIac(tree, options.iac);
184
195
  await sharedConstructsGenerator(tree, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/agent/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addDependenciesToPackageJson,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { ensureLicenseExceptions } from '../../license/config';\nimport { AG_UI_LANGGRAPH_EXCEPTIONS } from '../../license/known-exceptions';\nimport { addAgentChatScripts } from '../../utils/agent-chat/agent-chat';\nimport {\n addPythonFrameworkBase,\n ensurePythonAgentConnectionProject,\n getPythonAgentConnectionModuleName,\n getPythonAgentConnectionProject,\n} from '../../utils/agent-connection/agent-connection';\nimport { addAgentInfra } from '../../utils/agent-core-constructs/agent-core-constructs';\nimport { addPythonBundleTarget } from '../../utils/bundle/bundle';\nimport { resolveContainers } from '../../utils/containers';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { FsCommands } from '../../utils/fs';\nimport { updateGitIgnore } from '../../utils/git';\nimport { resolveIac } from '../../utils/iac';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport { kebabCase, toClassName, toSnakeCase } from '../../utils/names';\nimport { getNpmScope } from '../../utils/npm-scope';\nimport {\n addComponentDevTarget,\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n getGeneratorInfo,\n type NxGeneratorInfo,\n normalizeTargetKeyOrder,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport { toProjectRelativePath } from '../../utils/paths';\nimport { assignPort } from '../../utils/port';\nimport {\n addDependenciesToDependencyGroupInPyProjectToml,\n addDependenciesToPyProjectToml,\n addWorkspaceDependencyToPyProject,\n} from '../../utils/py';\nimport { sharedConstructsGenerator } from '../../utils/shared-constructs';\nimport { withVersions } from '../../utils/versions';\nimport type { PyAgentGeneratorSchema } from './schema';\n\nexport const PY_AGENT_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const pyAgentGenerator = async (\n tree: Tree,\n options: PyAgentGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const project = readProjectConfigurationUnqualified(tree, options.project);\n\n const pyProjectPath = joinPathFragments(project.root, 'pyproject.toml');\n\n // Check if the project has a pyproject.toml file\n if (!pyProjectPath) {\n throw new Error(\n `Unsupported project ${options.project}. Expected a Python project (with a pyproject.toml)`,\n );\n }\n\n if (!project.sourceRoot) {\n throw new Error(\n `This project does not have a source root. Please add a source root to the project configuration before running this generator.`,\n );\n }\n\n // Module name is the last part of the source root,\n const sourceParts = project.sourceRoot.split('/');\n const moduleName = sourceParts[sourceParts.length - 1];\n\n const name = kebabCase(\n options.name || `${kebabCase(project.name.split('.').pop())}-agent`,\n );\n const agentTargetPrefix = options.name ? name : 'agent';\n\n const agentNameSnakeCase = toSnakeCase(options.name || 'agent');\n const agentNameClassName = toClassName(name);\n\n const targetSourceDir = joinPathFragments(\n project.sourceRoot,\n agentNameSnakeCase,\n );\n\n const infra = options.infra ?? 'agentcore';\n const protocol = options.protocol ?? 'http';\n const framework = options.framework ?? 'strands';\n\n if (infra === 'none' && options.auth && options.auth !== 'iam') {\n console.warn(\n 'Warning: auth is ignored when no infrastructure is configured (no infrastructure is generated)',\n );\n }\n\n const auth = options.auth ?? 'iam';\n\n // Ensure the shared agent-connection project exists so the server entry\n // point can import `session_id_context` and propagate the AgentCore\n // session ID to any downstream MCP / A2A clients a later connection\n // generator wires into this agent.\n await ensurePythonAgentConnectionProject(tree);\n // The agent server imports the framework base helpers (session cache + model\n // error logging) regardless of whether a connection client is wired in. The\n // langchain framework has no base layer (its AG-UI foundation reuses only the\n // framework-agnostic session context), so this is a no-op for langchain.\n await addPythonFrameworkBase(tree, framework);\n const agentConnectionModuleName = getPythonAgentConnectionModuleName(tree);\n addWorkspaceDependencyToPyProject(\n tree,\n project,\n getPythonAgentConnectionProject(tree),\n );\n\n const templateContext = {\n name,\n agentNameSnakeCase,\n agentNameClassName,\n moduleName,\n agentConnectionModuleName,\n framework,\n };\n\n // Generate common files shared by both protocols. The agent module (agent.py)\n // is framework-specific (Strands yields a contextmanaged Agent; LangChain\n // returns a compiled create_agent graph), so it comes from a per-framework\n // dir. The package __init__.py is framework-agnostic (it stays in `common`).\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n framework === 'langchain' ? 'common-langchain' : 'common',\n ),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n if (framework === 'langchain') {\n // common-langchain only carries agent.py; the empty package __init__.py is\n // framework-agnostic, so emit it from the shared `common` dir.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'common'),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n }\n\n // Generate protocol-specific files. Each protocol's server entry point is\n // framework-specific (Strands yields a contextmanaged Agent; LangChain drives\n // a compiled create_agent graph), so it comes from a per-framework dir\n // `<protocol>-langchain` for LangChain, or `<protocol>` for Strands.\n const protocolLower = protocol.toLowerCase();\n const protocolTemplateDir =\n framework === 'langchain' ? `${protocolLower}-langchain` : protocolLower;\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', protocolTemplateDir),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n // The HTTP server's init.py (the FastAPI app + JsonStreamingResponse) is\n // framework-agnostic and the LangChain http main.py reuses it, so emit it\n // from the shared `http` dir. Emitted after the langchain main.py above so\n // KeepExisting preserves that main.py and only adds init.py (the shared dir's\n // own Strands main.py is skipped).\n if (protocolLower === 'http' && framework === 'langchain') {\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'http'),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n }\n\n addDependenciesToPyProjectToml(tree, project.root, [\n 'aws-lambda-powertools',\n 'aws-opentelemetry-distro',\n 'bedrock-agentcore',\n 'boto3',\n 'fastapi',\n 'mcp',\n ...(framework === 'langchain'\n ? // langchain pulls no Strands dependencies — the langchain model binding\n // (langchain, langchain-aws, langgraph) plus the per-protocol server\n // adapter: ag-ui-langgraph for AG-UI, a2a-sdk for A2A, nothing extra for\n // HTTP (FastAPI is added above for every agent).\n ([\n 'langchain',\n 'langchain-aws',\n 'langgraph',\n ...(protocol === 'ag-ui'\n ? (['ag-ui-protocol', 'ag-ui-langgraph'] as const)\n : protocol === 'a2a'\n ? (['a2a-sdk'] as const)\n : ([] as const)),\n ] as const)\n : protocol === 'a2a'\n ? (['strands-agents[a2a]', 'strands-agents-tools'] as const)\n : protocol === 'ag-ui'\n ? ([\n 'strands-agents',\n 'strands-agents-tools',\n 'ag-ui-protocol',\n 'ag-ui-strands',\n ] as const)\n : (['strands-agents', 'strands-agents-tools'] as const)),\n 'uvicorn',\n ]);\n addDependenciesToDependencyGroupInPyProjectToml(tree, project.root, 'dev', [\n 'fastapi[standard]',\n ]);\n\n if (infra === 'agentcore') {\n const containers = await resolveContainers(tree, 'inherit');\n const dockerImageTag = `${getNpmScope(tree)}-${name}:latest`;\n\n // Add bundle target\n const { bundleTargetName, bundleOutputDir } = addPythonBundleTarget(\n project,\n {\n pythonPlatform: 'aarch64-manylinux_2_28',\n },\n );\n\n // Add the Dockerfile\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'deploy'),\n targetSourceDir,\n {\n agentNameSnakeCase,\n moduleName,\n bundleOutputDir,\n protocol,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n const dockerOutputDir = joinPathFragments(\n 'dist',\n project.root,\n 'docker',\n name,\n );\n const dockerTargetName = `${agentTargetPrefix}-docker`;\n\n // Add a docker target that prepares the docker context and builds the image\n const fs = new FsCommands(tree);\n project.targets[dockerTargetName] = {\n cache: true,\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(dockerOutputDir),\n fs.mkdir(dockerOutputDir),\n fs.cp(bundleOutputDir, dockerOutputDir),\n fs.cp(\n `${targetSourceDir}/Dockerfile`,\n `${dockerOutputDir}/Dockerfile`,\n ),\n `${containers} build --platform linux/arm64 -t ${dockerImageTag} ${dockerOutputDir}`,\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName],\n };\n\n addDependencyToTargetIfNotPresent(project, 'docker', dockerTargetName);\n addDependencyToTargetIfNotPresent(project, 'build', 'docker');\n\n // Add shared constructs\n const iac = await resolveIac(tree, options.iac);\n await sharedConstructsGenerator(tree, { iac });\n\n // Add the construct to deploy the agent.\n // AG-UI uses HTTP as the AgentCore protocol type (AG-UI is HTTP-based with SSE over POST).\n const infraProtocol =\n protocol === 'ag-ui' ? ('http' as const) : (protocol as 'http' | 'a2a');\n await addAgentInfra(tree, {\n agentNameKebabCase: name,\n agentNameClassName,\n dockerImageTag,\n dockerOutputDir,\n iac,\n projectName: project.name,\n auth,\n serverProtocol: infraProtocol,\n containers,\n });\n }\n\n // A2A servers use port 9000 as per the Strands A2A SDK default and AgentCore A2A contract.\n // HTTP and AG-UI agents use port 8081+ to avoid conflict with VS Code server on 8080.\n const localDevPortStart = protocol === 'a2a' ? 9000 : 8081;\n const localDevPort = assignPort(tree, project, localDevPortStart, {\n component: { info: PY_AGENT_GENERATOR_INFO, name: agentTargetPrefix },\n });\n\n // All protocols use fastapi dev for hot reload:\n // - HTTP: FastAPI app directly defined in init.py\n // - A2A: A2AServer.to_fastapi_app() creates a FastAPI app in main.py\n // - AG-UI: create_strands_app() creates a FastAPI app in main.py\n const serveCommand = `uv run fastapi dev ${moduleName}/${agentNameSnakeCase}/main.py --port ${localDevPort}`;\n\n // HTTP chat uses the type-safe TypeScript client generated from the\n // agent's OpenAPI spec (same generated client the react-connection\n // generator produces). A2A and AG-UI speak standard protocols, so\n // we can run `agent-chat-cli` directly as a binary.\n const openApiTargetName = `${agentTargetPrefix}-openapi`;\n const clientGenTargetName = `${agentTargetPrefix}-generate-client`;\n\n const scriptsDir = joinPathFragments(\n project.root,\n 'scripts',\n agentTargetPrefix,\n );\n\n if (protocol === 'http') {\n // Emit the OpenAPI spec generator script (shared with react-connection)\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'react-connection',\n 'files',\n 'agent',\n ),\n project.root,\n {\n moduleName,\n agentNameSnakeCase,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // Ignore the generated client directory\n updateGitIgnore(tree, project.root, (patterns) => [\n ...patterns,\n `scripts/${agentTargetPrefix}/generated/`,\n ]);\n }\n\n // Every protocol gets a standalone `chat.ts`. It connects to the local\n // `dev` server by default, or to the deployed agent (with the\n // appropriate auth) when `RUNTIME_CONFIG_APP_ID` is set.\n addAgentChatScripts(tree, {\n scriptsDir,\n protocol,\n language: 'py',\n agentNameClassName,\n auth,\n });\n\n // TypeScript deps for the chat CLI, which runs standalone via tsx for every\n // protocol and resolves the deployed agent from AppConfig. `agent-chat-cli`\n // transitively bundles the protocol clients (@a2a-js/sdk, @ag-ui/client).\n addDependenciesToPackageJson(\n tree,\n {},\n withVersions([\n 'agent-chat-cli',\n 'tsx',\n '@types/node',\n '@aws-lambda-powertools/parameters',\n '@aws-sdk/client-appconfigdata',\n ...(auth === 'iam'\n ? (['aws4fetch', '@aws-sdk/credential-providers'] as const)\n : ([] as const)),\n ...(protocol === 'a2a' ? (['@a2a-js/sdk'] as const) : ([] as const)),\n ]),\n );\n\n const chatUrl =\n protocol === 'ag-ui'\n ? `http://localhost:${localDevPort}/invocations`\n : `http://localhost:${localDevPort}`;\n const chatCommand = `tsx ./scripts/${agentTargetPrefix}/chat.ts`;\n\n const httpOnlyTargets =\n protocol === 'http'\n ? {\n [openApiTargetName]: {\n cache: true,\n executor: 'nx:run-commands',\n outputs: [\n `{workspaceRoot}/dist/{projectRoot}/openapi/${agentNameSnakeCase}`,\n ],\n options: {\n commands: [\n `uv run python {projectRoot}/scripts/${agentNameSnakeCase}_openapi.py \"dist/{projectRoot}/openapi/${agentNameSnakeCase}/openapi.json\"`,\n ],\n },\n },\n [clientGenTargetName]: {\n cache: true,\n executor: 'nx:run-commands',\n dependsOn: [openApiTargetName],\n inputs: [\n {\n dependentTasksOutputFiles: '**/*.json',\n },\n ],\n outputs: [`{projectRoot}/scripts/${agentTargetPrefix}/generated`],\n options: {\n commands: [\n `nx g @aws/nx-plugin:open-api#ts-client --openApiSpecPath=\"dist/${project.root}/openapi/${agentNameSnakeCase}/openapi.json\" --outputPath=\"${project.root}/scripts/${agentTargetPrefix}/generated\" --no-interactive`,\n ],\n },\n },\n }\n : {};\n\n const agentTargets = {\n ...project.targets,\n ...httpOnlyTargets,\n [`${agentTargetPrefix}-serve`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [serveCommand],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n },\n },\n },\n [`${agentTargetPrefix}-dev`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [serveCommand],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n LOCAL_DEV: 'true',\n },\n },\n },\n // HTTP chat imports the generated client, so ensure it's built first.\n // No dev dependency — chat runs standalone against a local or\n // deployed agent. normalizeTargetKeyOrder keeps the conditional dependsOn\n // in Nx 23's serialization order so re-runs stay byte-identical.\n [`${agentTargetPrefix}-chat`]: normalizeTargetKeyOrder({\n executor: 'nx:run-commands',\n options: {\n commands: [chatCommand],\n cwd: '{projectRoot}',\n env: {\n URL: chatUrl,\n },\n },\n ...(protocol === 'http' ? { dependsOn: [clientGenTargetName] } : {}),\n }),\n };\n\n // Aggregate `<agent>-dev` under the project-level `dev` target.\n addComponentDevTarget(agentTargets, `${agentTargetPrefix}-dev`);\n\n updateProjectConfiguration(tree, project.name, {\n ...project,\n targets: sortObjectKeys(agentTargets),\n });\n\n addComponentGeneratorMetadata(\n tree,\n project.name,\n PY_AGENT_GENERATOR_INFO,\n toProjectRelativePath(project, targetSourceDir),\n agentTargetPrefix,\n {\n port: localDevPort,\n rc: agentNameClassName,\n auth,\n protocol,\n // The mcp / gateway connection generators dispatch on this field to pick\n // the Strands vs LangChain Layer-2 client + agent.py transform.\n framework,\n },\n );\n\n await addGeneratorMetricsIfApplicable(tree, [PY_AGENT_GENERATOR_INFO]);\n\n // langchain-core (pulled by every langchain agent regardless of protocol)\n // brings jsonpatch/jsonpointer, whose wheels ship without resolvable SPDX\n // license metadata, so register those exceptions so the workspace license\n // check still passes.\n if (framework === 'langchain') {\n await ensureLicenseExceptions(tree, AG_UI_LANGGRAPH_EXCEPTIONS);\n }\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\n\nexport default pyAgentGenerator;\n"],"names":["addDependenciesToPackageJson","generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","ensureLicenseExceptions","AG_UI_LANGGRAPH_EXCEPTIONS","addAgentChatScripts","addPythonFrameworkBase","ensurePythonAgentConnectionProject","getPythonAgentConnectionModuleName","getPythonAgentConnectionProject","addAgentInfra","addPythonBundleTarget","resolveContainers","formatFilesInSubtree","FsCommands","updateGitIgnore","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toSnakeCase","getNpmScope","addComponentDevTarget","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","normalizeTargetKeyOrder","readProjectConfigurationUnqualified","sortObjectKeys","toProjectRelativePath","assignPort","addDependenciesToDependencyGroupInPyProjectToml","addDependenciesToPyProjectToml","addWorkspaceDependencyToPyProject","sharedConstructsGenerator","withVersions","PY_AGENT_GENERATOR_INFO","filename","pyAgentGenerator","tree","options","project","pyProjectPath","root","Error","sourceRoot","sourceParts","split","moduleName","length","name","pop","agentTargetPrefix","agentNameSnakeCase","agentNameClassName","targetSourceDir","infra","protocol","framework","auth","console","warn","agentConnectionModuleName","templateContext","dirname","overwriteStrategy","KeepExisting","protocolLower","toLowerCase","protocolTemplateDir","containers","dockerImageTag","bundleTargetName","bundleOutputDir","pythonPlatform","dockerOutputDir","dockerTargetName","fs","targets","cache","executor","commands","rm","mkdir","cp","parallel","dependsOn","iac","infraProtocol","agentNameKebabCase","projectName","serverProtocol","localDevPortStart","localDevPort","component","info","serveCommand","openApiTargetName","clientGenTargetName","scriptsDir","patterns","language","chatUrl","chatCommand","httpOnlyTargets","outputs","inputs","dependentTasksOutputFiles","agentTargets","continuous","cwd","env","PORT","LOCAL_DEV","URL","port","rc","preferInstallDependencies","languages"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/agent/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n addDependenciesToPackageJson,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { ensureLicenseExceptions } from '../../license/config';\nimport { AG_UI_LANGGRAPH_EXCEPTIONS } from '../../license/known-exceptions';\nimport { addAgentChatScripts } from '../../utils/agent-chat/agent-chat';\nimport {\n addPythonFrameworkBase,\n ensurePythonAgentConnectionProject,\n getPythonAgentConnectionModuleName,\n getPythonAgentConnectionProject,\n} from '../../utils/agent-connection/agent-connection';\nimport { addAgentInfra } from '../../utils/agent-core-constructs/agent-core-constructs';\nimport { addPythonBundleTarget } from '../../utils/bundle/bundle';\nimport { resolveContainers } from '../../utils/containers';\nimport { addDockerScanTarget } from '../../utils/docker';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { FsCommands } from '../../utils/fs';\nimport { updateGitIgnore } from '../../utils/git';\nimport { resolveIac } from '../../utils/iac';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport { kebabCase, toClassName, toSnakeCase } from '../../utils/names';\nimport { getNpmScope } from '../../utils/npm-scope';\nimport {\n addComponentDevTarget,\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n getGeneratorInfo,\n type NxGeneratorInfo,\n normalizeTargetKeyOrder,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport { toProjectRelativePath } from '../../utils/paths';\nimport { assignPort } from '../../utils/port';\nimport {\n addDependenciesToDependencyGroupInPyProjectToml,\n addDependenciesToPyProjectToml,\n addWorkspaceDependencyToPyProject,\n} from '../../utils/py';\nimport { sharedConstructsGenerator } from '../../utils/shared-constructs';\nimport { BASE_IMAGES, withVersions } from '../../utils/versions';\nimport type { PyAgentGeneratorSchema } from './schema';\n\nexport const PY_AGENT_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const pyAgentGenerator = async (\n tree: Tree,\n options: PyAgentGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const project = readProjectConfigurationUnqualified(tree, options.project);\n\n const pyProjectPath = joinPathFragments(project.root, 'pyproject.toml');\n\n // Check if the project has a pyproject.toml file\n if (!pyProjectPath) {\n throw new Error(\n `Unsupported project ${options.project}. Expected a Python project (with a pyproject.toml)`,\n );\n }\n\n if (!project.sourceRoot) {\n throw new Error(\n `This project does not have a source root. Please add a source root to the project configuration before running this generator.`,\n );\n }\n\n // Module name is the last part of the source root,\n const sourceParts = project.sourceRoot.split('/');\n const moduleName = sourceParts[sourceParts.length - 1];\n\n const name = kebabCase(\n options.name || `${kebabCase(project.name.split('.').pop())}-agent`,\n );\n const agentTargetPrefix = options.name ? name : 'agent';\n\n const agentNameSnakeCase = toSnakeCase(options.name || 'agent');\n const agentNameClassName = toClassName(name);\n\n const targetSourceDir = joinPathFragments(\n project.sourceRoot,\n agentNameSnakeCase,\n );\n\n const infra = options.infra ?? 'agentcore';\n const protocol = options.protocol ?? 'http';\n const framework = options.framework ?? 'strands';\n\n if (infra === 'none' && options.auth && options.auth !== 'iam') {\n console.warn(\n 'Warning: auth is ignored when no infrastructure is configured (no infrastructure is generated)',\n );\n }\n\n const auth = options.auth ?? 'iam';\n\n // Ensure the shared agent-connection project exists so the server entry\n // point can import `session_id_context` and propagate the AgentCore\n // session ID to any downstream MCP / A2A clients a later connection\n // generator wires into this agent.\n await ensurePythonAgentConnectionProject(tree);\n // The agent server imports the framework base helpers (session cache + model\n // error logging) regardless of whether a connection client is wired in. The\n // langchain framework has no base layer (its AG-UI foundation reuses only the\n // framework-agnostic session context), so this is a no-op for langchain.\n await addPythonFrameworkBase(tree, framework);\n const agentConnectionModuleName = getPythonAgentConnectionModuleName(tree);\n addWorkspaceDependencyToPyProject(\n tree,\n project,\n getPythonAgentConnectionProject(tree),\n );\n\n const templateContext = {\n name,\n agentNameSnakeCase,\n agentNameClassName,\n moduleName,\n agentConnectionModuleName,\n framework,\n };\n\n // Generate common files shared by both protocols. The agent module (agent.py)\n // is framework-specific (Strands yields a contextmanaged Agent; LangChain\n // returns a compiled create_agent graph), so it comes from a per-framework\n // dir. The package __init__.py is framework-agnostic (it stays in `common`).\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n framework === 'langchain' ? 'common-langchain' : 'common',\n ),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n if (framework === 'langchain') {\n // common-langchain only carries agent.py; the empty package __init__.py is\n // framework-agnostic, so emit it from the shared `common` dir.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'common'),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n }\n\n // Generate protocol-specific files. Each protocol's server entry point is\n // framework-specific (Strands yields a contextmanaged Agent; LangChain drives\n // a compiled create_agent graph), so it comes from a per-framework dir\n // `<protocol>-langchain` for LangChain, or `<protocol>` for Strands.\n const protocolLower = protocol.toLowerCase();\n const protocolTemplateDir =\n framework === 'langchain' ? `${protocolLower}-langchain` : protocolLower;\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', protocolTemplateDir),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n // The HTTP server's init.py (the FastAPI app + JsonStreamingResponse) is\n // framework-agnostic and the LangChain http main.py reuses it, so emit it\n // from the shared `http` dir. Emitted after the langchain main.py above so\n // KeepExisting preserves that main.py and only adds init.py (the shared dir's\n // own Strands main.py is skipped).\n if (protocolLower === 'http' && framework === 'langchain') {\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'http'),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n }\n\n addDependenciesToPyProjectToml(tree, project.root, [\n 'aws-lambda-powertools',\n 'aws-opentelemetry-distro',\n 'bedrock-agentcore',\n 'boto3',\n 'fastapi',\n 'mcp',\n ...(framework === 'langchain'\n ? // langchain pulls no Strands dependencies — the langchain model binding\n // (langchain, langchain-aws, langgraph) plus the per-protocol server\n // adapter: ag-ui-langgraph for AG-UI, a2a-sdk for A2A, nothing extra for\n // HTTP (FastAPI is added above for every agent).\n ([\n 'langchain',\n 'langchain-aws',\n 'langgraph',\n ...(protocol === 'ag-ui'\n ? (['ag-ui-protocol', 'ag-ui-langgraph'] as const)\n : protocol === 'a2a'\n ? (['a2a-sdk'] as const)\n : ([] as const)),\n ] as const)\n : protocol === 'a2a'\n ? (['strands-agents[a2a]', 'strands-agents-tools'] as const)\n : protocol === 'ag-ui'\n ? ([\n 'strands-agents',\n 'strands-agents-tools',\n 'ag-ui-protocol',\n 'ag-ui-strands',\n ] as const)\n : (['strands-agents', 'strands-agents-tools'] as const)),\n 'uvicorn',\n ]);\n addDependenciesToDependencyGroupInPyProjectToml(tree, project.root, 'dev', [\n 'fastapi[standard]',\n ]);\n\n if (infra === 'agentcore') {\n const containers = await resolveContainers(tree, 'inherit');\n const dockerImageTag = `${getNpmScope(tree)}-${name}:latest`;\n\n // Add bundle target\n const { bundleTargetName, bundleOutputDir } = addPythonBundleTarget(\n project,\n {\n pythonPlatform: 'aarch64-manylinux_2_28',\n },\n );\n\n // Add the Dockerfile\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'deploy'),\n targetSourceDir,\n {\n agentNameSnakeCase,\n moduleName,\n bundleOutputDir,\n protocol,\n pythonBaseImage: BASE_IMAGES.python,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n const dockerOutputDir = joinPathFragments(\n 'dist',\n project.root,\n 'docker',\n name,\n );\n const dockerTargetName = `${agentTargetPrefix}-docker`;\n\n // Add a docker target that prepares the docker context and builds the image\n const fs = new FsCommands(tree);\n project.targets[dockerTargetName] = {\n cache: true,\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(dockerOutputDir),\n fs.mkdir(dockerOutputDir),\n fs.cp(bundleOutputDir, dockerOutputDir),\n fs.cp(\n `${targetSourceDir}/Dockerfile`,\n `${dockerOutputDir}/Dockerfile`,\n ),\n `${containers} build --platform linux/arm64 -t ${dockerImageTag} ${dockerOutputDir}`,\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName],\n };\n\n addDependencyToTargetIfNotPresent(project, 'docker', dockerTargetName);\n addDependencyToTargetIfNotPresent(project, 'build', 'docker');\n\n addDockerScanTarget(tree, {\n project,\n containerEngine: containers,\n trivyTargetName: `${agentTargetPrefix}-trivy`,\n dockerTargetName,\n imageTags: [dockerImageTag],\n });\n\n // Add shared constructs\n const iac = await resolveIac(tree, options.iac);\n await sharedConstructsGenerator(tree, { iac });\n\n // Add the construct to deploy the agent.\n // AG-UI uses HTTP as the AgentCore protocol type (AG-UI is HTTP-based with SSE over POST).\n const infraProtocol =\n protocol === 'ag-ui' ? ('http' as const) : (protocol as 'http' | 'a2a');\n await addAgentInfra(tree, {\n agentNameKebabCase: name,\n agentNameClassName,\n dockerImageTag,\n dockerOutputDir,\n iac,\n projectName: project.name,\n auth,\n serverProtocol: infraProtocol,\n containers,\n });\n }\n\n // A2A servers use port 9000 as per the Strands A2A SDK default and AgentCore A2A contract.\n // HTTP and AG-UI agents use port 8081+ to avoid conflict with VS Code server on 8080.\n const localDevPortStart = protocol === 'a2a' ? 9000 : 8081;\n const localDevPort = assignPort(tree, project, localDevPortStart, {\n component: { info: PY_AGENT_GENERATOR_INFO, name: agentTargetPrefix },\n });\n\n // All protocols use fastapi dev for hot reload:\n // - HTTP: FastAPI app directly defined in init.py\n // - A2A: A2AServer.to_fastapi_app() creates a FastAPI app in main.py\n // - AG-UI: create_strands_app() creates a FastAPI app in main.py\n const serveCommand = `uv run fastapi dev ${moduleName}/${agentNameSnakeCase}/main.py --port ${localDevPort}`;\n\n // HTTP chat uses the type-safe TypeScript client generated from the\n // agent's OpenAPI spec (same generated client the react-connection\n // generator produces). A2A and AG-UI speak standard protocols, so\n // we can run `agent-chat-cli` directly as a binary.\n const openApiTargetName = `${agentTargetPrefix}-openapi`;\n const clientGenTargetName = `${agentTargetPrefix}-generate-client`;\n\n const scriptsDir = joinPathFragments(\n project.root,\n 'scripts',\n agentTargetPrefix,\n );\n\n if (protocol === 'http') {\n // Emit the OpenAPI spec generator script (shared with react-connection)\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'react-connection',\n 'files',\n 'agent',\n ),\n project.root,\n {\n moduleName,\n agentNameSnakeCase,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // Ignore the generated client directory\n updateGitIgnore(tree, project.root, (patterns) => [\n ...patterns,\n `scripts/${agentTargetPrefix}/generated/`,\n ]);\n }\n\n // Every protocol gets a standalone `chat.ts`. It connects to the local\n // `dev` server by default, or to the deployed agent (with the\n // appropriate auth) when `RUNTIME_CONFIG_APP_ID` is set.\n addAgentChatScripts(tree, {\n scriptsDir,\n protocol,\n language: 'py',\n agentNameClassName,\n auth,\n });\n\n // TypeScript deps for the chat CLI, which runs standalone via tsx for every\n // protocol and resolves the deployed agent from AppConfig. `agent-chat-cli`\n // transitively bundles the protocol clients (@a2a-js/sdk, @ag-ui/client).\n addDependenciesToPackageJson(\n tree,\n {},\n withVersions([\n 'agent-chat-cli',\n 'tsx',\n '@types/node',\n '@aws-lambda-powertools/parameters',\n '@aws-sdk/client-appconfigdata',\n ...(auth === 'iam'\n ? (['aws4fetch', '@aws-sdk/credential-providers'] as const)\n : ([] as const)),\n ...(protocol === 'a2a' ? (['@a2a-js/sdk'] as const) : ([] as const)),\n ]),\n );\n\n const chatUrl =\n protocol === 'ag-ui'\n ? `http://localhost:${localDevPort}/invocations`\n : `http://localhost:${localDevPort}`;\n const chatCommand = `tsx ./scripts/${agentTargetPrefix}/chat.ts`;\n\n const httpOnlyTargets =\n protocol === 'http'\n ? {\n [openApiTargetName]: {\n cache: true,\n executor: 'nx:run-commands',\n outputs: [\n `{workspaceRoot}/dist/{projectRoot}/openapi/${agentNameSnakeCase}`,\n ],\n options: {\n commands: [\n `uv run python {projectRoot}/scripts/${agentNameSnakeCase}_openapi.py \"dist/{projectRoot}/openapi/${agentNameSnakeCase}/openapi.json\"`,\n ],\n },\n },\n [clientGenTargetName]: {\n cache: true,\n executor: 'nx:run-commands',\n dependsOn: [openApiTargetName],\n inputs: [\n {\n dependentTasksOutputFiles: '**/*.json',\n },\n ],\n outputs: [`{projectRoot}/scripts/${agentTargetPrefix}/generated`],\n options: {\n commands: [\n `nx g @aws/nx-plugin:open-api#ts-client --openApiSpecPath=\"dist/${project.root}/openapi/${agentNameSnakeCase}/openapi.json\" --outputPath=\"${project.root}/scripts/${agentTargetPrefix}/generated\" --no-interactive`,\n ],\n },\n },\n }\n : {};\n\n const agentTargets = {\n ...project.targets,\n ...httpOnlyTargets,\n [`${agentTargetPrefix}-serve`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [serveCommand],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n },\n },\n },\n [`${agentTargetPrefix}-dev`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [serveCommand],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n LOCAL_DEV: 'true',\n },\n },\n },\n // HTTP chat imports the generated client, so ensure it's built first.\n // No dev dependency — chat runs standalone against a local or\n // deployed agent. normalizeTargetKeyOrder keeps the conditional dependsOn\n // in Nx 23's serialization order so re-runs stay byte-identical.\n [`${agentTargetPrefix}-chat`]: normalizeTargetKeyOrder({\n executor: 'nx:run-commands',\n options: {\n commands: [chatCommand],\n cwd: '{projectRoot}',\n env: {\n URL: chatUrl,\n },\n },\n ...(protocol === 'http' ? { dependsOn: [clientGenTargetName] } : {}),\n }),\n };\n\n // Aggregate `<agent>-dev` under the project-level `dev` target.\n addComponentDevTarget(agentTargets, `${agentTargetPrefix}-dev`);\n\n updateProjectConfiguration(tree, project.name, {\n ...project,\n targets: sortObjectKeys(agentTargets),\n });\n\n addComponentGeneratorMetadata(\n tree,\n project.name,\n PY_AGENT_GENERATOR_INFO,\n toProjectRelativePath(project, targetSourceDir),\n agentTargetPrefix,\n {\n port: localDevPort,\n rc: agentNameClassName,\n auth,\n protocol,\n // The mcp / gateway connection generators dispatch on this field to pick\n // the Strands vs LangChain Layer-2 client + agent.py transform.\n framework,\n },\n );\n\n await addGeneratorMetricsIfApplicable(tree, [PY_AGENT_GENERATOR_INFO]);\n\n // langchain-core (pulled by every langchain agent regardless of protocol)\n // brings jsonpatch/jsonpointer, whose wheels ship without resolvable SPDX\n // license metadata, so register those exceptions so the workspace license\n // check still passes.\n if (framework === 'langchain') {\n await ensureLicenseExceptions(tree, AG_UI_LANGGRAPH_EXCEPTIONS);\n }\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\n\nexport default pyAgentGenerator;\n"],"names":["addDependenciesToPackageJson","generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","ensureLicenseExceptions","AG_UI_LANGGRAPH_EXCEPTIONS","addAgentChatScripts","addPythonFrameworkBase","ensurePythonAgentConnectionProject","getPythonAgentConnectionModuleName","getPythonAgentConnectionProject","addAgentInfra","addPythonBundleTarget","resolveContainers","addDockerScanTarget","formatFilesInSubtree","FsCommands","updateGitIgnore","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toSnakeCase","getNpmScope","addComponentDevTarget","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","normalizeTargetKeyOrder","readProjectConfigurationUnqualified","sortObjectKeys","toProjectRelativePath","assignPort","addDependenciesToDependencyGroupInPyProjectToml","addDependenciesToPyProjectToml","addWorkspaceDependencyToPyProject","sharedConstructsGenerator","BASE_IMAGES","withVersions","PY_AGENT_GENERATOR_INFO","filename","pyAgentGenerator","tree","options","project","pyProjectPath","root","Error","sourceRoot","sourceParts","split","moduleName","length","name","pop","agentTargetPrefix","agentNameSnakeCase","agentNameClassName","targetSourceDir","infra","protocol","framework","auth","console","warn","agentConnectionModuleName","templateContext","dirname","overwriteStrategy","KeepExisting","protocolLower","toLowerCase","protocolTemplateDir","containers","dockerImageTag","bundleTargetName","bundleOutputDir","pythonPlatform","pythonBaseImage","python","dockerOutputDir","dockerTargetName","fs","targets","cache","executor","commands","rm","mkdir","cp","parallel","dependsOn","containerEngine","trivyTargetName","imageTags","iac","infraProtocol","agentNameKebabCase","projectName","serverProtocol","localDevPortStart","localDevPort","component","info","serveCommand","openApiTargetName","clientGenTargetName","scriptsDir","patterns","language","chatUrl","chatCommand","httpOnlyTargets","outputs","inputs","dependentTasksOutputFiles","agentTargets","continuous","cwd","env","PORT","LOCAL_DEV","URL","port","rc","preferInstallDependencies","languages"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- FROM public.ecr.aws/docker/library/python:3.14-slim
1
+ FROM <%- pythonBaseImage %>
2
2
 
3
3
  WORKDIR /app
4
4
 
@@ -7,6 +7,7 @@ import { MCP_INSPECTOR_EXCEPTIONS } from "../../license/known-exceptions.js";
7
7
  import { addMcpServerInfra } from "../../utils/agent-core-constructs/agent-core-constructs.js";
8
8
  import { addPythonBundleTarget } from "../../utils/bundle/bundle.js";
9
9
  import { resolveContainers } from "../../utils/containers.js";
10
+ import { addDockerScanTarget } from "../../utils/docker.js";
10
11
  import { formatFilesInSubtree } from "../../utils/format.js";
11
12
  import { FsCommands } from "../../utils/fs.js";
12
13
  import { resolveIac } from "../../utils/iac.js";
@@ -19,7 +20,7 @@ import { toProjectRelativePath } from "../../utils/paths.js";
19
20
  import { assignPort } from "../../utils/port.js";
20
21
  import { addDependenciesToPyProjectToml } from "../../utils/py.js";
21
22
  import { sharedConstructsGenerator } from "../../utils/shared-constructs.js";
22
- import { withVersions } from "../../utils/versions.js";
23
+ import { BASE_IMAGES, withVersions } from "../../utils/versions.js";
23
24
  export const PY_MCP_SERVER_GENERATOR_INFO = getGeneratorInfo(import.meta.filename);
24
25
  export const pyMcpServerGenerator = async (tree, options)=>{
25
26
  const project = readProjectConfigurationUnqualified(tree, options.project);
@@ -70,7 +71,8 @@ export const pyMcpServerGenerator = async (tree, options)=>{
70
71
  generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'deploy'), targetSourceDir, {
71
72
  mcpServerNameSnakeCase,
72
73
  moduleName,
73
- bundleOutputDir
74
+ bundleOutputDir,
75
+ pythonBaseImage: BASE_IMAGES.python
74
76
  }, {
75
77
  overwriteStrategy: OverwriteStrategy.KeepExisting
76
78
  });
@@ -97,6 +99,15 @@ export const pyMcpServerGenerator = async (tree, options)=>{
97
99
  };
98
100
  addDependencyToTargetIfNotPresent(project, 'docker', dockerTargetName);
99
101
  addDependencyToTargetIfNotPresent(project, 'build', 'docker');
102
+ addDockerScanTarget(tree, {
103
+ project,
104
+ containerEngine: containers,
105
+ trivyTargetName: `${mcpTargetPrefix}-trivy`,
106
+ dockerTargetName,
107
+ imageTags: [
108
+ dockerImageTag
109
+ ]
110
+ });
100
111
  // Add shared constructs
101
112
  const iac = await resolveIac(tree, options.iac);
102
113
  await sharedConstructsGenerator(tree, {