@aws/nx-plugin 1.3.1 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/migrations.json CHANGED
@@ -7,6 +7,11 @@
7
7
  "description": "Turn off Biome 2.6's Markdown and YAML formatting in biome.json, which formats them by default",
8
8
  "implementation": "./src/migrations/latest/biome-markdown-yaml-formatter-off/migration"
9
9
  },
10
+ "latest-py-agentcore-launcher": {
11
+ "version": "1.3.2",
12
+ "description": "Launch Python AgentCore code with the managed interpreter",
13
+ "implementation": "./src/migrations/latest/py-agentcore-launcher/migration"
14
+ },
10
15
  "v1.0.0-rc.50-0001-modernize-function-props-cast": {
11
16
  "version": "1.0.0-rc.50",
12
17
  "description": "Replace the legacy angle-bracket FunctionProps type assertion with the modern as syntax in generated API constructs",
@@ -438,7 +443,7 @@
438
443
  "implementation": "./src/migrations/v1.3.0/0001-ts-agent-guardrails-terraform-version-retention/migration"
439
444
  },
440
445
  "sync-vended-versions": {
441
- "version": "1.3.1",
446
+ "version": "1.3.2",
442
447
  "description": "Sync vended dependency versions and the tracked plugin version to those vended by this release",
443
448
  "implementation": "./src/utils/version-upgrade-migration/migration"
444
449
  }
@@ -610,7 +615,7 @@
610
615
  }
611
616
  },
612
617
  "nx-23.3.1-nx-packages": {
613
- "version": "1.3.1",
618
+ "version": "1.3.2",
614
619
  "packages": {
615
620
  "nx": {
616
621
  "version": "23.3.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws/nx-plugin",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/awslabs/nx-plugin-for-aws.git",
@@ -0,0 +1,3 @@
1
+ {
2
+ "description": "Launch Python AgentCore code with the managed interpreter"
3
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { type MigrationReturnObject, type Tree } from '@nx/devkit';
6
+ /** Add the interpreter-safe launcher without changing the user's main.py or application. */
7
+ export default function migration(tree: Tree): Promise<MigrationReturnObject>;
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */ import { basename } from "node:path";
5
+ import { getProjects, joinPathFragments, updateProjectConfiguration } from "@nx/devkit";
6
+ import { PY_AGENT_GENERATOR_INFO } from "../../../py/agent/generator.js";
7
+ import { PY_MCP_SERVER_GENERATOR_INFO } from "../../../py/mcp-server/generator.js";
8
+ import { applyGritQL, matchGritQL } from "../../../utils/ast.js";
9
+ import { formatFilesInSubtree } from "../../../utils/format.js";
10
+ import { kebabCase } from "../../../utils/names.js";
11
+ const TERRAFORM_RUNTIME = 'packages/common/terraform/src/core/agent-core-code/runtime.tf';
12
+ const PYTHON_AGENT_CORE_LAUNCHER = 'agentcore_launcher.py';
13
+ const launcher = `\
14
+ import sys
15
+ from pathlib import Path
16
+
17
+ from opentelemetry.instrumentation.auto_instrumentation import run
18
+
19
+ if __name__ == "__main__":
20
+ sys.argv = [
21
+ "opentelemetry-instrument",
22
+ sys.executable,
23
+ str(Path(__file__).with_name("main.py")),
24
+ *sys.argv[1:],
25
+ ]
26
+ run()
27
+ `;
28
+ const terraformEntry = 'entry_point = var.code_entry_point == "agentcore_launcher.py" ? [var.code_entry_point] : ["opentelemetry-instrument", var.code_entry_point]';
29
+ const oldTerraformEntry = 'entry_point = ["opentelemetry-instrument", var.code_entry_point]';
30
+ const hcl = (pattern)=>`language hcl\n${pattern}`;
31
+ const terraformInput = (entryPoint)=>`\`module "agent_core_runtime" { $body }\` where { $body <: contains \`code_runtime = $runtime\`, $runtime <: r".*PYTHON_.*", $body <: contains \`code_entry_point = "${entryPoint}"\` }`;
32
+ const cdkInput = (entryPoint)=>`\`AgentRuntimeArtifact.fromCodeAsset({ $props })\` where { $props <: contains \`runtime: AgentCoreRuntime.$runtime\`, $runtime <: r"PYTHON_.*", $props <: contains \`entrypoint: ${entryPoint}\` }`;
33
+ /** Add the interpreter-safe launcher without changing the user's main.py or application. */ export default async function migration(tree) {
34
+ const nextSteps = [];
35
+ if (tree.exists(TERRAFORM_RUNTIME) && await matchGritQL(tree, TERRAFORM_RUNTIME, hcl(`\`${oldTerraformEntry}\``))) {
36
+ await applyGritQL(tree, TERRAFORM_RUNTIME, hcl(`\`${oldTerraformEntry}\` => \`${terraformEntry}\``));
37
+ }
38
+ const coreMigrated = tree.exists(TERRAFORM_RUNTIME) && await matchGritQL(tree, TERRAFORM_RUNTIME, hcl(`\`${terraformEntry}\``));
39
+ for (const project of getProjects(tree).values()){
40
+ const components = project.metadata?.components ?? [];
41
+ let changed = false;
42
+ for (const component of components){
43
+ const agent = component.generator === PY_AGENT_GENERATOR_INFO.id;
44
+ if (!agent && component.generator !== PY_MCP_SERVER_GENERATOR_INFO.id || component.infra !== 'agentcore') {
45
+ continue;
46
+ }
47
+ const terraform = component.iac === 'terraform';
48
+ const targetName = `${component.name}-package`;
49
+ const target = project.targets?.[targetName];
50
+ const name = kebabCase(component.rc ?? '');
51
+ const packageDir = joinPathFragments(project.root, 'package', basename(component.path ?? ''));
52
+ const outputDir = joinPathFragments('dist', project.root, 'package', name);
53
+ const launcherPath = joinPathFragments(packageDir, PYTHON_AGENT_CORE_LAUNCHER);
54
+ const copyLauncher = `shx cp ${launcherPath} ${outputDir}/${PYTHON_AGENT_CORE_LAUNCHER}`;
55
+ const commands = target?.options?.commands;
56
+ const expectedCommands = [
57
+ `shx rm -rf ${outputDir}`,
58
+ `shx mkdir -p ${outputDir}`,
59
+ `shx cp -R dist/${project.root}/bundle-arm/. ${outputDir}`,
60
+ `shx cp -R ${project.sourceRoot}/. ${outputDir}/${basename(project.sourceRoot ?? '')}`,
61
+ `shx cp ${packageDir}/main.py ${outputDir}/main.py`
62
+ ];
63
+ const category = agent ? 'agents' : 'mcp-servers';
64
+ const infraPath = terraform ? `packages/common/terraform/src/app/${category}/${name}/${name}.tf` : `packages/common/constructs/src/app/${category}/${name}/${name}.ts`;
65
+ const report = ()=>nextSteps.push(`${project.name}/${component.name}: review customized packaging or ${infraPath}; add ${PYTHON_AGENT_CORE_LAUNCHER} calling OpenTelemetry run() with sys.executable and main.py, copy it to the package root, and select it as this Python runtime's code entrypoint.`);
66
+ if (!component.path || !component.rc || ![
67
+ 'cdk',
68
+ 'terraform'
69
+ ].includes(component.iac) || target?.executor !== 'nx:run-commands' || target.options?.parallel !== false || !Array.isArray(commands) || ![
70
+ 5,
71
+ 6
72
+ ].includes(commands.length) || expectedCommands.some((command, index)=>commands[index] !== command) || commands.length === 6 && commands[5] !== copyLauncher || !tree.exists(`${packageDir}/main.py`) || !tree.exists(infraPath) || tree.exists(launcherPath) && tree.read(launcherPath, 'utf-8') !== launcher || terraform && !tree.exists(TERRAFORM_RUNTIME)) {
73
+ report();
74
+ continue;
75
+ }
76
+ const oldEntry = terraform ? hcl(terraformInput('main.py')) : cdkInput("['opentelemetry-instrument', 'main.py']");
77
+ const newEntry = terraform ? hcl(terraformInput(PYTHON_AGENT_CORE_LAUNCHER)) : cdkInput("['agentcore_launcher.py']");
78
+ const alreadyMigrated = await matchGritQL(tree, infraPath, newEntry);
79
+ if (!alreadyMigrated && !await matchGritQL(tree, infraPath, oldEntry) || terraform && !coreMigrated) {
80
+ report();
81
+ continue;
82
+ }
83
+ if (!tree.exists(launcherPath)) tree.write(launcherPath, launcher);
84
+ if (commands.length === 5) {
85
+ commands.push(copyLauncher);
86
+ changed = true;
87
+ }
88
+ if (!alreadyMigrated) {
89
+ await applyGritQL(tree, infraPath, terraform ? hcl('`module "agent_core_runtime" { $body }` where { $body <: contains `code_runtime = $runtime`, $runtime <: r".*PYTHON_.*", $body <: contains bubble `code_entry_point = "main.py"` => `code_entry_point = "agentcore_launcher.py"` }') : "`AgentRuntimeArtifact.fromCodeAsset({ $props })` where { $props <: contains `runtime: AgentCoreRuntime.$runtime`, $runtime <: r\"PYTHON_.*\", $props <: contains bubble `entrypoint: ['opentelemetry-instrument', 'main.py']` => `entrypoint: ['agentcore_launcher.py']` }");
90
+ }
91
+ }
92
+ if (changed) updateProjectConfiguration(tree, project.name, project);
93
+ }
94
+ await formatFilesInSubtree(tree);
95
+ return {
96
+ nextSteps
97
+ };
98
+ }
99
+
100
+ //# sourceMappingURL=migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/py-agentcore-launcher/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { basename } from 'node:path';\nimport {\n getProjects,\n joinPathFragments,\n type MigrationReturnObject,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { PY_AGENT_GENERATOR_INFO } from '../../../py/agent/generator.js';\nimport { PY_MCP_SERVER_GENERATOR_INFO } from '../../../py/mcp-server/generator.js';\nimport { applyGritQL, matchGritQL } from '../../../utils/ast.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\nimport { kebabCase } from '../../../utils/names.js';\nimport type { ComponentMetadata } from '../../../utils/nx.js';\n\nconst TERRAFORM_RUNTIME =\n 'packages/common/terraform/src/core/agent-core-code/runtime.tf';\nconst PYTHON_AGENT_CORE_LAUNCHER = 'agentcore_launcher.py';\nconst launcher = `\\\nimport sys\nfrom pathlib import Path\n\nfrom opentelemetry.instrumentation.auto_instrumentation import run\n\nif __name__ == \"__main__\":\n sys.argv = [\n \"opentelemetry-instrument\",\n sys.executable,\n str(Path(__file__).with_name(\"main.py\")),\n *sys.argv[1:],\n ]\n run()\n`;\nconst terraformEntry =\n 'entry_point = var.code_entry_point == \"agentcore_launcher.py\" ? [var.code_entry_point] : [\"opentelemetry-instrument\", var.code_entry_point]';\nconst oldTerraformEntry =\n 'entry_point = [\"opentelemetry-instrument\", var.code_entry_point]';\nconst hcl = (pattern: string) => `language hcl\\n${pattern}`;\nconst terraformInput = (entryPoint: string) =>\n `\\`module \"agent_core_runtime\" { $body }\\` where { $body <: contains \\`code_runtime = $runtime\\`, $runtime <: r\".*PYTHON_.*\", $body <: contains \\`code_entry_point = \"${entryPoint}\"\\` }`;\nconst cdkInput = (entryPoint: string) =>\n `\\`AgentRuntimeArtifact.fromCodeAsset({ $props })\\` where { $props <: contains \\`runtime: AgentCoreRuntime.$runtime\\`, $runtime <: r\"PYTHON_.*\", $props <: contains \\`entrypoint: ${entryPoint}\\` }`;\n\n/** Add the interpreter-safe launcher without changing the user's main.py or application. */\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n if (\n tree.exists(TERRAFORM_RUNTIME) &&\n (await matchGritQL(\n tree,\n TERRAFORM_RUNTIME,\n hcl(`\\`${oldTerraformEntry}\\``),\n ))\n ) {\n await applyGritQL(\n tree,\n TERRAFORM_RUNTIME,\n hcl(`\\`${oldTerraformEntry}\\` => \\`${terraformEntry}\\``),\n );\n }\n const coreMigrated =\n tree.exists(TERRAFORM_RUNTIME) &&\n (await matchGritQL(tree, TERRAFORM_RUNTIME, hcl(`\\`${terraformEntry}\\``)));\n for (const project of getProjects(tree).values()) {\n const components: ComponentMetadata[] = project.metadata?.components ?? [];\n let changed = false;\n for (const component of components) {\n const agent = component.generator === PY_AGENT_GENERATOR_INFO.id;\n if (\n (!agent && component.generator !== PY_MCP_SERVER_GENERATOR_INFO.id) ||\n component.infra !== 'agentcore'\n ) {\n continue;\n }\n const terraform = component.iac === 'terraform';\n const targetName = `${component.name}-package`;\n const target = project.targets?.[targetName];\n const name = kebabCase(component.rc ?? '');\n const packageDir = joinPathFragments(\n project.root,\n 'package',\n basename(component.path ?? ''),\n );\n const outputDir = joinPathFragments(\n 'dist',\n project.root,\n 'package',\n name,\n );\n const launcherPath = joinPathFragments(\n packageDir,\n PYTHON_AGENT_CORE_LAUNCHER,\n );\n const copyLauncher = `shx cp ${launcherPath} ${outputDir}/${PYTHON_AGENT_CORE_LAUNCHER}`;\n const commands = target?.options?.commands;\n const expectedCommands = [\n `shx rm -rf ${outputDir}`,\n `shx mkdir -p ${outputDir}`,\n `shx cp -R dist/${project.root}/bundle-arm/. ${outputDir}`,\n `shx cp -R ${project.sourceRoot}/. ${outputDir}/${basename(project.sourceRoot ?? '')}`,\n `shx cp ${packageDir}/main.py ${outputDir}/main.py`,\n ];\n const category = agent ? 'agents' : 'mcp-servers';\n const infraPath = terraform\n ? `packages/common/terraform/src/app/${category}/${name}/${name}.tf`\n : `packages/common/constructs/src/app/${category}/${name}/${name}.ts`;\n const report = () =>\n nextSteps.push(\n `${project.name}/${component.name}: review customized packaging or ${infraPath}; add ${PYTHON_AGENT_CORE_LAUNCHER} calling OpenTelemetry run() with sys.executable and main.py, copy it to the package root, and select it as this Python runtime's code entrypoint.`,\n );\n if (\n !component.path ||\n !component.rc ||\n !['cdk', 'terraform'].includes(component.iac) ||\n target?.executor !== 'nx:run-commands' ||\n target.options?.parallel !== false ||\n !Array.isArray(commands) ||\n ![5, 6].includes(commands.length) ||\n expectedCommands.some(\n (command, index) => commands[index] !== command,\n ) ||\n (commands.length === 6 && commands[5] !== copyLauncher) ||\n !tree.exists(`${packageDir}/main.py`) ||\n !tree.exists(infraPath) ||\n (tree.exists(launcherPath) &&\n tree.read(launcherPath, 'utf-8') !== launcher) ||\n (terraform && !tree.exists(TERRAFORM_RUNTIME))\n ) {\n report();\n continue;\n }\n const oldEntry = terraform\n ? hcl(terraformInput('main.py'))\n : cdkInput(\"['opentelemetry-instrument', 'main.py']\");\n const newEntry = terraform\n ? hcl(terraformInput(PYTHON_AGENT_CORE_LAUNCHER))\n : cdkInput(\"['agentcore_launcher.py']\");\n const alreadyMigrated = await matchGritQL(tree, infraPath, newEntry);\n if (\n (!alreadyMigrated && !(await matchGritQL(tree, infraPath, oldEntry))) ||\n (terraform && !coreMigrated)\n ) {\n report();\n continue;\n }\n if (!tree.exists(launcherPath)) tree.write(launcherPath, launcher);\n if (commands.length === 5) {\n commands.push(copyLauncher);\n changed = true;\n }\n if (!alreadyMigrated) {\n await applyGritQL(\n tree,\n infraPath,\n terraform\n ? hcl(\n '`module \"agent_core_runtime\" { $body }` where { $body <: contains `code_runtime = $runtime`, $runtime <: r\".*PYTHON_.*\", $body <: contains bubble `code_entry_point = \"main.py\"` => `code_entry_point = \"agentcore_launcher.py\"` }',\n )\n : \"`AgentRuntimeArtifact.fromCodeAsset({ $props })` where { $props <: contains `runtime: AgentCoreRuntime.$runtime`, $runtime <: r\\\"PYTHON_.*\\\", $props <: contains bubble `entrypoint: ['opentelemetry-instrument', 'main.py']` => `entrypoint: ['agentcore_launcher.py']` }\",\n );\n }\n }\n if (changed) updateProjectConfiguration(tree, project.name, project);\n }\n await formatFilesInSubtree(tree);\n return { nextSteps };\n}\n"],"names":["basename","getProjects","joinPathFragments","updateProjectConfiguration","PY_AGENT_GENERATOR_INFO","PY_MCP_SERVER_GENERATOR_INFO","applyGritQL","matchGritQL","formatFilesInSubtree","kebabCase","TERRAFORM_RUNTIME","PYTHON_AGENT_CORE_LAUNCHER","launcher","terraformEntry","oldTerraformEntry","hcl","pattern","terraformInput","entryPoint","cdkInput","migration","tree","nextSteps","exists","coreMigrated","project","values","components","metadata","changed","component","agent","generator","id","infra","terraform","iac","targetName","name","target","targets","rc","packageDir","root","path","outputDir","launcherPath","copyLauncher","commands","options","expectedCommands","sourceRoot","category","infraPath","report","push","includes","executor","parallel","Array","isArray","length","some","command","index","read","oldEntry","newEntry","alreadyMigrated","write"],"mappings":"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"}
@@ -8,7 +8,7 @@ import { addPyDependencies, addTsDependencies } from "../../utils/add-dependenci
8
8
  import { addAgentChatScripts } from "../../utils/agent-chat/agent-chat.js";
9
9
  import { AGENT_CONNECTION_PY_DEPENDENCIES, addPythonFrameworkBase, ensureLangchainS3CheckpointSaver, ensurePythonAgentConnectionProject, getPythonAgentConnectionModuleName, getPythonAgentConnectionProject } from "../../utils/agent-connection/agent-connection.js";
10
10
  import { addAgentInfra } from "../../utils/agent-core-constructs/agent-core-constructs.js";
11
- import { addPythonCodePackageTarget, agentCorePythonRuntime, isAgentCoreHosted, isContainerHosted } from "../../utils/agent-core-packaging.js";
11
+ import { addPythonCodePackageTarget, agentCorePythonRuntime, isAgentCoreHosted, isContainerHosted, PYTHON_AGENT_CORE_LAUNCHER } from "../../utils/agent-core-packaging.js";
12
12
  import { addPythonBundleTarget } from "../../utils/bundle/bundle.js";
13
13
  import { resolveContainers } from "../../utils/containers.js";
14
14
  import { declareDependencies, ownedElsewhere } from "../../utils/declared-dependencies.js";
@@ -372,7 +372,7 @@ export const pyAgentGenerator = async (tree, options)=>{
372
372
  type: 'code',
373
373
  outputDir: packageOutputDir,
374
374
  runtime: agentCorePythonRuntime(),
375
- entryPoint: 'main.py'
375
+ entryPoint: PYTHON_AGENT_CORE_LAUNCHER
376
376
  };
377
377
  }
378
378
  // Add shared constructs
@@ -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 type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { ensureLicenseExceptions } from '../../license/config.js';\nimport { AG_UI_LANGGRAPH_EXCEPTIONS } from '../../license/known-exceptions.js';\nimport {\n addPyDependencies,\n addTsDependencies,\n} from '../../utils/add-dependencies.js';\nimport { addAgentChatScripts } from '../../utils/agent-chat/agent-chat.js';\nimport {\n AGENT_CONNECTION_PY_DEPENDENCIES,\n addPythonFrameworkBase,\n ensureLangchainS3CheckpointSaver,\n ensurePythonAgentConnectionProject,\n getPythonAgentConnectionModuleName,\n getPythonAgentConnectionProject,\n} from '../../utils/agent-connection/agent-connection.js';\nimport {\n type AgentCoreArtifact,\n addAgentInfra,\n} from '../../utils/agent-core-constructs/agent-core-constructs.js';\nimport {\n addPythonCodePackageTarget,\n agentCorePythonRuntime,\n isAgentCoreHosted,\n isContainerHosted,\n} from '../../utils/agent-core-packaging.js';\nimport { addPythonBundleTarget } from '../../utils/bundle/bundle.js';\nimport { resolveContainers } from '../../utils/containers.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../utils/declared-dependencies.js';\nimport {\n addDockerScanTarget,\n DOCKER_DEPENDENCIES,\n IMAGE_BUILD_CACHE,\n} from '../../utils/docker.js';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { FS_DEPENDENCIES, FsCommands } from '../../utils/fs.js';\nimport { updateGitIgnore } from '../../utils/git.js';\nimport { resolveIac } from '../../utils/iac.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { kebabCase, toClassName, toSnakeCase } from '../../utils/names.js';\nimport { getNpmScope } from '../../utils/npm-scope.js';\nimport {\n addArtifactDependencyToTargets,\n addComponentDevTarget,\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n getGeneratorInfo,\n type NxGeneratorInfo,\n normalizeTargetKeyOrder,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx.js';\nimport { sortObjectKeys } from '../../utils/object.js';\nimport { openApiCodegenTarget } from '../../utils/open-api-codegen-target.js';\nimport {\n getRelativePathToRootByDirectory,\n toProjectRelativePath,\n} from '../../utils/paths.js';\nimport { assignPort } from '../../utils/port.js';\nimport { addWorkspaceDependencyToPyProject } from '../../utils/py.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../../utils/shared-constructs.js';\nimport type { IacMetadata } from '../../utils/shared-constructs-constants.js';\nimport { BASE_IMAGES } from '../../utils/versions.js';\nimport type {\n AgentProtocol,\n PyAgentFramework,\n PyAgentGeneratorSchema,\n PyAgentInfra,\n PyAgentSession,\n} from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface PyAgentMetadata extends IacMetadata {\n readonly port: number;\n readonly rc: string;\n readonly auth: string;\n readonly protocol: AgentProtocol;\n /**\n * The mcp / gateway connection generators dispatch on this field to pick the\n * Strands vs LangChain Layer-2 client + agent.py transform.\n */\n readonly framework: PyAgentFramework;\n readonly session: PyAgentSession;\n /**\n * How this component is packaged and hosted, so a consumer can tell a\n * code-packaged runtime from a container-packaged one without re-deriving it.\n */\n readonly infra: PyAgentInfra;\n}\n\n/** Whether the chat CLI signs its requests, which only IAM auth needs. */\nconst isIam = (m: PyAgentMetadata) => m.auth === 'iam';\n\n// Each entry names the framework and protocol branch it belongs to, so the same\n// declaration drives both adding and the version sync.\nexport const DEPENDENCIES = declareDependencies<PyAgentMetadata>()({\n ts: [\n // The chat CLI, which runs standalone via tsx for every protocol and\n // resolves the deployed agent from AppConfig. `agent-chat-cli` transitively\n // bundles the protocol clients (@a2a-js/sdk, @ag-ui/client).\n { name: 'agent-chat-cli', dev: true, root: true },\n { name: 'tsx', dev: true, root: true },\n { name: '@types/node', dev: true, root: true },\n { name: '@aws-lambda-powertools/parameters', dev: true, root: true },\n { name: '@aws-sdk/client-appconfigdata', dev: true, root: true },\n { name: 'aws4fetch', when: isIam, dev: true, root: true },\n {\n name: '@aws-sdk/credential-providers',\n when: isIam,\n dev: true,\n root: true,\n },\n {\n name: '@a2a-js/sdk',\n when: (m) => m.protocol === 'a2a',\n dev: true,\n root: true,\n },\n // Added by the helpers that own the projects they belong to.\n ...ownedElsewhere(FS_DEPENDENCIES),\n ...ownedElsewhere(DOCKER_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n py: [\n { name: 'aws-lambda-powertools' },\n { name: 'aws-opentelemetry-distro' },\n { name: 'bedrock-agentcore' },\n { name: 'boto3' },\n { name: 'fastapi' },\n { name: 'mcp' },\n // langchain pulls no Strands dependencies — the langchain model binding\n // plus the per-protocol server adapter: ag-ui-langgraph for AG-UI, a2a-sdk\n // for A2A, nothing extra for HTTP (FastAPI is added for every agent).\n { name: 'langchain', when: (m) => m.framework === 'langchain' },\n { name: 'langchain-aws', when: (m) => m.framework === 'langchain' },\n { name: 'langgraph', when: (m) => m.framework === 'langchain' },\n // Local dev uses a SQLite-backed checkpointer for convenience (parity\n // with the strands framework's local FileSessionManager).\n {\n name: 'langgraph-checkpoint-sqlite',\n when: (m) => m.framework === 'langchain',\n },\n // AsyncSqliteSaver's driver, required alongside langgraph-checkpoint-sqlite.\n { name: 'aiosqlite', when: (m) => m.framework === 'langchain' },\n // Provides DynamoDBSaver (with S3 offloading for large checkpoints).\n {\n name: 'langgraph-checkpoint-aws',\n when: (m) => m.framework === 'langchain' && m.session === 'dynamodb-s3',\n },\n {\n name: 'ag-ui-protocol',\n when: (m) => m.framework === 'langchain' && m.protocol === 'ag-ui',\n },\n {\n name: 'ag-ui-langgraph',\n when: (m) => m.framework === 'langchain' && m.protocol === 'ag-ui',\n },\n {\n name: 'a2a-sdk',\n when: (m) => m.framework === 'langchain' && m.protocol === 'a2a',\n },\n {\n name: 'strands-agents[a2a]',\n when: (m) => m.framework === 'strands' && m.protocol === 'a2a',\n },\n {\n name: 'strands-agents',\n when: (m) => m.framework === 'strands' && m.protocol !== 'a2a',\n },\n {\n name: 'strands-agents-tools',\n when: (m) => m.framework === 'strands',\n },\n // Declared again here so a Strands AG-UI agent lists it in the same order\n // the generated pyproject.toml had before.\n {\n name: 'ag-ui-protocol',\n when: (m) => m.framework === 'strands' && m.protocol === 'ag-ui',\n },\n {\n name: 'ag-ui-strands',\n when: (m) => m.framework === 'strands' && m.protocol === 'ag-ui',\n },\n { name: 'uvicorn' },\n // `fastapi dev` runs the local server for every protocol.\n { name: 'fastapi[standard]', group: 'dev' },\n // The agent-connection helper adds these to its own project.\n ...ownedElsewhere(AGENT_CONNECTION_PY_DEPENDENCIES),\n ],\n});\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 // 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 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 // Session backends are framework-specific: Strands' SessionManager only has\n // an S3-backed implementation here (via strands.session.S3SessionManager),\n // while LangChain uses dedicated S3 and DynamoDB checkpointer libraries.\n // 'in-memory' is valid for both.\n const SESSIONS_BY_FRAMEWORK: Record<\n PyAgentFramework,\n readonly PyAgentSession[]\n > = {\n strands: ['s3', 'in-memory'],\n langchain: ['s3', 'dynamodb-s3', 'in-memory'],\n };\n if (\n options.session &&\n !SESSIONS_BY_FRAMEWORK[framework].includes(options.session)\n ) {\n throw new Error(\n `Unsupported combination: session '${options.session}' is not implemented for the ${framework} framework (supported: ${SESSIONS_BY_FRAMEWORK[framework].join(', ')}).`,\n );\n }\n const session = options.session ?? 's3';\n\n // With infra=none there's no CDK/Terraform construct to provision a bucket\n // or table or set RUNTIME_CONFIG_APP_ID, so session.py's non-local-dev\n // branch has nothing to read from AppConfig at runtime — the generated code\n // still honors `session`, but only works outside local dev if the caller\n // wires up matching infra/runtime config themselves.\n if (infra === 'none' && session !== 'in-memory') {\n console.warn(\n `Warning: session '${session}' requires infrastructure to configure it automatically (no infrastructure is generated for infra=none) — outside local dev this will fail unless you configure matching runtime config yourself`,\n );\n }\n\n // Local-dev session storage lives at the workspace root\n // (`tmp/agents/<framework>/<agent-name>`), not inside the project, so each\n // agent gets its own storage directory — shared by both frameworks\n // (Strands' FileSessionManager, LangChain's SqliteSaver). The\n // `-dev`/`-serve` targets run with cwd={projectRoot}, so compute that\n // directory relative to the project root here rather than resolving it at\n // runtime.\n const localSessionsDir = joinPathFragments(\n getRelativePathToRootByDirectory(project.root),\n `tmp/agents/${framework}/${name}`,\n );\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, DEPENDENCIES);\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, DEPENDENCIES, 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 protocol,\n session,\n localSessionsDir,\n };\n\n // Files live under a per-framework dir (files/strands, files/langchain),\n // mirrored one-for-one — including files that don't vary by framework\n // (e.g. the empty package __init__.py) — so there's a single, uniform\n // <framework>/<protocol> layout with no cross-framework fallbacks.\n // `framework` is itself the directory name.\n\n // Common files shared by both protocols: the agent module (Strands yields a\n // contextmanaged Agent with a session.py sibling; LangChain returns a\n // compiled create_agent graph) and the package __init__.py.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', framework, 'common'),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n if (framework === 'langchain' && session === 's3') {\n ensureLangchainS3CheckpointSaver(tree);\n }\n\n // Protocol-specific files. Each protocol's server entry point is\n // framework-specific (Strands yields a contextmanaged Agent; LangChain\n // drives a compiled create_agent graph).\n const protocolLower = protocol.toLowerCase();\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', framework, protocolLower),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n if (isAgentCoreHosted(infra)) {\n const container = isContainerHosted(infra);\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 let artifact: AgentCoreArtifact;\n\n if (container) {\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, DEPENDENCIES);\n project.targets[dockerTargetName] = {\n cache: IMAGE_BUILD_CACHE,\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(dockerOutputDir),\n fs.mkdir(dockerOutputDir),\n fs.cpDir(bundleOutputDir, dockerOutputDir),\n fs.cpFile(\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 addArtifactDependencyToTargets(project, 'docker');\n\n addDockerScanTarget(\n tree,\n {\n project,\n containerEngine: containers,\n trivyTargetName: `${agentTargetPrefix}-trivy`,\n dockerTargetName,\n imageTags: [dockerImageTag],\n },\n DEPENDENCIES,\n );\n\n artifact = {\n type: 'container',\n dockerImageTag,\n outputDir: dockerOutputDir,\n };\n } else {\n // The entry point the managed runtime runs, at the package root.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'package'),\n joinPathFragments(project.root, 'package', agentNameSnakeCase),\n {\n agentNameSnakeCase,\n moduleName,\n port: protocol === 'a2a' ? 9000 : 8080,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n const packageOutputDir = joinPathFragments(\n 'dist',\n project.root,\n 'package',\n name,\n );\n addPythonCodePackageTarget(\n tree,\n {\n project,\n targetName: `${agentTargetPrefix}-package`,\n bundleTargetName,\n bundleOutputDir,\n packageOutputDir,\n sourceRoot: project.sourceRoot,\n moduleName,\n entryPointPath: joinPathFragments(\n project.root,\n 'package',\n agentNameSnakeCase,\n 'main.py',\n ),\n entryPointFileName: 'main.py',\n },\n DEPENDENCIES,\n );\n\n artifact = {\n type: 'code',\n outputDir: packageOutputDir,\n runtime: agentCorePythonRuntime(),\n entryPoint: 'main.py',\n };\n }\n\n // Add shared constructs\n await sharedConstructsGenerator(tree, { iac }, DEPENDENCIES);\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 artifact,\n iac,\n projectName: project.name,\n auth,\n session,\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 // 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: PyAgentMetadata = {\n infra,\n port: localDevPort,\n rc: agentNameClassName,\n auth,\n protocol,\n framework,\n session,\n ...(iac ? { iac } : {}),\n };\n\n addPyDependencies(tree, DEPENDENCIES, {\n metadata,\n projectRoot: project.root,\n });\n addTsDependencies(tree, DEPENDENCIES, { metadata });\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 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 // The spec serialises models a dependency may own, and this target\n // has no `dependsOn` for `default`'s transitive\n // `dependentTasksOutputFiles` to resolve against — so `^production`\n // is the only edge to the dependency, and without it a model change\n // there serves a stale spec.\n inputs: ['production', '^production'],\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]: openApiCodegenTarget({\n generator: 'ts-client',\n openApiSpecPath: `dist/${project.root}/openapi/${agentNameSnakeCase}/openapi.json`,\n outputPath: `${project.root}/scripts/${agentTargetPrefix}/generated`,\n specBuildTargetName: openApiTargetName,\n outputs: [`{projectRoot}/scripts/${agentTargetPrefix}/generated`],\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 metadata,\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":["generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","ensureLicenseExceptions","AG_UI_LANGGRAPH_EXCEPTIONS","addPyDependencies","addTsDependencies","addAgentChatScripts","AGENT_CONNECTION_PY_DEPENDENCIES","addPythonFrameworkBase","ensureLangchainS3CheckpointSaver","ensurePythonAgentConnectionProject","getPythonAgentConnectionModuleName","getPythonAgentConnectionProject","addAgentInfra","addPythonCodePackageTarget","agentCorePythonRuntime","isAgentCoreHosted","isContainerHosted","addPythonBundleTarget","resolveContainers","declareDependencies","ownedElsewhere","addDockerScanTarget","DOCKER_DEPENDENCIES","IMAGE_BUILD_CACHE","formatFilesInSubtree","FS_DEPENDENCIES","FsCommands","updateGitIgnore","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toSnakeCase","getNpmScope","addArtifactDependencyToTargets","addComponentDevTarget","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","normalizeTargetKeyOrder","readProjectConfigurationUnqualified","sortObjectKeys","openApiCodegenTarget","getRelativePathToRootByDirectory","toProjectRelativePath","assignPort","addWorkspaceDependencyToPyProject","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","BASE_IMAGES","isIam","m","auth","DEPENDENCIES","ts","name","dev","root","when","protocol","py","framework","session","group","PY_AGENT_GENERATOR_INFO","filename","pyAgentGenerator","tree","options","project","pyProjectPath","Error","sourceRoot","sourceParts","split","moduleName","length","pop","agentTargetPrefix","agentNameSnakeCase","agentNameClassName","targetSourceDir","infra","iac","undefined","console","warn","SESSIONS_BY_FRAMEWORK","strands","langchain","includes","join","localSessionsDir","agentConnectionModuleName","templateContext","dirname","overwriteStrategy","KeepExisting","protocolLower","toLowerCase","container","containers","dockerImageTag","bundleTargetName","bundleOutputDir","pythonPlatform","artifact","pythonBaseImage","python","dockerOutputDir","dockerTargetName","fs","targets","cache","executor","commands","rm","mkdir","cpDir","cpFile","parallel","dependsOn","containerEngine","trivyTargetName","imageTags","type","outputDir","port","packageOutputDir","targetName","entryPointPath","entryPointFileName","runtime","entryPoint","infraProtocol","agentNameKebabCase","projectName","serverProtocol","localDevPortStart","localDevPort","component","info","metadata","rc","projectRoot","serveCommand","openApiTargetName","clientGenTargetName","scriptsDir","patterns","language","chatUrl","chatCommand","httpOnlyTargets","inputs","outputs","generator","openApiSpecPath","outputPath","specBuildTargetName","agentTargets","continuous","cwd","env","PORT","LOCAL_DEV","URL","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 type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { ensureLicenseExceptions } from '../../license/config.js';\nimport { AG_UI_LANGGRAPH_EXCEPTIONS } from '../../license/known-exceptions.js';\nimport {\n addPyDependencies,\n addTsDependencies,\n} from '../../utils/add-dependencies.js';\nimport { addAgentChatScripts } from '../../utils/agent-chat/agent-chat.js';\nimport {\n AGENT_CONNECTION_PY_DEPENDENCIES,\n addPythonFrameworkBase,\n ensureLangchainS3CheckpointSaver,\n ensurePythonAgentConnectionProject,\n getPythonAgentConnectionModuleName,\n getPythonAgentConnectionProject,\n} from '../../utils/agent-connection/agent-connection.js';\nimport {\n type AgentCoreArtifact,\n addAgentInfra,\n} from '../../utils/agent-core-constructs/agent-core-constructs.js';\nimport {\n addPythonCodePackageTarget,\n agentCorePythonRuntime,\n isAgentCoreHosted,\n isContainerHosted,\n PYTHON_AGENT_CORE_LAUNCHER,\n} from '../../utils/agent-core-packaging.js';\nimport { addPythonBundleTarget } from '../../utils/bundle/bundle.js';\nimport { resolveContainers } from '../../utils/containers.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../utils/declared-dependencies.js';\nimport {\n addDockerScanTarget,\n DOCKER_DEPENDENCIES,\n IMAGE_BUILD_CACHE,\n} from '../../utils/docker.js';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { FS_DEPENDENCIES, FsCommands } from '../../utils/fs.js';\nimport { updateGitIgnore } from '../../utils/git.js';\nimport { resolveIac } from '../../utils/iac.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { kebabCase, toClassName, toSnakeCase } from '../../utils/names.js';\nimport { getNpmScope } from '../../utils/npm-scope.js';\nimport {\n addArtifactDependencyToTargets,\n addComponentDevTarget,\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n getGeneratorInfo,\n type NxGeneratorInfo,\n normalizeTargetKeyOrder,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx.js';\nimport { sortObjectKeys } from '../../utils/object.js';\nimport { openApiCodegenTarget } from '../../utils/open-api-codegen-target.js';\nimport {\n getRelativePathToRootByDirectory,\n toProjectRelativePath,\n} from '../../utils/paths.js';\nimport { assignPort } from '../../utils/port.js';\nimport { addWorkspaceDependencyToPyProject } from '../../utils/py.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../../utils/shared-constructs.js';\nimport type { IacMetadata } from '../../utils/shared-constructs-constants.js';\nimport { BASE_IMAGES } from '../../utils/versions.js';\nimport type {\n AgentProtocol,\n PyAgentFramework,\n PyAgentGeneratorSchema,\n PyAgentInfra,\n PyAgentSession,\n} from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface PyAgentMetadata extends IacMetadata {\n readonly port: number;\n readonly rc: string;\n readonly auth: string;\n readonly protocol: AgentProtocol;\n /**\n * The mcp / gateway connection generators dispatch on this field to pick the\n * Strands vs LangChain Layer-2 client + agent.py transform.\n */\n readonly framework: PyAgentFramework;\n readonly session: PyAgentSession;\n /**\n * How this component is packaged and hosted, so a consumer can tell a\n * code-packaged runtime from a container-packaged one without re-deriving it.\n */\n readonly infra: PyAgentInfra;\n}\n\n/** Whether the chat CLI signs its requests, which only IAM auth needs. */\nconst isIam = (m: PyAgentMetadata) => m.auth === 'iam';\n\n// Each entry names the framework and protocol branch it belongs to, so the same\n// declaration drives both adding and the version sync.\nexport const DEPENDENCIES = declareDependencies<PyAgentMetadata>()({\n ts: [\n // The chat CLI, which runs standalone via tsx for every protocol and\n // resolves the deployed agent from AppConfig. `agent-chat-cli` transitively\n // bundles the protocol clients (@a2a-js/sdk, @ag-ui/client).\n { name: 'agent-chat-cli', dev: true, root: true },\n { name: 'tsx', dev: true, root: true },\n { name: '@types/node', dev: true, root: true },\n { name: '@aws-lambda-powertools/parameters', dev: true, root: true },\n { name: '@aws-sdk/client-appconfigdata', dev: true, root: true },\n { name: 'aws4fetch', when: isIam, dev: true, root: true },\n {\n name: '@aws-sdk/credential-providers',\n when: isIam,\n dev: true,\n root: true,\n },\n {\n name: '@a2a-js/sdk',\n when: (m) => m.protocol === 'a2a',\n dev: true,\n root: true,\n },\n // Added by the helpers that own the projects they belong to.\n ...ownedElsewhere(FS_DEPENDENCIES),\n ...ownedElsewhere(DOCKER_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n py: [\n { name: 'aws-lambda-powertools' },\n { name: 'aws-opentelemetry-distro' },\n { name: 'bedrock-agentcore' },\n { name: 'boto3' },\n { name: 'fastapi' },\n { name: 'mcp' },\n // langchain pulls no Strands dependencies — the langchain model binding\n // plus the per-protocol server adapter: ag-ui-langgraph for AG-UI, a2a-sdk\n // for A2A, nothing extra for HTTP (FastAPI is added for every agent).\n { name: 'langchain', when: (m) => m.framework === 'langchain' },\n { name: 'langchain-aws', when: (m) => m.framework === 'langchain' },\n { name: 'langgraph', when: (m) => m.framework === 'langchain' },\n // Local dev uses a SQLite-backed checkpointer for convenience (parity\n // with the strands framework's local FileSessionManager).\n {\n name: 'langgraph-checkpoint-sqlite',\n when: (m) => m.framework === 'langchain',\n },\n // AsyncSqliteSaver's driver, required alongside langgraph-checkpoint-sqlite.\n { name: 'aiosqlite', when: (m) => m.framework === 'langchain' },\n // Provides DynamoDBSaver (with S3 offloading for large checkpoints).\n {\n name: 'langgraph-checkpoint-aws',\n when: (m) => m.framework === 'langchain' && m.session === 'dynamodb-s3',\n },\n {\n name: 'ag-ui-protocol',\n when: (m) => m.framework === 'langchain' && m.protocol === 'ag-ui',\n },\n {\n name: 'ag-ui-langgraph',\n when: (m) => m.framework === 'langchain' && m.protocol === 'ag-ui',\n },\n {\n name: 'a2a-sdk',\n when: (m) => m.framework === 'langchain' && m.protocol === 'a2a',\n },\n {\n name: 'strands-agents[a2a]',\n when: (m) => m.framework === 'strands' && m.protocol === 'a2a',\n },\n {\n name: 'strands-agents',\n when: (m) => m.framework === 'strands' && m.protocol !== 'a2a',\n },\n {\n name: 'strands-agents-tools',\n when: (m) => m.framework === 'strands',\n },\n // Declared again here so a Strands AG-UI agent lists it in the same order\n // the generated pyproject.toml had before.\n {\n name: 'ag-ui-protocol',\n when: (m) => m.framework === 'strands' && m.protocol === 'ag-ui',\n },\n {\n name: 'ag-ui-strands',\n when: (m) => m.framework === 'strands' && m.protocol === 'ag-ui',\n },\n { name: 'uvicorn' },\n // `fastapi dev` runs the local server for every protocol.\n { name: 'fastapi[standard]', group: 'dev' },\n // The agent-connection helper adds these to its own project.\n ...ownedElsewhere(AGENT_CONNECTION_PY_DEPENDENCIES),\n ],\n});\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 // 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 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 // Session backends are framework-specific: Strands' SessionManager only has\n // an S3-backed implementation here (via strands.session.S3SessionManager),\n // while LangChain uses dedicated S3 and DynamoDB checkpointer libraries.\n // 'in-memory' is valid for both.\n const SESSIONS_BY_FRAMEWORK: Record<\n PyAgentFramework,\n readonly PyAgentSession[]\n > = {\n strands: ['s3', 'in-memory'],\n langchain: ['s3', 'dynamodb-s3', 'in-memory'],\n };\n if (\n options.session &&\n !SESSIONS_BY_FRAMEWORK[framework].includes(options.session)\n ) {\n throw new Error(\n `Unsupported combination: session '${options.session}' is not implemented for the ${framework} framework (supported: ${SESSIONS_BY_FRAMEWORK[framework].join(', ')}).`,\n );\n }\n const session = options.session ?? 's3';\n\n // With infra=none there's no CDK/Terraform construct to provision a bucket\n // or table or set RUNTIME_CONFIG_APP_ID, so session.py's non-local-dev\n // branch has nothing to read from AppConfig at runtime — the generated code\n // still honors `session`, but only works outside local dev if the caller\n // wires up matching infra/runtime config themselves.\n if (infra === 'none' && session !== 'in-memory') {\n console.warn(\n `Warning: session '${session}' requires infrastructure to configure it automatically (no infrastructure is generated for infra=none) — outside local dev this will fail unless you configure matching runtime config yourself`,\n );\n }\n\n // Local-dev session storage lives at the workspace root\n // (`tmp/agents/<framework>/<agent-name>`), not inside the project, so each\n // agent gets its own storage directory — shared by both frameworks\n // (Strands' FileSessionManager, LangChain's SqliteSaver). The\n // `-dev`/`-serve` targets run with cwd={projectRoot}, so compute that\n // directory relative to the project root here rather than resolving it at\n // runtime.\n const localSessionsDir = joinPathFragments(\n getRelativePathToRootByDirectory(project.root),\n `tmp/agents/${framework}/${name}`,\n );\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, DEPENDENCIES);\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, DEPENDENCIES, 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 protocol,\n session,\n localSessionsDir,\n };\n\n // Files live under a per-framework dir (files/strands, files/langchain),\n // mirrored one-for-one — including files that don't vary by framework\n // (e.g. the empty package __init__.py) — so there's a single, uniform\n // <framework>/<protocol> layout with no cross-framework fallbacks.\n // `framework` is itself the directory name.\n\n // Common files shared by both protocols: the agent module (Strands yields a\n // contextmanaged Agent with a session.py sibling; LangChain returns a\n // compiled create_agent graph) and the package __init__.py.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', framework, 'common'),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n if (framework === 'langchain' && session === 's3') {\n ensureLangchainS3CheckpointSaver(tree);\n }\n\n // Protocol-specific files. Each protocol's server entry point is\n // framework-specific (Strands yields a contextmanaged Agent; LangChain\n // drives a compiled create_agent graph).\n const protocolLower = protocol.toLowerCase();\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', framework, protocolLower),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n if (isAgentCoreHosted(infra)) {\n const container = isContainerHosted(infra);\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 let artifact: AgentCoreArtifact;\n\n if (container) {\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, DEPENDENCIES);\n project.targets[dockerTargetName] = {\n cache: IMAGE_BUILD_CACHE,\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(dockerOutputDir),\n fs.mkdir(dockerOutputDir),\n fs.cpDir(bundleOutputDir, dockerOutputDir),\n fs.cpFile(\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 addArtifactDependencyToTargets(project, 'docker');\n\n addDockerScanTarget(\n tree,\n {\n project,\n containerEngine: containers,\n trivyTargetName: `${agentTargetPrefix}-trivy`,\n dockerTargetName,\n imageTags: [dockerImageTag],\n },\n DEPENDENCIES,\n );\n\n artifact = {\n type: 'container',\n dockerImageTag,\n outputDir: dockerOutputDir,\n };\n } else {\n // The entry point the managed runtime runs, at the package root.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'package'),\n joinPathFragments(project.root, 'package', agentNameSnakeCase),\n {\n agentNameSnakeCase,\n moduleName,\n port: protocol === 'a2a' ? 9000 : 8080,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n const packageOutputDir = joinPathFragments(\n 'dist',\n project.root,\n 'package',\n name,\n );\n addPythonCodePackageTarget(\n tree,\n {\n project,\n targetName: `${agentTargetPrefix}-package`,\n bundleTargetName,\n bundleOutputDir,\n packageOutputDir,\n sourceRoot: project.sourceRoot,\n moduleName,\n entryPointPath: joinPathFragments(\n project.root,\n 'package',\n agentNameSnakeCase,\n 'main.py',\n ),\n entryPointFileName: 'main.py',\n },\n DEPENDENCIES,\n );\n\n artifact = {\n type: 'code',\n outputDir: packageOutputDir,\n runtime: agentCorePythonRuntime(),\n entryPoint: PYTHON_AGENT_CORE_LAUNCHER,\n };\n }\n\n // Add shared constructs\n await sharedConstructsGenerator(tree, { iac }, DEPENDENCIES);\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 artifact,\n iac,\n projectName: project.name,\n auth,\n session,\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 // 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: PyAgentMetadata = {\n infra,\n port: localDevPort,\n rc: agentNameClassName,\n auth,\n protocol,\n framework,\n session,\n ...(iac ? { iac } : {}),\n };\n\n addPyDependencies(tree, DEPENDENCIES, {\n metadata,\n projectRoot: project.root,\n });\n addTsDependencies(tree, DEPENDENCIES, { metadata });\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 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 // The spec serialises models a dependency may own, and this target\n // has no `dependsOn` for `default`'s transitive\n // `dependentTasksOutputFiles` to resolve against — so `^production`\n // is the only edge to the dependency, and without it a model change\n // there serves a stale spec.\n inputs: ['production', '^production'],\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]: openApiCodegenTarget({\n generator: 'ts-client',\n openApiSpecPath: `dist/${project.root}/openapi/${agentNameSnakeCase}/openapi.json`,\n outputPath: `${project.root}/scripts/${agentTargetPrefix}/generated`,\n specBuildTargetName: openApiTargetName,\n outputs: [`{projectRoot}/scripts/${agentTargetPrefix}/generated`],\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 metadata,\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":["generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","ensureLicenseExceptions","AG_UI_LANGGRAPH_EXCEPTIONS","addPyDependencies","addTsDependencies","addAgentChatScripts","AGENT_CONNECTION_PY_DEPENDENCIES","addPythonFrameworkBase","ensureLangchainS3CheckpointSaver","ensurePythonAgentConnectionProject","getPythonAgentConnectionModuleName","getPythonAgentConnectionProject","addAgentInfra","addPythonCodePackageTarget","agentCorePythonRuntime","isAgentCoreHosted","isContainerHosted","PYTHON_AGENT_CORE_LAUNCHER","addPythonBundleTarget","resolveContainers","declareDependencies","ownedElsewhere","addDockerScanTarget","DOCKER_DEPENDENCIES","IMAGE_BUILD_CACHE","formatFilesInSubtree","FS_DEPENDENCIES","FsCommands","updateGitIgnore","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toSnakeCase","getNpmScope","addArtifactDependencyToTargets","addComponentDevTarget","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","normalizeTargetKeyOrder","readProjectConfigurationUnqualified","sortObjectKeys","openApiCodegenTarget","getRelativePathToRootByDirectory","toProjectRelativePath","assignPort","addWorkspaceDependencyToPyProject","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","BASE_IMAGES","isIam","m","auth","DEPENDENCIES","ts","name","dev","root","when","protocol","py","framework","session","group","PY_AGENT_GENERATOR_INFO","filename","pyAgentGenerator","tree","options","project","pyProjectPath","Error","sourceRoot","sourceParts","split","moduleName","length","pop","agentTargetPrefix","agentNameSnakeCase","agentNameClassName","targetSourceDir","infra","iac","undefined","console","warn","SESSIONS_BY_FRAMEWORK","strands","langchain","includes","join","localSessionsDir","agentConnectionModuleName","templateContext","dirname","overwriteStrategy","KeepExisting","protocolLower","toLowerCase","container","containers","dockerImageTag","bundleTargetName","bundleOutputDir","pythonPlatform","artifact","pythonBaseImage","python","dockerOutputDir","dockerTargetName","fs","targets","cache","executor","commands","rm","mkdir","cpDir","cpFile","parallel","dependsOn","containerEngine","trivyTargetName","imageTags","type","outputDir","port","packageOutputDir","targetName","entryPointPath","entryPointFileName","runtime","entryPoint","infraProtocol","agentNameKebabCase","projectName","serverProtocol","localDevPortStart","localDevPort","component","info","metadata","rc","projectRoot","serveCommand","openApiTargetName","clientGenTargetName","scriptsDir","patterns","language","chatUrl","chatCommand","httpOnlyTargets","inputs","outputs","generator","openApiSpecPath","outputPath","specBuildTargetName","agentTargets","continuous","cwd","env","PORT","LOCAL_DEV","URL","preferInstallDependencies","languages"],"mappings":"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"}
@@ -4,7 +4,7 @@
4
4
  */ import { generateFiles, joinPathFragments, OverwriteStrategy, updateProjectConfiguration } from "@nx/devkit";
5
5
  import { addPyDependencies, addTsDependencies } from "../../utils/add-dependencies.js";
6
6
  import { addMcpServerInfra } from "../../utils/agent-core-constructs/agent-core-constructs.js";
7
- import { addPythonCodePackageTarget, agentCorePythonRuntime, isAgentCoreHosted, isContainerHosted } from "../../utils/agent-core-packaging.js";
7
+ import { addPythonCodePackageTarget, agentCorePythonRuntime, isAgentCoreHosted, isContainerHosted, PYTHON_AGENT_CORE_LAUNCHER } from "../../utils/agent-core-packaging.js";
8
8
  import { addPythonBundleTarget } from "../../utils/bundle/bundle.js";
9
9
  import { resolveContainers } from "../../utils/containers.js";
10
10
  import { declareDependencies, ownedElsewhere } from "../../utils/declared-dependencies.js";
@@ -169,7 +169,7 @@ export const pyMcpServerGenerator = async (tree, options)=>{
169
169
  type: 'code',
170
170
  outputDir: packageOutputDir,
171
171
  runtime: agentCorePythonRuntime(),
172
- entryPoint: 'main.py'
172
+ entryPoint: PYTHON_AGENT_CORE_LAUNCHER
173
173
  };
174
174
  }
175
175
  // Add shared constructs
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/mcp-server/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport {\n addPyDependencies,\n addTsDependencies,\n} from '../../utils/add-dependencies.js';\nimport {\n type AgentCoreArtifact,\n addMcpServerInfra,\n} from '../../utils/agent-core-constructs/agent-core-constructs.js';\nimport {\n addPythonCodePackageTarget,\n agentCorePythonRuntime,\n isAgentCoreHosted,\n isContainerHosted,\n} from '../../utils/agent-core-packaging.js';\nimport { addPythonBundleTarget } from '../../utils/bundle/bundle.js';\nimport { resolveContainers } from '../../utils/containers.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../utils/declared-dependencies.js';\nimport {\n addDockerScanTarget,\n DOCKER_DEPENDENCIES,\n IMAGE_BUILD_CACHE,\n} from '../../utils/docker.js';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { FS_DEPENDENCIES, FsCommands } from '../../utils/fs.js';\nimport { resolveIac } from '../../utils/iac.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { kebabCase, toClassName, toSnakeCase } from '../../utils/names.js';\nimport { getNpmScope } from '../../utils/npm-scope.js';\nimport {\n addArtifactDependencyToTargets,\n addComponentDevTarget,\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx.js';\nimport { toProjectRelativePath } from '../../utils/paths.js';\nimport { registerPnpmBuiltDependencies } from '../../utils/pnpm-workspace.js';\nimport { assignPort } from '../../utils/port.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../../utils/shared-constructs.js';\nimport type { IacMetadata } from '../../utils/shared-constructs-constants.js';\nimport { BASE_IMAGES } from '../../utils/versions.js';\nimport type { PyMcpServerGeneratorSchema, PyMcpServerInfra } from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface PyMcpServerMetadata extends IacMetadata {\n readonly port: number;\n readonly rc: string;\n readonly auth: string;\n /**\n * How this component is packaged and hosted, so a consumer can tell a\n * code-packaged runtime from a container-packaged one without re-deriving it.\n */\n readonly infra: PyMcpServerInfra;\n}\n\nexport const DEPENDENCIES = declareDependencies<PyMcpServerMetadata>()({\n ts: [\n // The MCP inspector is shared tooling.\n { name: '@modelcontextprotocol/inspector', dev: true, root: true },\n // Added by the helpers that own the projects they belong to.\n ...ownedElsewhere(FS_DEPENDENCIES),\n ...ownedElsewhere(DOCKER_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n py: [\n { name: 'aws-lambda-powertools' },\n { name: 'mcp' },\n { name: 'uvicorn' },\n { name: 'boto3' },\n { name: 'aws-opentelemetry-distro' },\n ],\n});\n\nexport const PY_MCP_SERVER_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const pyMcpServerGenerator = async (\n tree: Tree,\n options: PyMcpServerGeneratorSchema,\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())}-mcp-server`,\n );\n const mcpTargetPrefix = options.name ? name : 'mcp-server';\n\n const mcpServerNameSnakeCase = toSnakeCase(options.name || 'mcp-server');\n const mcpServerNameClassName = toClassName(name);\n\n const targetSourceDir = joinPathFragments(\n project.sourceRoot,\n mcpServerNameSnakeCase,\n );\n\n const infra = options.infra ?? 'agentcore';\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 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 // Generate example server\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'app'),\n targetSourceDir,\n {\n name,\n mcpServerNameSnakeCase,\n mcpServerNameClassName,\n moduleName,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n if (isAgentCoreHosted(infra)) {\n const container = isContainerHosted(infra);\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 let artifact: AgentCoreArtifact;\n\n if (container) {\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'deploy'),\n targetSourceDir,\n {\n mcpServerNameSnakeCase,\n moduleName,\n bundleOutputDir,\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 = `${mcpTargetPrefix}-docker`;\n\n // Add a docker target that prepares the docker context and builds the image\n const fs = new FsCommands(tree, DEPENDENCIES);\n project.targets[dockerTargetName] = {\n cache: IMAGE_BUILD_CACHE,\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(dockerOutputDir),\n fs.mkdir(dockerOutputDir),\n fs.cpDir(bundleOutputDir, dockerOutputDir),\n fs.cpFile(\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 addArtifactDependencyToTargets(project, 'docker');\n\n addDockerScanTarget(\n tree,\n {\n project,\n containerEngine: containers,\n trivyTargetName: `${mcpTargetPrefix}-trivy`,\n dockerTargetName,\n imageTags: [dockerImageTag],\n },\n DEPENDENCIES,\n );\n\n artifact = {\n type: 'container',\n dockerImageTag,\n outputDir: dockerOutputDir,\n };\n } else {\n // The entry point the managed runtime runs, at the package root.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'package'),\n joinPathFragments(project.root, 'package', mcpServerNameSnakeCase),\n {\n mcpServerNameSnakeCase,\n moduleName,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n const packageOutputDir = joinPathFragments(\n 'dist',\n project.root,\n 'package',\n name,\n );\n addPythonCodePackageTarget(\n tree,\n {\n project,\n targetName: `${mcpTargetPrefix}-package`,\n bundleTargetName,\n bundleOutputDir,\n packageOutputDir,\n sourceRoot: project.sourceRoot,\n moduleName,\n entryPointPath: joinPathFragments(\n project.root,\n 'package',\n mcpServerNameSnakeCase,\n 'main.py',\n ),\n entryPointFileName: 'main.py',\n },\n DEPENDENCIES,\n );\n\n artifact = {\n type: 'code',\n outputDir: packageOutputDir,\n runtime: agentCorePythonRuntime(),\n entryPoint: 'main.py',\n };\n }\n\n // Add shared constructs\n await sharedConstructsGenerator(tree, { iac }, DEPENDENCIES);\n\n // Add the construct to deploy the mcp server\n await addMcpServerInfra(tree, {\n mcpServerNameKebabCase: name,\n mcpServerNameClassName,\n projectName: project.name,\n artifact,\n iac,\n auth,\n containers,\n });\n }\n\n const localDevPort = assignPort(tree, project, 8000, {\n component: { info: PY_MCP_SERVER_GENERATOR_INFO, name: mcpTargetPrefix },\n });\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: PyMcpServerMetadata = {\n infra,\n port: localDevPort,\n rc: mcpServerNameClassName,\n auth,\n ...(iac ? { iac } : {}),\n };\n\n // The MCP inspector has a postinstall script that cascades installs into its\n // client packages, which no-ops when the package is installed as a dependency.\n // Register it as an explicitly-rejected build so pnpm 11's default\n // `strictDepBuilds=true` skips it instead of failing the install.\n registerPnpmBuiltDependencies(tree, {\n '@modelcontextprotocol/inspector': false,\n });\n\n addPyDependencies(tree, DEPENDENCIES, {\n metadata,\n projectRoot: project.root,\n });\n addTsDependencies(tree, DEPENDENCIES, { metadata });\n\n const mcpTargets = {\n ...project.targets,\n // Add targets for running the MCP server\n [`${mcpTargetPrefix}-serve-stdio`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [`uv run -m ${moduleName}.${mcpServerNameSnakeCase}.stdio`],\n cwd: '{projectRoot}',\n },\n },\n [`${mcpTargetPrefix}-serve`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [\n `uv run uvicorn --reload ${moduleName}.${mcpServerNameSnakeCase}.http:app --host 0.0.0.0 --port ${localDevPort}`,\n ],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n },\n },\n },\n [`${mcpTargetPrefix}-dev`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [\n `uv run uvicorn --reload ${moduleName}.${mcpServerNameSnakeCase}.http:app --host 0.0.0.0 --port ${localDevPort}`,\n ],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n LOCAL_DEV: 'true',\n },\n },\n },\n [`${mcpTargetPrefix}-inspect`]: {\n executor: 'nx:run-commands',\n continuous: true,\n // Launch the inspector against the locally served HTTP server. The dev\n // target starts the server and any connected dependencies (e.g. a local\n // database).\n dependsOn: [`${mcpTargetPrefix}-dev`],\n options: {\n commands: [\n `mcp-inspector --transport http --server-url http://localhost:${localDevPort}/mcp`,\n ],\n cwd: '{projectRoot}',\n },\n },\n [`${mcpTargetPrefix}-inspect-stdio`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [\n `mcp-inspector -- uv run -m ${moduleName}.${mcpServerNameSnakeCase}.stdio`,\n ],\n cwd: '{projectRoot}',\n },\n },\n };\n\n // Aggregate `<mcp>-dev` under the project-level `dev` target.\n addComponentDevTarget(mcpTargets, `${mcpTargetPrefix}-dev`);\n\n updateProjectConfiguration(tree, project.name, {\n ...project,\n targets: mcpTargets,\n });\n\n addComponentGeneratorMetadata(\n tree,\n project.name,\n PY_MCP_SERVER_GENERATOR_INFO,\n toProjectRelativePath(project, targetSourceDir),\n mcpTargetPrefix,\n metadata,\n );\n\n await addGeneratorMetricsIfApplicable(tree, [PY_MCP_SERVER_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\n\nexport default pyMcpServerGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","addPyDependencies","addTsDependencies","addMcpServerInfra","addPythonCodePackageTarget","agentCorePythonRuntime","isAgentCoreHosted","isContainerHosted","addPythonBundleTarget","resolveContainers","declareDependencies","ownedElsewhere","addDockerScanTarget","DOCKER_DEPENDENCIES","IMAGE_BUILD_CACHE","formatFilesInSubtree","FS_DEPENDENCIES","FsCommands","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toSnakeCase","getNpmScope","addArtifactDependencyToTargets","addComponentDevTarget","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","readProjectConfigurationUnqualified","toProjectRelativePath","registerPnpmBuiltDependencies","assignPort","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","BASE_IMAGES","DEPENDENCIES","ts","name","dev","root","py","PY_MCP_SERVER_GENERATOR_INFO","filename","pyMcpServerGenerator","tree","options","project","pyProjectPath","Error","sourceRoot","sourceParts","split","moduleName","length","pop","mcpTargetPrefix","mcpServerNameSnakeCase","mcpServerNameClassName","targetSourceDir","infra","iac","undefined","auth","console","warn","dirname","overwriteStrategy","KeepExisting","container","containers","dockerImageTag","bundleTargetName","bundleOutputDir","pythonPlatform","artifact","pythonBaseImage","python","dockerOutputDir","dockerTargetName","fs","targets","cache","executor","commands","rm","mkdir","cpDir","cpFile","parallel","dependsOn","containerEngine","trivyTargetName","imageTags","type","outputDir","packageOutputDir","targetName","entryPointPath","entryPointFileName","runtime","entryPoint","mcpServerNameKebabCase","projectName","localDevPort","component","info","metadata","port","rc","projectRoot","mcpTargets","continuous","cwd","env","PORT","LOCAL_DEV","preferInstallDependencies","languages"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/mcp-server/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport {\n addPyDependencies,\n addTsDependencies,\n} from '../../utils/add-dependencies.js';\nimport {\n type AgentCoreArtifact,\n addMcpServerInfra,\n} from '../../utils/agent-core-constructs/agent-core-constructs.js';\nimport {\n addPythonCodePackageTarget,\n agentCorePythonRuntime,\n isAgentCoreHosted,\n isContainerHosted,\n PYTHON_AGENT_CORE_LAUNCHER,\n} from '../../utils/agent-core-packaging.js';\nimport { addPythonBundleTarget } from '../../utils/bundle/bundle.js';\nimport { resolveContainers } from '../../utils/containers.js';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../utils/declared-dependencies.js';\nimport {\n addDockerScanTarget,\n DOCKER_DEPENDENCIES,\n IMAGE_BUILD_CACHE,\n} from '../../utils/docker.js';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { FS_DEPENDENCIES, FsCommands } from '../../utils/fs.js';\nimport { resolveIac } from '../../utils/iac.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { kebabCase, toClassName, toSnakeCase } from '../../utils/names.js';\nimport { getNpmScope } from '../../utils/npm-scope.js';\nimport {\n addArtifactDependencyToTargets,\n addComponentDevTarget,\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx.js';\nimport { toProjectRelativePath } from '../../utils/paths.js';\nimport { registerPnpmBuiltDependencies } from '../../utils/pnpm-workspace.js';\nimport { assignPort } from '../../utils/port.js';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../../utils/shared-constructs.js';\nimport type { IacMetadata } from '../../utils/shared-constructs-constants.js';\nimport { BASE_IMAGES } from '../../utils/versions.js';\nimport type { PyMcpServerGeneratorSchema, PyMcpServerInfra } from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface PyMcpServerMetadata extends IacMetadata {\n readonly port: number;\n readonly rc: string;\n readonly auth: string;\n /**\n * How this component is packaged and hosted, so a consumer can tell a\n * code-packaged runtime from a container-packaged one without re-deriving it.\n */\n readonly infra: PyMcpServerInfra;\n}\n\nexport const DEPENDENCIES = declareDependencies<PyMcpServerMetadata>()({\n ts: [\n // The MCP inspector is shared tooling.\n { name: '@modelcontextprotocol/inspector', dev: true, root: true },\n // Added by the helpers that own the projects they belong to.\n ...ownedElsewhere(FS_DEPENDENCIES),\n ...ownedElsewhere(DOCKER_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n py: [\n { name: 'aws-lambda-powertools' },\n { name: 'mcp' },\n { name: 'uvicorn' },\n { name: 'boto3' },\n { name: 'aws-opentelemetry-distro' },\n ],\n});\n\nexport const PY_MCP_SERVER_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const pyMcpServerGenerator = async (\n tree: Tree,\n options: PyMcpServerGeneratorSchema,\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())}-mcp-server`,\n );\n const mcpTargetPrefix = options.name ? name : 'mcp-server';\n\n const mcpServerNameSnakeCase = toSnakeCase(options.name || 'mcp-server');\n const mcpServerNameClassName = toClassName(name);\n\n const targetSourceDir = joinPathFragments(\n project.sourceRoot,\n mcpServerNameSnakeCase,\n );\n\n const infra = options.infra ?? 'agentcore';\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 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 // Generate example server\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'app'),\n targetSourceDir,\n {\n name,\n mcpServerNameSnakeCase,\n mcpServerNameClassName,\n moduleName,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n if (isAgentCoreHosted(infra)) {\n const container = isContainerHosted(infra);\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 let artifact: AgentCoreArtifact;\n\n if (container) {\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'deploy'),\n targetSourceDir,\n {\n mcpServerNameSnakeCase,\n moduleName,\n bundleOutputDir,\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 = `${mcpTargetPrefix}-docker`;\n\n // Add a docker target that prepares the docker context and builds the image\n const fs = new FsCommands(tree, DEPENDENCIES);\n project.targets[dockerTargetName] = {\n cache: IMAGE_BUILD_CACHE,\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(dockerOutputDir),\n fs.mkdir(dockerOutputDir),\n fs.cpDir(bundleOutputDir, dockerOutputDir),\n fs.cpFile(\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 addArtifactDependencyToTargets(project, 'docker');\n\n addDockerScanTarget(\n tree,\n {\n project,\n containerEngine: containers,\n trivyTargetName: `${mcpTargetPrefix}-trivy`,\n dockerTargetName,\n imageTags: [dockerImageTag],\n },\n DEPENDENCIES,\n );\n\n artifact = {\n type: 'container',\n dockerImageTag,\n outputDir: dockerOutputDir,\n };\n } else {\n // The entry point the managed runtime runs, at the package root.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'package'),\n joinPathFragments(project.root, 'package', mcpServerNameSnakeCase),\n {\n mcpServerNameSnakeCase,\n moduleName,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n const packageOutputDir = joinPathFragments(\n 'dist',\n project.root,\n 'package',\n name,\n );\n addPythonCodePackageTarget(\n tree,\n {\n project,\n targetName: `${mcpTargetPrefix}-package`,\n bundleTargetName,\n bundleOutputDir,\n packageOutputDir,\n sourceRoot: project.sourceRoot,\n moduleName,\n entryPointPath: joinPathFragments(\n project.root,\n 'package',\n mcpServerNameSnakeCase,\n 'main.py',\n ),\n entryPointFileName: 'main.py',\n },\n DEPENDENCIES,\n );\n\n artifact = {\n type: 'code',\n outputDir: packageOutputDir,\n runtime: agentCorePythonRuntime(),\n entryPoint: PYTHON_AGENT_CORE_LAUNCHER,\n };\n }\n\n // Add shared constructs\n await sharedConstructsGenerator(tree, { iac }, DEPENDENCIES);\n\n // Add the construct to deploy the mcp server\n await addMcpServerInfra(tree, {\n mcpServerNameKebabCase: name,\n mcpServerNameClassName,\n projectName: project.name,\n artifact,\n iac,\n auth,\n containers,\n });\n }\n\n const localDevPort = assignPort(tree, project, 8000, {\n component: { info: PY_MCP_SERVER_GENERATOR_INFO, name: mcpTargetPrefix },\n });\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: PyMcpServerMetadata = {\n infra,\n port: localDevPort,\n rc: mcpServerNameClassName,\n auth,\n ...(iac ? { iac } : {}),\n };\n\n // The MCP inspector has a postinstall script that cascades installs into its\n // client packages, which no-ops when the package is installed as a dependency.\n // Register it as an explicitly-rejected build so pnpm 11's default\n // `strictDepBuilds=true` skips it instead of failing the install.\n registerPnpmBuiltDependencies(tree, {\n '@modelcontextprotocol/inspector': false,\n });\n\n addPyDependencies(tree, DEPENDENCIES, {\n metadata,\n projectRoot: project.root,\n });\n addTsDependencies(tree, DEPENDENCIES, { metadata });\n\n const mcpTargets = {\n ...project.targets,\n // Add targets for running the MCP server\n [`${mcpTargetPrefix}-serve-stdio`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [`uv run -m ${moduleName}.${mcpServerNameSnakeCase}.stdio`],\n cwd: '{projectRoot}',\n },\n },\n [`${mcpTargetPrefix}-serve`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [\n `uv run uvicorn --reload ${moduleName}.${mcpServerNameSnakeCase}.http:app --host 0.0.0.0 --port ${localDevPort}`,\n ],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n },\n },\n },\n [`${mcpTargetPrefix}-dev`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [\n `uv run uvicorn --reload ${moduleName}.${mcpServerNameSnakeCase}.http:app --host 0.0.0.0 --port ${localDevPort}`,\n ],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n LOCAL_DEV: 'true',\n },\n },\n },\n [`${mcpTargetPrefix}-inspect`]: {\n executor: 'nx:run-commands',\n continuous: true,\n // Launch the inspector against the locally served HTTP server. The dev\n // target starts the server and any connected dependencies (e.g. a local\n // database).\n dependsOn: [`${mcpTargetPrefix}-dev`],\n options: {\n commands: [\n `mcp-inspector --transport http --server-url http://localhost:${localDevPort}/mcp`,\n ],\n cwd: '{projectRoot}',\n },\n },\n [`${mcpTargetPrefix}-inspect-stdio`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [\n `mcp-inspector -- uv run -m ${moduleName}.${mcpServerNameSnakeCase}.stdio`,\n ],\n cwd: '{projectRoot}',\n },\n },\n };\n\n // Aggregate `<mcp>-dev` under the project-level `dev` target.\n addComponentDevTarget(mcpTargets, `${mcpTargetPrefix}-dev`);\n\n updateProjectConfiguration(tree, project.name, {\n ...project,\n targets: mcpTargets,\n });\n\n addComponentGeneratorMetadata(\n tree,\n project.name,\n PY_MCP_SERVER_GENERATOR_INFO,\n toProjectRelativePath(project, targetSourceDir),\n mcpTargetPrefix,\n metadata,\n );\n\n await addGeneratorMetricsIfApplicable(tree, [PY_MCP_SERVER_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\n\nexport default pyMcpServerGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","addPyDependencies","addTsDependencies","addMcpServerInfra","addPythonCodePackageTarget","agentCorePythonRuntime","isAgentCoreHosted","isContainerHosted","PYTHON_AGENT_CORE_LAUNCHER","addPythonBundleTarget","resolveContainers","declareDependencies","ownedElsewhere","addDockerScanTarget","DOCKER_DEPENDENCIES","IMAGE_BUILD_CACHE","formatFilesInSubtree","FS_DEPENDENCIES","FsCommands","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toSnakeCase","getNpmScope","addArtifactDependencyToTargets","addComponentDevTarget","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","readProjectConfigurationUnqualified","toProjectRelativePath","registerPnpmBuiltDependencies","assignPort","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","BASE_IMAGES","DEPENDENCIES","ts","name","dev","root","py","PY_MCP_SERVER_GENERATOR_INFO","filename","pyMcpServerGenerator","tree","options","project","pyProjectPath","Error","sourceRoot","sourceParts","split","moduleName","length","pop","mcpTargetPrefix","mcpServerNameSnakeCase","mcpServerNameClassName","targetSourceDir","infra","iac","undefined","auth","console","warn","dirname","overwriteStrategy","KeepExisting","container","containers","dockerImageTag","bundleTargetName","bundleOutputDir","pythonPlatform","artifact","pythonBaseImage","python","dockerOutputDir","dockerTargetName","fs","targets","cache","executor","commands","rm","mkdir","cpDir","cpFile","parallel","dependsOn","containerEngine","trivyTargetName","imageTags","type","outputDir","packageOutputDir","targetName","entryPointPath","entryPointFileName","runtime","entryPoint","mcpServerNameKebabCase","projectName","localDevPort","component","info","metadata","port","rc","projectRoot","mcpTargets","continuous","cwd","env","PORT","LOCAL_DEV","preferInstallDependencies","languages"],"mappings":"AAAA;;;CAGC,GACD,SAEEA,aAAa,EACbC,iBAAiB,EACjBC,iBAAiB,EAEjBC,0BAA0B,QACrB,aAAa;AACpB,SACEC,iBAAiB,EACjBC,iBAAiB,QACZ,kCAAkC;AACzC,SAEEC,iBAAiB,QACZ,6DAA6D;AACpE,SACEC,0BAA0B,EAC1BC,sBAAsB,EACtBC,iBAAiB,EACjBC,iBAAiB,EACjBC,0BAA0B,QACrB,sCAAsC;AAC7C,SAASC,qBAAqB,QAAQ,+BAA+B;AACrE,SAASC,iBAAiB,QAAQ,4BAA4B;AAC9D,SACEC,mBAAmB,EACnBC,cAAc,QACT,uCAAuC;AAC9C,SACEC,mBAAmB,EACnBC,mBAAmB,EACnBC,iBAAiB,QACZ,wBAAwB;AAC/B,SAASC,oBAAoB,QAAQ,wBAAwB;AAC7D,SAASC,eAAe,EAAEC,UAAU,QAAQ,oBAAoB;AAChE,SAASC,UAAU,QAAQ,qBAAqB;AAChD,SAASC,mBAAmB,QAAQ,yBAAyB;AAC7D,SAASC,+BAA+B,QAAQ,yBAAyB;AACzE,SAASC,SAAS,EAAEC,WAAW,EAAEC,WAAW,QAAQ,uBAAuB;AAC3E,SAASC,WAAW,QAAQ,2BAA2B;AACvD,SACEC,8BAA8B,EAC9BC,qBAAqB,EACrBC,6BAA6B,EAC7BC,iCAAiC,EACjCC,gBAAgB,EAEhBC,mCAAmC,QAC9B,oBAAoB;AAC3B,SAASC,qBAAqB,QAAQ,uBAAuB;AAC7D,SAASC,6BAA6B,QAAQ,gCAAgC;AAC9E,SAASC,UAAU,QAAQ,sBAAsB;AACjD,SACEC,8BAA8B,EAC9BC,yBAAyB,QACpB,mCAAmC;AAE1C,SAASC,WAAW,QAAQ,0BAA0B;AAetD,OAAO,MAAMC,eAAe3B,sBAA2C;IACrE4B,IAAI;QACF,uCAAuC;QACvC;YAAEC,MAAM;YAAmCC,KAAK;YAAMC,MAAM;QAAK;QACjE,6DAA6D;WAC1D9B,eAAeK;WACfL,eAAeE;WACfF,eAAeuB;KACnB;IACDQ,IAAI;QACF;YAAEH,MAAM;QAAwB;QAChC;YAAEA,MAAM;QAAM;QACd;YAAEA,MAAM;QAAU;QAClB;YAAEA,MAAM;QAAQ;QAChB;YAAEA,MAAM;QAA2B;KACpC;AACH,GAAG;AAEH,OAAO,MAAMI,+BAAgDd,iBAC3D,YAAYe,QAAQ,EACpB;AAEF,OAAO,MAAMC,uBAAuB,OAClCC,MACAC;IAEA,MAAMC,UAAUlB,oCAAoCgB,MAAMC,QAAQC,OAAO;IAEzE,MAAMC,gBAAgBpD,kBAAkBmD,QAAQP,IAAI,EAAE;IAEtD,iDAAiD;IACjD,IAAI,CAACQ,eAAe;QAClB,MAAM,IAAIC,MACR,CAAC,oBAAoB,EAAEH,QAAQC,OAAO,CAAC,mDAAmD,CAAC;IAE/F;IAEA,IAAI,CAACA,QAAQG,UAAU,EAAE;QACvB,MAAM,IAAID,MACR,CAAC,8HAA8H,CAAC;IAEpI;IAEA,mDAAmD;IACnD,MAAME,cAAcJ,QAAQG,UAAU,CAACE,KAAK,CAAC;IAC7C,MAAMC,aAAaF,WAAW,CAACA,YAAYG,MAAM,GAAG,EAAE;IAEtD,MAAMhB,OAAOlB,UACX0B,QAAQR,IAAI,IAAI,GAAGlB,UAAU2B,QAAQT,IAAI,CAACc,KAAK,CAAC,KAAKG,GAAG,IAAI,WAAW,CAAC;IAE1E,MAAMC,kBAAkBV,QAAQR,IAAI,GAAGA,OAAO;IAE9C,MAAMmB,yBAAyBnC,YAAYwB,QAAQR,IAAI,IAAI;IAC3D,MAAMoB,yBAAyBrC,YAAYiB;IAE3C,MAAMqB,kBAAkB/D,kBACtBmD,QAAQG,UAAU,EAClBO;IAGF,MAAMG,QAAQd,QAAQc,KAAK,IAAI;IAE/B,oEAAoE;IACpE,qEAAqE;IACrE,mEAAmE;IACnE,MAAMC,MACJD,UAAU,SAAS,MAAM3C,WAAW4B,MAAMC,QAAQe,GAAG,IAAIC;IAE3D,IAAIF,UAAU,UAAUd,QAAQiB,IAAI,IAAIjB,QAAQiB,IAAI,KAAK,OAAO;QAC9DC,QAAQC,IAAI,CACV;IAEJ;IAEA,MAAMF,OAAOjB,QAAQiB,IAAI,IAAI;IAE7B,0BAA0B;IAC1BpE,cACEkD,MACAjD,kBAAkB,YAAYsE,OAAO,EAAE,SAAS,QAChDP,iBACA;QACErB;QACAmB;QACAC;QACAL;IACF,GACA;QAAEc,mBAAmBtE,kBAAkBuE,YAAY;IAAC;IAGtD,IAAIhE,kBAAkBwD,QAAQ;QAC5B,MAAMS,YAAYhE,kBAAkBuD;QACpC,MAAMU,aAAa,MAAM9D,kBAAkBqC,MAAM;QACjD,MAAM0B,iBAAiB,GAAGhD,YAAYsB,MAAM,CAAC,EAAEP,KAAK,OAAO,CAAC;QAE5D,oBAAoB;QACpB,MAAM,EAAEkC,gBAAgB,EAAEC,eAAe,EAAE,GAAGlE,sBAC5CwC,SACA;YACE2B,gBAAgB;QAClB;QAGF,IAAIC;QAEJ,IAAIN,WAAW;YACb1E,cACEkD,MACAjD,kBAAkB,YAAYsE,OAAO,EAAE,SAAS,WAChDP,iBACA;gBACEF;gBACAJ;gBACAoB;gBACAG,iBAAiBzC,YAAY0C,MAAM;YACrC,GACA;gBAAEV,mBAAmBtE,kBAAkBuE,YAAY;YAAC;YAGtD,MAAMU,kBAAkBlF,kBACtB,QACAmD,QAAQP,IAAI,EACZ,UACAF;YAEF,MAAMyC,mBAAmB,GAAGvB,gBAAgB,OAAO,CAAC;YAEpD,4EAA4E;YAC5E,MAAMwB,KAAK,IAAIhE,WAAW6B,MAAMT;YAChCW,QAAQkC,OAAO,CAACF,iBAAiB,GAAG;gBAClCG,OAAOrE;gBACPsE,UAAU;gBACVrC,SAAS;oBACPsC,UAAU;wBACRJ,GAAGK,EAAE,CAACP;wBACNE,GAAGM,KAAK,CAACR;wBACTE,GAAGO,KAAK,CAACd,iBAAiBK;wBAC1BE,GAAGQ,MAAM,CACP,GAAG7B,gBAAgB,WAAW,CAAC,EAC/B,GAAGmB,gBAAgB,WAAW,CAAC;wBAEjC,GAAGR,WAAW,iCAAiC,EAAEC,eAAe,CAAC,EAAEO,iBAAiB;qBACrF;oBACDW,UAAU;gBACZ;gBACAC,WAAW;oBAAClB;iBAAiB;YAC/B;YAEA7C,kCAAkCoB,SAAS,UAAUgC;YACrDvD,+BAA+BuB,SAAS;YAExCpC,oBACEkC,MACA;gBACEE;gBACA4C,iBAAiBrB;gBACjBsB,iBAAiB,GAAGpC,gBAAgB,MAAM,CAAC;gBAC3CuB;gBACAc,WAAW;oBAACtB;iBAAe;YAC7B,GACAnC;YAGFuC,WAAW;gBACTmB,MAAM;gBACNvB;gBACAwB,WAAWjB;YACb;QACF,OAAO;YACL,iEAAiE;YACjEnF,cACEkD,MACAjD,kBAAkB,YAAYsE,OAAO,EAAE,SAAS,YAChDtE,kBAAkBmD,QAAQP,IAAI,EAAE,WAAWiB,yBAC3C;gBACEA;gBACAJ;YACF,GACA;gBAAEc,mBAAmBtE,kBAAkBuE,YAAY;YAAC;YAGtD,MAAM4B,mBAAmBpG,kBACvB,QACAmD,QAAQP,IAAI,EACZ,WACAF;YAEFpC,2BACE2C,MACA;gBACEE;gBACAkD,YAAY,GAAGzC,gBAAgB,QAAQ,CAAC;gBACxCgB;gBACAC;gBACAuB;gBACA9C,YAAYH,QAAQG,UAAU;gBAC9BG;gBACA6C,gBAAgBtG,kBACdmD,QAAQP,IAAI,EACZ,WACAiB,wBACA;gBAEF0C,oBAAoB;YACtB,GACA/D;YAGFuC,WAAW;gBACTmB,MAAM;gBACNC,WAAWC;gBACXI,SAASjG;gBACTkG,YAAY/F;YACd;QACF;QAEA,wBAAwB;QACxB,MAAM4B,0BAA0BW,MAAM;YAAEgB;QAAI,GAAGzB;QAE/C,6CAA6C;QAC7C,MAAMnC,kBAAkB4C,MAAM;YAC5ByD,wBAAwBhE;YACxBoB;YACA6C,aAAaxD,QAAQT,IAAI;YACzBqC;YACAd;YACAE;YACAO;QACF;IACF;IAEA,MAAMkC,eAAexE,WAAWa,MAAME,SAAS,MAAM;QACnD0D,WAAW;YAAEC,MAAMhE;YAA8BJ,MAAMkB;QAAgB;IACzE;IAEA,2EAA2E;IAC3E,6DAA6D;IAC7D,MAAMmD,WAAgC;QACpC/C;QACAgD,MAAMJ;QACNK,IAAInD;QACJK;QACA,GAAIF,MAAM;YAAEA;QAAI,IAAI,CAAC,CAAC;IACxB;IAEA,6EAA6E;IAC7E,+EAA+E;IAC/E,mEAAmE;IACnE,kEAAkE;IAClE9B,8BAA8Bc,MAAM;QAClC,mCAAmC;IACrC;IAEA9C,kBAAkB8C,MAAMT,cAAc;QACpCuE;QACAG,aAAa/D,QAAQP,IAAI;IAC3B;IACAxC,kBAAkB6C,MAAMT,cAAc;QAAEuE;IAAS;IAEjD,MAAMI,aAAa;QACjB,GAAGhE,QAAQkC,OAAO;QAClB,yCAAyC;QACzC,CAAC,GAAGzB,gBAAgB,YAAY,CAAC,CAAC,EAAE;YAClC2B,UAAU;YACV6B,YAAY;YACZlE,SAAS;gBACPsC,UAAU;oBAAC,CAAC,UAAU,EAAE/B,WAAW,CAAC,EAAEI,uBAAuB,MAAM,CAAC;iBAAC;gBACrEwD,KAAK;YACP;QACF;QACA,CAAC,GAAGzD,gBAAgB,MAAM,CAAC,CAAC,EAAE;YAC5B2B,UAAU;YACV6B,YAAY;YACZlE,SAAS;gBACPsC,UAAU;oBACR,CAAC,wBAAwB,EAAE/B,WAAW,CAAC,EAAEI,uBAAuB,gCAAgC,EAAE+C,cAAc;iBACjH;gBACDS,KAAK;gBACLC,KAAK;oBACHC,MAAM,GAAGX,cAAc;gBACzB;YACF;QACF;QACA,CAAC,GAAGhD,gBAAgB,IAAI,CAAC,CAAC,EAAE;YAC1B2B,UAAU;YACV6B,YAAY;YACZlE,SAAS;gBACPsC,UAAU;oBACR,CAAC,wBAAwB,EAAE/B,WAAW,CAAC,EAAEI,uBAAuB,gCAAgC,EAAE+C,cAAc;iBACjH;gBACDS,KAAK;gBACLC,KAAK;oBACHC,MAAM,GAAGX,cAAc;oBACvBY,WAAW;gBACb;YACF;QACF;QACA,CAAC,GAAG5D,gBAAgB,QAAQ,CAAC,CAAC,EAAE;YAC9B2B,UAAU;YACV6B,YAAY;YACZ,uEAAuE;YACvE,wEAAwE;YACxE,aAAa;YACbtB,WAAW;gBAAC,GAAGlC,gBAAgB,IAAI,CAAC;aAAC;YACrCV,SAAS;gBACPsC,UAAU;oBACR,CAAC,6DAA6D,EAAEoB,aAAa,IAAI,CAAC;iBACnF;gBACDS,KAAK;YACP;QACF;QACA,CAAC,GAAGzD,gBAAgB,cAAc,CAAC,CAAC,EAAE;YACpC2B,UAAU;YACV6B,YAAY;YACZlE,SAAS;gBACPsC,UAAU;oBACR,CAAC,2BAA2B,EAAE/B,WAAW,CAAC,EAAEI,uBAAuB,MAAM,CAAC;iBAC3E;gBACDwD,KAAK;YACP;QACF;IACF;IAEA,8DAA8D;IAC9DxF,sBAAsBsF,YAAY,GAAGvD,gBAAgB,IAAI,CAAC;IAE1D1D,2BAA2B+C,MAAME,QAAQT,IAAI,EAAE;QAC7C,GAAGS,OAAO;QACVkC,SAAS8B;IACX;IAEArF,8BACEmB,MACAE,QAAQT,IAAI,EACZI,8BACAZ,sBAAsBiB,SAASY,kBAC/BH,iBACAmD;IAGF,MAAMxF,gCAAgC0B,MAAM;QAACH;KAA6B;IAE1E,MAAM5B,qBAAqB+B;IAC3B,OAAO,IACL3B,oBAAoB2B,MAAMC,QAAQuE,yBAAyB,EAAE;YAC3DC,WAAW;gBAAC;gBAAc;aAAS;QACrC;AACJ,EAAE;AAEF,eAAe1E,qBAAqB"}
@@ -162,7 +162,7 @@ export class <%- nameClassName %> extends Construct implements IGrantable, IConn
162
162
  this.code = AgentRuntimeArtifact.fromCodeAsset({
163
163
  path: bundleDir,
164
164
  runtime: AgentCoreRuntime.<%- codeRuntime %>,
165
- entrypoint: ['opentelemetry-instrument', '<%- codeEntryPoint %>'],
165
+ entrypoint: [<% if (!codeRuntime.startsWith('PYTHON_')) { %>'opentelemetry-instrument', <% } %>'<%- codeEntryPoint %>'],
166
166
  });
167
167
  <%_ } _%>
168
168
 
@@ -140,7 +140,7 @@ module "runtime" {
140
140
  # The `opentelemetry-instrument` prefix auto-instruments with the AWS Distro
141
141
  # for OpenTelemetry packaged alongside the code.
142
142
  # https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/observability-configure.html
143
- entry_point = ["opentelemetry-instrument", var.code_entry_point]
143
+ entry_point = var.code_entry_point == "agentcore_launcher.py" ? [var.code_entry_point] : ["opentelemetry-instrument", var.code_entry_point]
144
144
  runtime = var.code_runtime
145
145
  s3_bucket = aws_s3_object.agent_core_code.bucket
146
146
  s3_key = aws_s3_object.agent_core_code.key
@@ -25,6 +25,9 @@ export declare const isContainerHosted: (infra: AgentCoreInfra) => boolean;
25
25
  export declare const agentCoreNodeRuntime: () => string;
26
26
  /** The AgentCore managed runtime a Python component targets. */
27
27
  export declare const agentCorePythonRuntime: () => string;
28
+ export declare const PYTHON_AGENT_CORE_LAUNCHER = "agentcore_launcher.py";
29
+ /** Run instrumentation with the managed interpreter, independent of console-script shebangs. */
30
+ export declare const pythonAgentCoreLauncher: (entryPointFileName: string) => string;
28
31
  /**
29
32
  * Dependencies a caller must declare to add a code (`.zip`) packaging target.
30
33
  *
@@ -117,10 +120,10 @@ export interface AddPythonCodePackageTargetOptions {
117
120
  * Add a target assembling the deployable code package for a Python AgentCore
118
121
  * Runtime.
119
122
  *
120
- * The package is the arm64 dependency bundle (which already carries
121
- * `bin/opentelemetry-instrument` from `aws-opentelemetry-distro`, satisfying
122
- * AgentCore's requirement that OpenTelemetry be present), the project's own
123
- * module tree, and a root entry point script.
123
+ * The package contains the arm64 dependency bundle with `aws-opentelemetry-distro`,
124
+ * the project's module tree, its root entry point and an instrumentation launcher.
125
+ * The launcher calls OpenTelemetry's `run()` with `sys.executable` and the original
126
+ * entry point, so a console-script shebang cannot select the build machine's Python.
124
127
  *
125
128
  * The entry point sits at the package root rather than inside the module:
126
129
  * AgentCore runs it as a file path, and Python gives a script run that way no
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
- */ import { joinPathFragments } from "@nx/devkit";
4
+ */ import { dirname } from "node:path";
5
+ import { joinPathFragments } from "@nx/devkit";
5
6
  import { forDependencies } from "./declared-dependencies.js";
6
7
  import { FS_DEPENDENCIES, FsCommands } from "./fs.js";
7
8
  import { addArtifactDependencyToTargets, normalizeTargetKeyOrder } from "./nx.js";
@@ -24,6 +25,22 @@ import { agentCoreRuntime, TS_VERSIONS } from "./versions.js";
24
25
  /** Whether the given infra option builds and hosts a container image. */ export const isContainerHosted = (infra)=>infra === 'agentcore-ecr';
25
26
  /** The AgentCore managed runtime a TypeScript component targets. */ export const agentCoreNodeRuntime = ()=>agentCoreRuntime('node');
26
27
  /** The AgentCore managed runtime a Python component targets. */ export const agentCorePythonRuntime = ()=>agentCoreRuntime('python');
28
+ export const PYTHON_AGENT_CORE_LAUNCHER = 'agentcore_launcher.py';
29
+ /** Run instrumentation with the managed interpreter, independent of console-script shebangs. */ export const pythonAgentCoreLauncher = (entryPointFileName)=>`\
30
+ import sys
31
+ from pathlib import Path
32
+
33
+ from opentelemetry.instrumentation.auto_instrumentation import run
34
+
35
+ if __name__ == "__main__":
36
+ sys.argv = [
37
+ "opentelemetry-instrument",
38
+ sys.executable,
39
+ str(Path(__file__).with_name(${JSON.stringify(entryPointFileName)})),
40
+ *sys.argv[1:],
41
+ ]
42
+ run()
43
+ `;
27
44
  /**
28
45
  * Dependencies a caller must declare to add a code (`.zip`) packaging target.
29
46
  *
@@ -122,10 +139,10 @@ import { agentCoreRuntime, TS_VERSIONS } from "./versions.js";
122
139
  * Add a target assembling the deployable code package for a Python AgentCore
123
140
  * Runtime.
124
141
  *
125
- * The package is the arm64 dependency bundle (which already carries
126
- * `bin/opentelemetry-instrument` from `aws-opentelemetry-distro`, satisfying
127
- * AgentCore's requirement that OpenTelemetry be present), the project's own
128
- * module tree, and a root entry point script.
142
+ * The package contains the arm64 dependency bundle with `aws-opentelemetry-distro`,
143
+ * the project's module tree, its root entry point and an instrumentation launcher.
144
+ * The launcher calls OpenTelemetry's `run()` with `sys.executable` and the original
145
+ * entry point, so a console-script shebang cannot select the build machine's Python.
129
146
  *
130
147
  * The entry point sits at the package root rather than inside the module:
131
148
  * AgentCore runs it as a file path, and Python gives a script run that way no
@@ -136,6 +153,10 @@ import { agentCoreRuntime, TS_VERSIONS } from "./versions.js";
136
153
  */ export const addPythonCodePackageTarget = (tree, options, declaration)=>{
137
154
  const { project, targetName, bundleTargetName, bundleOutputDir, packageOutputDir, sourceRoot, moduleName, entryPointPath, entryPointFileName } = options;
138
155
  const fs = new FsCommands(tree, forDependencies(declaration));
156
+ const launcherPath = joinPathFragments(dirname(entryPointPath), PYTHON_AGENT_CORE_LAUNCHER);
157
+ if (!tree.exists(launcherPath)) {
158
+ tree.write(launcherPath, pythonAgentCoreLauncher(entryPointFileName));
159
+ }
139
160
  project.targets ??= {};
140
161
  project.targets[targetName] = normalizeTargetKeyOrder({
141
162
  cache: true,
@@ -153,7 +174,8 @@ import { agentCoreRuntime, TS_VERSIONS } from "./versions.js";
153
174
  fs.mkdir(packageOutputDir),
154
175
  fs.cpDir(bundleOutputDir, packageOutputDir),
155
176
  fs.cpDir(sourceRoot, joinPathFragments(packageOutputDir, moduleName)),
156
- fs.cpFile(entryPointPath, joinPathFragments(packageOutputDir, entryPointFileName))
177
+ fs.cpFile(entryPointPath, joinPathFragments(packageOutputDir, entryPointFileName)),
178
+ fs.cpFile(launcherPath, joinPathFragments(packageOutputDir, PYTHON_AGENT_CORE_LAUNCHER))
157
179
  ],
158
180
  parallel: false
159
181
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/agent-core-packaging.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n joinPathFragments,\n type ProjectConfiguration,\n type Tree,\n} from '@nx/devkit';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from './declared-dependencies.js';\nimport { FS_DEPENDENCIES, FsCommands } from './fs.js';\nimport {\n addArtifactDependencyToTargets,\n normalizeTargetKeyOrder,\n} from './nx.js';\nimport {\n agentCoreRuntime,\n type ITsDepVersion,\n TS_VERSIONS,\n} from './versions.js';\n\n/**\n * How an AgentCore Runtime's artifact is packaged and hosted.\n *\n * `agentcore` uploads a `.zip` of the built code to S3 and runs it on an\n * AgentCore managed language runtime, which skips the container build, ECR\n * repository and image push entirely — the fastest build and deploy cycle.\n * `agentcore-ecr` builds an arm64 container image and hosts it from ECR, for\n * workloads needing OS-level control (e.g. native system libraries) or an\n * established container pipeline.\n */\nexport const AGENT_CORE_INFRA = ['agentcore', 'agentcore-ecr', 'none'] as const;\n\nexport type AgentCoreInfra = (typeof AGENT_CORE_INFRA)[number];\n\n/** Whether the given infra option hosts on AgentCore Runtime at all. */\nexport const isAgentCoreHosted = (infra: AgentCoreInfra): boolean =>\n infra === 'agentcore' || infra === 'agentcore-ecr';\n\n/** Whether the given infra option builds and hosts a container image. */\nexport const isContainerHosted = (infra: AgentCoreInfra): boolean =>\n infra === 'agentcore-ecr';\n\n/** The AgentCore managed runtime a TypeScript component targets. */\nexport const agentCoreNodeRuntime = (): string => agentCoreRuntime('node');\n\n/** The AgentCore managed runtime a Python component targets. */\nexport const agentCorePythonRuntime = (): string => agentCoreRuntime('python');\n\n/**\n * Dependencies a caller must declare to add a code (`.zip`) packaging target.\n *\n * The TypeScript package target vendors the AWS Distro for OpenTelemetry into\n * the package directory, so its version is declared here (spread through\n * `ownedElsewhere` by callers, since the install targets the built package\n * rather than any workspace manifest).\n */\nexport const CODE_PACKAGE_DEPENDENCIES = [\n ...FS_DEPENDENCIES,\n { name: '@aws/aws-distro-opentelemetry-node-autoinstrumentation' },\n] as const satisfies readonly { name: ITsDepVersion }[];\n\nexport interface AddTypeScriptCodePackageTargetOptions {\n /** Project configuration to add the target to (mutated in place). */\n readonly project: ProjectConfiguration;\n /** Name of the packaging target to add, e.g. `agent-package`. */\n readonly targetName: string;\n /** Name of the target producing the bundled `index.js`, depended on here. */\n readonly bundleTargetName: string;\n /** Directory holding the bundled `index.js`, relative to the workspace root. */\n readonly bundleOutputDir: string;\n /** Directory to assemble the deployable package in, relative to the workspace root. */\n readonly packageOutputDir: string;\n}\n\n/**\n * Name of the target that installs ADOT for the project's code packages. Every\n * code package in a project vendors the same thing, so they share one.\n */\nexport const ADOT_VENDOR_TARGET_NAME = 'agent-core-vendor';\n\n/**\n * Directory the vendor target installs into, relative to the workspace root.\n *\n * A sibling of the `package` directory rather than a path inside it: Nx replaces\n * a cached target's whole declared output directory on restore, so an output\n * nested inside another target's output would have each wipe the other's work on\n * a cache hit.\n */\nexport const adotVendorDir = (projectRoot: string): string =>\n joinPathFragments('dist', projectRoot, 'agent-core-vendor');\n\n/**\n * Add a target assembling the deployable code package for a TypeScript\n * AgentCore Runtime.\n *\n * The package is the rolldown bundle plus a vendored AWS Distro for\n * OpenTelemetry install. AgentCore rejects a code package with no OpenTelemetry\n * dependencies present (`CREATE_FAILED`: \"OpenTelemetry instrumentation\n * executable not found\"), so ADOT must ship inside the package rather than\n * being installed at runtime — the `opentelemetry-instrument` entry point\n * prefix resolves it from there.\n *\n * The install is scoped to its own directory with `--prefix` and `--no-save`, so\n * it never touches the project's own manifest. `--omit=dev` keeps the package to\n * what the runtime loads. ADOT is pure JavaScript with no native binaries, so the\n * package is architecture independent even though AgentCore only runs arm64.\n *\n * Vendoring is a separate target so Nx caches it independently of the source. It\n * depends on nothing but the pinned ADOT version, which the install command\n * carries and Nx hashes as part of the target's configuration, so it declares no\n * `inputs`: editing an agent replays a directory copy rather than re-running the\n * install, while bumping the version still invalidates it.\n */\nexport const addTypeScriptCodePackageTarget = <\n const D extends DependencyDeclaration,\n>(\n tree: Tree,\n options: AddTypeScriptCodePackageTargetOptions,\n declaration: D & MustDeclare<typeof CODE_PACKAGE_DEPENDENCIES, D>,\n): void => {\n const {\n project,\n targetName,\n bundleTargetName,\n bundleOutputDir,\n packageOutputDir,\n } = options;\n\n const fs = new FsCommands(\n tree,\n forDependencies<typeof FS_DEPENDENCIES>(declaration),\n );\n const adotVersion =\n TS_VERSIONS['@aws/aws-distro-opentelemetry-node-autoinstrumentation'];\n const vendorDir = adotVendorDir(project.root);\n\n project.targets ??= {};\n\n // Shared by every code package in the project, so only added once.\n project.targets[ADOT_VENDOR_TARGET_NAME] ??= {\n cache: true,\n inputs: [],\n outputs: [`{workspaceRoot}/${vendorDir}`],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(vendorDir),\n fs.mkdir(vendorDir),\n `npm install --prefix ${vendorDir} --no-save --no-audit --no-fund --omit=dev @aws/aws-distro-opentelemetry-node-autoinstrumentation@${adotVersion}`,\n ],\n parallel: false,\n },\n };\n\n project.targets[targetName] = normalizeTargetKeyOrder({\n cache: true,\n inputs: ['default'],\n outputs: [`{workspaceRoot}/${packageOutputDir}`],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(packageOutputDir),\n fs.mkdir(packageOutputDir),\n fs.cpFile(\n joinPathFragments(bundleOutputDir, 'index.js'),\n joinPathFragments(packageOutputDir, 'index.js'),\n ),\n fs.cpDir(\n joinPathFragments(vendorDir, 'node_modules'),\n joinPathFragments(packageOutputDir, 'node_modules'),\n ),\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName, ADOT_VENDOR_TARGET_NAME],\n });\n\n addArtifactDependencyToTargets(project, targetName);\n};\n\nexport interface AddPythonCodePackageTargetOptions {\n /** Project configuration to add the target to (mutated in place). */\n readonly project: ProjectConfiguration;\n /** Name of the packaging target to add, e.g. `agent-package`. */\n readonly targetName: string;\n /** Name of the arm64 bundle target, depended on here. */\n readonly bundleTargetName: string;\n /** Directory holding the arm64 bundle, relative to the workspace root. */\n readonly bundleOutputDir: string;\n /** Directory to assemble the deployable package in, relative to the workspace root. */\n readonly packageOutputDir: string;\n /**\n * The project's source root, which is itself the module directory — copied\n * into the package under {@link moduleName} so the agent's imports resolve.\n */\n readonly sourceRoot: string;\n /** Python module name (the source root's last segment). */\n readonly moduleName: string;\n /**\n * Path to the entry point script, relative to the workspace root. Copied to\n * the package root, where AgentCore's `entryPoint` runs it.\n */\n readonly entryPointPath: string;\n /** File name the entry point takes at the package root. */\n readonly entryPointFileName: string;\n}\n\n/**\n * Add a target assembling the deployable code package for a Python AgentCore\n * Runtime.\n *\n * The package is the arm64 dependency bundle (which already carries\n * `bin/opentelemetry-instrument` from `aws-opentelemetry-distro`, satisfying\n * AgentCore's requirement that OpenTelemetry be present), the project's own\n * module tree, and a root entry point script.\n *\n * The entry point sits at the package root rather than inside the module:\n * AgentCore runs it as a file path, and Python gives a script run that way no\n * parent package, so the agent's own `from .init import app` would raise\n * `ImportError: attempted relative import with no known parent package`. The\n * root script imports the module absolutely instead, which resolves those\n * relative imports normally.\n */\nexport const addPythonCodePackageTarget = <\n const D extends DependencyDeclaration,\n>(\n tree: Tree,\n options: AddPythonCodePackageTargetOptions,\n declaration: D & MustDeclare<typeof FS_DEPENDENCIES, D>,\n): void => {\n const {\n project,\n targetName,\n bundleTargetName,\n bundleOutputDir,\n packageOutputDir,\n sourceRoot,\n moduleName,\n entryPointPath,\n entryPointFileName,\n } = options;\n\n const fs = new FsCommands(\n tree,\n forDependencies<typeof FS_DEPENDENCIES>(declaration),\n );\n\n project.targets ??= {};\n project.targets[targetName] = normalizeTargetKeyOrder({\n cache: true,\n inputs: ['production', '^production'],\n outputs: [`{workspaceRoot}/${packageOutputDir}`],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(packageOutputDir),\n fs.mkdir(packageOutputDir),\n fs.cpDir(bundleOutputDir, packageOutputDir),\n fs.cpDir(sourceRoot, joinPathFragments(packageOutputDir, moduleName)),\n fs.cpFile(\n entryPointPath,\n joinPathFragments(packageOutputDir, entryPointFileName),\n ),\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName],\n });\n\n addArtifactDependencyToTargets(project, targetName);\n};\n"],"names":["joinPathFragments","forDependencies","FS_DEPENDENCIES","FsCommands","addArtifactDependencyToTargets","normalizeTargetKeyOrder","agentCoreRuntime","TS_VERSIONS","AGENT_CORE_INFRA","isAgentCoreHosted","infra","isContainerHosted","agentCoreNodeRuntime","agentCorePythonRuntime","CODE_PACKAGE_DEPENDENCIES","name","ADOT_VENDOR_TARGET_NAME","adotVendorDir","projectRoot","addTypeScriptCodePackageTarget","tree","options","declaration","project","targetName","bundleTargetName","bundleOutputDir","packageOutputDir","fs","adotVersion","vendorDir","root","targets","cache","inputs","outputs","executor","commands","rm","mkdir","parallel","cpFile","cpDir","dependsOn","addPythonCodePackageTarget","sourceRoot","moduleName","entryPointPath","entryPointFileName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/agent-core-packaging.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { dirname } from 'node:path';\nimport {\n joinPathFragments,\n type ProjectConfiguration,\n type Tree,\n} from '@nx/devkit';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from './declared-dependencies.js';\nimport { FS_DEPENDENCIES, FsCommands } from './fs.js';\nimport {\n addArtifactDependencyToTargets,\n normalizeTargetKeyOrder,\n} from './nx.js';\nimport {\n agentCoreRuntime,\n type ITsDepVersion,\n TS_VERSIONS,\n} from './versions.js';\n\n/**\n * How an AgentCore Runtime's artifact is packaged and hosted.\n *\n * `agentcore` uploads a `.zip` of the built code to S3 and runs it on an\n * AgentCore managed language runtime, which skips the container build, ECR\n * repository and image push entirely — the fastest build and deploy cycle.\n * `agentcore-ecr` builds an arm64 container image and hosts it from ECR, for\n * workloads needing OS-level control (e.g. native system libraries) or an\n * established container pipeline.\n */\nexport const AGENT_CORE_INFRA = ['agentcore', 'agentcore-ecr', 'none'] as const;\n\nexport type AgentCoreInfra = (typeof AGENT_CORE_INFRA)[number];\n\n/** Whether the given infra option hosts on AgentCore Runtime at all. */\nexport const isAgentCoreHosted = (infra: AgentCoreInfra): boolean =>\n infra === 'agentcore' || infra === 'agentcore-ecr';\n\n/** Whether the given infra option builds and hosts a container image. */\nexport const isContainerHosted = (infra: AgentCoreInfra): boolean =>\n infra === 'agentcore-ecr';\n\n/** The AgentCore managed runtime a TypeScript component targets. */\nexport const agentCoreNodeRuntime = (): string => agentCoreRuntime('node');\n\n/** The AgentCore managed runtime a Python component targets. */\nexport const agentCorePythonRuntime = (): string => agentCoreRuntime('python');\n\nexport const PYTHON_AGENT_CORE_LAUNCHER = 'agentcore_launcher.py';\n\n/** Run instrumentation with the managed interpreter, independent of console-script shebangs. */\nexport const pythonAgentCoreLauncher = (\n entryPointFileName: string,\n): string => `\\\nimport sys\nfrom pathlib import Path\n\nfrom opentelemetry.instrumentation.auto_instrumentation import run\n\nif __name__ == \"__main__\":\n sys.argv = [\n \"opentelemetry-instrument\",\n sys.executable,\n str(Path(__file__).with_name(${JSON.stringify(entryPointFileName)})),\n *sys.argv[1:],\n ]\n run()\n`;\n\n/**\n * Dependencies a caller must declare to add a code (`.zip`) packaging target.\n *\n * The TypeScript package target vendors the AWS Distro for OpenTelemetry into\n * the package directory, so its version is declared here (spread through\n * `ownedElsewhere` by callers, since the install targets the built package\n * rather than any workspace manifest).\n */\nexport const CODE_PACKAGE_DEPENDENCIES = [\n ...FS_DEPENDENCIES,\n { name: '@aws/aws-distro-opentelemetry-node-autoinstrumentation' },\n] as const satisfies readonly { name: ITsDepVersion }[];\n\nexport interface AddTypeScriptCodePackageTargetOptions {\n /** Project configuration to add the target to (mutated in place). */\n readonly project: ProjectConfiguration;\n /** Name of the packaging target to add, e.g. `agent-package`. */\n readonly targetName: string;\n /** Name of the target producing the bundled `index.js`, depended on here. */\n readonly bundleTargetName: string;\n /** Directory holding the bundled `index.js`, relative to the workspace root. */\n readonly bundleOutputDir: string;\n /** Directory to assemble the deployable package in, relative to the workspace root. */\n readonly packageOutputDir: string;\n}\n\n/**\n * Name of the target that installs ADOT for the project's code packages. Every\n * code package in a project vendors the same thing, so they share one.\n */\nexport const ADOT_VENDOR_TARGET_NAME = 'agent-core-vendor';\n\n/**\n * Directory the vendor target installs into, relative to the workspace root.\n *\n * A sibling of the `package` directory rather than a path inside it: Nx replaces\n * a cached target's whole declared output directory on restore, so an output\n * nested inside another target's output would have each wipe the other's work on\n * a cache hit.\n */\nexport const adotVendorDir = (projectRoot: string): string =>\n joinPathFragments('dist', projectRoot, 'agent-core-vendor');\n\n/**\n * Add a target assembling the deployable code package for a TypeScript\n * AgentCore Runtime.\n *\n * The package is the rolldown bundle plus a vendored AWS Distro for\n * OpenTelemetry install. AgentCore rejects a code package with no OpenTelemetry\n * dependencies present (`CREATE_FAILED`: \"OpenTelemetry instrumentation\n * executable not found\"), so ADOT must ship inside the package rather than\n * being installed at runtime — the `opentelemetry-instrument` entry point\n * prefix resolves it from there.\n *\n * The install is scoped to its own directory with `--prefix` and `--no-save`, so\n * it never touches the project's own manifest. `--omit=dev` keeps the package to\n * what the runtime loads. ADOT is pure JavaScript with no native binaries, so the\n * package is architecture independent even though AgentCore only runs arm64.\n *\n * Vendoring is a separate target so Nx caches it independently of the source. It\n * depends on nothing but the pinned ADOT version, which the install command\n * carries and Nx hashes as part of the target's configuration, so it declares no\n * `inputs`: editing an agent replays a directory copy rather than re-running the\n * install, while bumping the version still invalidates it.\n */\nexport const addTypeScriptCodePackageTarget = <\n const D extends DependencyDeclaration,\n>(\n tree: Tree,\n options: AddTypeScriptCodePackageTargetOptions,\n declaration: D & MustDeclare<typeof CODE_PACKAGE_DEPENDENCIES, D>,\n): void => {\n const {\n project,\n targetName,\n bundleTargetName,\n bundleOutputDir,\n packageOutputDir,\n } = options;\n\n const fs = new FsCommands(\n tree,\n forDependencies<typeof FS_DEPENDENCIES>(declaration),\n );\n const adotVersion =\n TS_VERSIONS['@aws/aws-distro-opentelemetry-node-autoinstrumentation'];\n const vendorDir = adotVendorDir(project.root);\n\n project.targets ??= {};\n\n // Shared by every code package in the project, so only added once.\n project.targets[ADOT_VENDOR_TARGET_NAME] ??= {\n cache: true,\n inputs: [],\n outputs: [`{workspaceRoot}/${vendorDir}`],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(vendorDir),\n fs.mkdir(vendorDir),\n `npm install --prefix ${vendorDir} --no-save --no-audit --no-fund --omit=dev @aws/aws-distro-opentelemetry-node-autoinstrumentation@${adotVersion}`,\n ],\n parallel: false,\n },\n };\n\n project.targets[targetName] = normalizeTargetKeyOrder({\n cache: true,\n inputs: ['default'],\n outputs: [`{workspaceRoot}/${packageOutputDir}`],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(packageOutputDir),\n fs.mkdir(packageOutputDir),\n fs.cpFile(\n joinPathFragments(bundleOutputDir, 'index.js'),\n joinPathFragments(packageOutputDir, 'index.js'),\n ),\n fs.cpDir(\n joinPathFragments(vendorDir, 'node_modules'),\n joinPathFragments(packageOutputDir, 'node_modules'),\n ),\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName, ADOT_VENDOR_TARGET_NAME],\n });\n\n addArtifactDependencyToTargets(project, targetName);\n};\n\nexport interface AddPythonCodePackageTargetOptions {\n /** Project configuration to add the target to (mutated in place). */\n readonly project: ProjectConfiguration;\n /** Name of the packaging target to add, e.g. `agent-package`. */\n readonly targetName: string;\n /** Name of the arm64 bundle target, depended on here. */\n readonly bundleTargetName: string;\n /** Directory holding the arm64 bundle, relative to the workspace root. */\n readonly bundleOutputDir: string;\n /** Directory to assemble the deployable package in, relative to the workspace root. */\n readonly packageOutputDir: string;\n /**\n * The project's source root, which is itself the module directory — copied\n * into the package under {@link moduleName} so the agent's imports resolve.\n */\n readonly sourceRoot: string;\n /** Python module name (the source root's last segment). */\n readonly moduleName: string;\n /**\n * Path to the entry point script, relative to the workspace root. Copied to\n * the package root, where AgentCore's `entryPoint` runs it.\n */\n readonly entryPointPath: string;\n /** File name the entry point takes at the package root. */\n readonly entryPointFileName: string;\n}\n\n/**\n * Add a target assembling the deployable code package for a Python AgentCore\n * Runtime.\n *\n * The package contains the arm64 dependency bundle with `aws-opentelemetry-distro`,\n * the project's module tree, its root entry point and an instrumentation launcher.\n * The launcher calls OpenTelemetry's `run()` with `sys.executable` and the original\n * entry point, so a console-script shebang cannot select the build machine's Python.\n *\n * The entry point sits at the package root rather than inside the module:\n * AgentCore runs it as a file path, and Python gives a script run that way no\n * parent package, so the agent's own `from .init import app` would raise\n * `ImportError: attempted relative import with no known parent package`. The\n * root script imports the module absolutely instead, which resolves those\n * relative imports normally.\n */\nexport const addPythonCodePackageTarget = <\n const D extends DependencyDeclaration,\n>(\n tree: Tree,\n options: AddPythonCodePackageTargetOptions,\n declaration: D & MustDeclare<typeof FS_DEPENDENCIES, D>,\n): void => {\n const {\n project,\n targetName,\n bundleTargetName,\n bundleOutputDir,\n packageOutputDir,\n sourceRoot,\n moduleName,\n entryPointPath,\n entryPointFileName,\n } = options;\n\n const fs = new FsCommands(\n tree,\n forDependencies<typeof FS_DEPENDENCIES>(declaration),\n );\n\n const launcherPath = joinPathFragments(\n dirname(entryPointPath),\n PYTHON_AGENT_CORE_LAUNCHER,\n );\n if (!tree.exists(launcherPath)) {\n tree.write(launcherPath, pythonAgentCoreLauncher(entryPointFileName));\n }\n\n project.targets ??= {};\n project.targets[targetName] = normalizeTargetKeyOrder({\n cache: true,\n inputs: ['production', '^production'],\n outputs: [`{workspaceRoot}/${packageOutputDir}`],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(packageOutputDir),\n fs.mkdir(packageOutputDir),\n fs.cpDir(bundleOutputDir, packageOutputDir),\n fs.cpDir(sourceRoot, joinPathFragments(packageOutputDir, moduleName)),\n fs.cpFile(\n entryPointPath,\n joinPathFragments(packageOutputDir, entryPointFileName),\n ),\n fs.cpFile(\n launcherPath,\n joinPathFragments(packageOutputDir, PYTHON_AGENT_CORE_LAUNCHER),\n ),\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName],\n });\n\n addArtifactDependencyToTargets(project, targetName);\n};\n"],"names":["dirname","joinPathFragments","forDependencies","FS_DEPENDENCIES","FsCommands","addArtifactDependencyToTargets","normalizeTargetKeyOrder","agentCoreRuntime","TS_VERSIONS","AGENT_CORE_INFRA","isAgentCoreHosted","infra","isContainerHosted","agentCoreNodeRuntime","agentCorePythonRuntime","PYTHON_AGENT_CORE_LAUNCHER","pythonAgentCoreLauncher","entryPointFileName","JSON","stringify","CODE_PACKAGE_DEPENDENCIES","name","ADOT_VENDOR_TARGET_NAME","adotVendorDir","projectRoot","addTypeScriptCodePackageTarget","tree","options","declaration","project","targetName","bundleTargetName","bundleOutputDir","packageOutputDir","fs","adotVersion","vendorDir","root","targets","cache","inputs","outputs","executor","commands","rm","mkdir","parallel","cpFile","cpDir","dependsOn","addPythonCodePackageTarget","sourceRoot","moduleName","entryPointPath","launcherPath","exists","write"],"mappings":"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"}
@@ -36,6 +36,12 @@ DENIED_TERM = "stocks"
36
36
  BLOCKED_ANSWER = "Sorry, I can't help with that request."
37
37
 
38
38
 
39
+ class FakeAwsServer(ThreadingHTTPServer):
40
+ """Queue concurrent SDK connection bursts while requests are accepted."""
41
+
42
+ request_queue_size = 128
43
+
44
+
39
45
  def _header(name: str, value: str) -> bytes:
40
46
  n, v = name.encode(), value.encode()
41
47
  return struct.pack("B", len(n)) + n + b"\x07" + struct.pack(">H", len(v)) + v
@@ -196,10 +202,10 @@ def _handler(config_file: str, log_file: str) -> type[BaseHTTPRequestHandler]:
196
202
 
197
203
  def start_server(config_file: str, log_file: str, port: int = 0) -> tuple[ThreadingHTTPServer, int]:
198
204
  """Serve on 127.0.0.1 in a daemon thread; port 0 picks a free port."""
199
- server = ThreadingHTTPServer(("127.0.0.1", port), _handler(config_file, log_file))
205
+ server = FakeAwsServer(("127.0.0.1", port), _handler(config_file, log_file))
200
206
  threading.Thread(target=server.serve_forever, daemon=True).start()
201
207
  return server, server.server_address[1]
202
208
 
203
209
 
204
210
  if __name__ == "__main__":
205
- ThreadingHTTPServer(("127.0.0.1", int(sys.argv[2])), _handler(sys.argv[1], sys.argv[3])).serve_forever()
211
+ FakeAwsServer(("127.0.0.1", int(sys.argv[2])), _handler(sys.argv[1], sys.argv[3])).serve_forever()