@aws/nx-plugin 1.0.0-rc.47 → 1.0.0-rc.49
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/LICENSE-THIRD-PARTY +15 -0
- package/generators.json +7 -0
- package/migrations.json +5 -0
- package/package.json +4 -4
- package/src/mcp-server/dev-server.d.ts +1 -0
- package/src/mcp-server/dev-server.js +18 -0
- package/src/mcp-server/dev-server.js.map +1 -0
- package/src/mcp-server/guide-pipeline.js +1 -1
- package/src/mcp-server/guide-pipeline.js.map +1 -1
- package/src/mcp-server/server.js +2 -0
- package/src/mcp-server/server.js.map +1 -1
- package/src/mcp-server/tools/general-guidance.d.ts +1 -1
- package/src/mcp-server/tools/general-guidance.js +1 -0
- package/src/mcp-server/tools/general-guidance.js.map +1 -1
- package/src/mcp-server/tools/upgrade-workspace.d.ts +11 -0
- package/src/mcp-server/tools/upgrade-workspace.js +32 -0
- package/src/mcp-server/tools/upgrade-workspace.js.map +1 -0
- package/src/preset/__snapshots__/generator.spec.ts.snap +6 -0
- package/src/sdk/ts.d.ts +4 -2
- package/src/sdk/ts.js +4 -2
- package/src/sdk/ts.js.map +1 -1
- package/src/ts/agent/__snapshots__/generator.spec.ts.snap +9 -4
- package/src/ts/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +1 -0
- package/src/ts/agent/files/ag-ui/index.ts.template +25 -9
- package/src/ts/agent/files/common/agent.ts.template +2 -1
- package/src/ts/agent/files/deploy/Dockerfile.template +7 -3
- package/src/ts/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +1 -0
- package/src/ts/agent/generator.js +2 -2
- package/src/ts/agent/generator.js.map +1 -1
- package/src/ts/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +1 -0
- package/src/ts/mcp-server/files/Dockerfile.template +7 -3
- package/src/ts/mcp-server/generator.js +2 -2
- package/src/ts/mcp-server/generator.js.map +1 -1
- package/src/ts/nx-migration/files/migration.spec.ts.template +26 -0
- package/src/ts/nx-migration/files/migration.ts.template +55 -0
- package/src/ts/nx-migration/files/prompt.md.template +46 -0
- package/src/ts/nx-migration/generator.d.ts +24 -0
- package/src/ts/nx-migration/generator.js +122 -0
- package/src/ts/nx-migration/generator.js.map +1 -0
- package/src/ts/nx-migration/schema.d.js +6 -0
- package/src/ts/nx-migration/schema.d.js.map +1 -0
- package/src/ts/nx-migration/schema.d.ts +13 -0
- package/src/ts/nx-migration/schema.json +63 -0
- package/src/ts/nx-plugin/utils.d.ts +21 -1
- package/src/ts/nx-plugin/utils.js +46 -35
- package/src/ts/nx-plugin/utils.js.map +1 -1
- package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +11 -3
- package/src/ts/rdb/files/Dockerfile.template +5 -1
- package/src/ts/rdb/files/src/migration-handler.ts.template +3 -1
- package/src/ts/rdb/generator.js +2 -2
- package/src/ts/rdb/generator.js.map +1 -1
- package/src/utils/agent-connection/agent-connection.js +4 -0
- package/src/utils/agent-connection/agent-connection.js.map +1 -1
- package/src/utils/agent-connection/files/core-strands/base/tool-errors-strands.ts.template +22 -0
- package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.tf.template +19 -1
- package/src/utils/commands.d.ts +4 -3
- package/src/utils/commands.js +6 -2
- package/src/utils/commands.js.map +1 -1
- package/src/utils/docker.d.ts +8 -0
- package/src/utils/docker.js +8 -1
- package/src/utils/docker.js.map +1 -1
- package/src/utils/format.js +54 -25
- package/src/utils/format.js.map +1 -1
- package/src/utils/init.js +7 -2
- package/src/utils/init.js.map +1 -1
- package/src/utils/mcp.d.ts +9 -0
- package/src/utils/mcp.js +9 -1
- package/src/utils/mcp.js.map +1 -1
- package/src/utils/migration-versions.d.ts +95 -0
- package/src/utils/migration-versions.js +128 -0
- package/src/utils/migration-versions.js.map +1 -0
- package/src/utils/nx.d.ts +18 -0
- package/src/utils/nx.js +24 -1
- package/src/utils/nx.js.map +1 -1
- package/src/utils/test-git.d.ts +39 -0
- package/src/utils/test-git.js +117 -0
- package/src/utils/test-git.js.map +1 -0
- package/src/utils/versions.d.ts +4 -1
- package/src/utils/versions.js +10 -2
- package/src/utils/versions.js.map +1 -1
- package/src/bin/aws-nx-mcp.d.ts +0 -2
- package/src/bin/aws-nx-mcp.js +0 -14
- package/src/bin/aws-nx-mcp.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Agent, tool } from '@strands-agents/sdk';
|
|
2
|
-
import { logModelErrors } from '<%- agentConnectionImport %>';
|
|
2
|
+
import { logModelErrors, logToolErrors } from '<%- agentConnectionImport %>';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
5
|
const multiply = tool({
|
|
@@ -20,5 +20,6 @@ export const getAgent = async () => {
|
|
|
20
20
|
tools: [multiply],
|
|
21
21
|
});
|
|
22
22
|
logModelErrors(agent);
|
|
23
|
+
logToolErrors(agent);
|
|
23
24
|
return agent;
|
|
24
25
|
};
|
|
@@ -7,11 +7,15 @@ WORKDIR /app
|
|
|
7
7
|
|
|
8
8
|
# Add AWS Distro for OpenTelemetry for observability
|
|
9
9
|
# https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/observability-configure.html
|
|
10
|
-
# The
|
|
11
|
-
#
|
|
10
|
+
# The overrides pin transitive dependencies with known HIGH/CRITICAL
|
|
11
|
+
# vulnerabilities to fixed versions. npm is removed once the install is done —
|
|
12
|
+
# the runtime only needs node, and npm's own bundled dependencies would
|
|
13
|
+
# otherwise carry vulnerabilities into the image.
|
|
12
14
|
RUN npm init -y \
|
|
13
15
|
&& npm pkg set "overrides.@opentelemetry/propagator-jaeger=<%- jaegerVersion %>" \
|
|
14
|
-
&& npm
|
|
16
|
+
&& npm pkg set "overrides.minimatch=<%- minimatchVersion %>" \
|
|
17
|
+
&& npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation@<%- adotVersion %> \
|
|
18
|
+
&& npm uninstall -g npm
|
|
15
19
|
|
|
16
20
|
# Copy bundled agent
|
|
17
21
|
COPY index.js /app
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`ts#agent#gateway-connection generator > should match snapshot for agent-connection src files > agent-connection-index.ts 1`] = `
|
|
4
4
|
"export * from './app/my-gateway-client-strands.js';
|
|
5
|
+
export * from './core/tool-errors-strands.js';
|
|
5
6
|
export * from './core/model-errors-strands.js';
|
|
6
7
|
export * from './core/with-session-id-strands.js';
|
|
7
8
|
export * from './core/session-context.js';
|
|
@@ -8,7 +8,7 @@ import { addAgentInfra } from "../../utils/agent-core-constructs/agent-core-cons
|
|
|
8
8
|
import { addTypeScriptBundleTarget } from "../../utils/bundle/bundle.js";
|
|
9
9
|
import { resolveContainers } from "../../utils/containers.js";
|
|
10
10
|
import { addDependenciesToPackageJson } from "../../utils/dependencies.js";
|
|
11
|
-
import { addDockerScanTarget } from "../../utils/docker.js";
|
|
11
|
+
import { addDockerScanTarget, nodeImageVersions } from "../../utils/docker.js";
|
|
12
12
|
import { formatFilesInSubtree } from "../../utils/format.js";
|
|
13
13
|
import { FsCommands } from "../../utils/fs.js";
|
|
14
14
|
import { resolveIac } from "../../utils/iac.js";
|
|
@@ -81,7 +81,7 @@ export const tsAgentGenerator = async (tree, options)=>{
|
|
|
81
81
|
adotVersion: TS_VERSIONS['@aws/aws-distro-opentelemetry-node-autoinstrumentation'],
|
|
82
82
|
jaegerVersion: TS_VERSIONS['@opentelemetry/propagator-jaeger'],
|
|
83
83
|
nodeBaseImage: BASE_IMAGES.node,
|
|
84
|
-
|
|
84
|
+
...nodeImageVersions(),
|
|
85
85
|
...esmVars(tree)
|
|
86
86
|
}, {
|
|
87
87
|
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/ts/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 { addAgentChatScripts } from '../../utils/agent-chat/agent-chat';\nimport {\n addTypeScriptFrameworkBase,\n ensureTypeScriptAgentConnectionProject,\n} from '../../utils/agent-connection/agent-connection';\nimport { addAgentInfra } from '../../utils/agent-core-constructs/agent-core-constructs';\nimport { addTypeScriptBundleTarget } from '../../utils/bundle/bundle';\nimport { resolveContainers } from '../../utils/containers';\nimport { addDependenciesToPackageJson } from '../../utils/dependencies';\nimport { addDockerScanTarget } from '../../utils/docker';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { FsCommands } from '../../utils/fs';\nimport { resolveIac } from '../../utils/iac';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport { esmVars } from '../../utils/module-format';\nimport { kebabCase, toClassName } from '../../utils/names';\nimport { getNpmScope } from '../../utils/npm-scope';\nimport {\n addComponentDevTarget,\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport { assignPort } from '../../utils/port';\nimport { sharedConstructsGenerator } from '../../utils/shared-constructs';\nimport { BASE_IMAGES, TS_VERSIONS, withVersions } from '../../utils/versions';\nimport type { TsAgentGeneratorSchema } from './schema';\n\nexport const TS_AGENT_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const tsAgentGenerator = async (\n tree: Tree,\n options: TsAgentGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const project = readProjectConfigurationUnqualified(tree, options.project);\n\n if (!tree.exists(joinPathFragments(project.root, 'tsconfig.json'))) {\n throw new Error(\n `Unsupported project ${options.project}. Expected a TypeScript project (with a tsconfig.json)`,\n );\n }\n\n const defaultName = `${kebabCase(project.name.split('/').pop())}-agent`;\n const name = kebabCase(options.name || defaultName);\n const agentNameClassName = toClassName(name);\n const agentTargetPrefix = options.name ? name : 'agent';\n const targetSourceDirRelativeToProjectRoot = joinPathFragments(\n 'src',\n agentTargetPrefix,\n );\n const targetSourceDir = joinPathFragments(\n project.root,\n targetSourceDirRelativeToProjectRoot,\n );\n const relativeSourceDir = targetSourceDir.replace(project.root + '/', './');\n const distDir = joinPathFragments('dist', project.root);\n\n const infra = options.infra ?? 'agentcore';\n const protocol = options.protocol ?? 'http';\n\n if (infra === 'none' && options.auth && options.auth !== 'iam') {\n console.warn(\n 'Warning: auth is ignored when no infrastructure is configured (no infrastructure is generated)',\n );\n }\n\n const auth = options.auth ?? 'iam';\n\n // Ensure the shared agent-connection project exists so the server entry\n // point can import `runWithSessionId` and propagate the AgentCore session\n // ID to any downstream MCP / A2A clients a later connection generator\n // wires into this agent.\n await ensureTypeScriptAgentConnectionProject(tree);\n // The agent server imports the framework base helpers (session cache + model\n // error logging) regardless of whether a connection client is wired in.\n await addTypeScriptFrameworkBase(tree);\n\n const templateContext = {\n name,\n agentNameClassName,\n distDir,\n agentConnectionImport: `@${getNpmScope(tree)}/agent-connection`,\n ...esmVars(tree),\n };\n\n // Generate common files shared by both protocols\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'common'),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // Generate protocol-specific files\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', protocol.toLowerCase()),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n if (infra === 'agentcore') {\n const containers = await resolveContainers(tree, 'inherit');\n const dockerImageTag = `${getNpmScope(tree)}-${name}:latest`;\n\n // Add bundle target\n await addTypeScriptBundleTarget(tree, project, {\n targetFilePath: `${targetSourceDirRelativeToProjectRoot}/index.ts`,\n bundleOutputDir: joinPathFragments('agent', name),\n });\n\n // Add the Dockerfile\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'deploy'),\n targetSourceDir,\n {\n distDir,\n name,\n protocol,\n adotVersion:\n TS_VERSIONS['@aws/aws-distro-opentelemetry-node-autoinstrumentation'],\n jaegerVersion: TS_VERSIONS['@opentelemetry/propagator-jaeger'],\n nodeBaseImage: BASE_IMAGES.node,\n npmVersion: TS_VERSIONS.npm,\n ...esmVars(tree),\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n const dockerOutputDir = joinPathFragments(\n 'dist',\n project.root,\n 'bundle',\n 'agent',\n name,\n );\n const dockerTargetName = `${agentTargetPrefix}-docker`;\n\n const fs = new FsCommands(tree);\n project.targets[dockerTargetName] = {\n cache: true,\n outputs: [`{workspaceRoot}/${dockerOutputDir}/Dockerfile`],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.cp(\n `${targetSourceDir}/Dockerfile`,\n `${dockerOutputDir}/Dockerfile`,\n ),\n `${containers} build --platform linux/arm64 -t ${dockerImageTag} ${dockerOutputDir}`,\n ],\n parallel: false,\n },\n dependsOn: ['bundle'],\n };\n\n addDependencyToTargetIfNotPresent(project, 'docker', dockerTargetName);\n addDependencyToTargetIfNotPresent(project, 'build', 'docker');\n\n addDockerScanTarget(tree, {\n project,\n containerEngine: containers,\n trivyTargetName: `${agentTargetPrefix}-trivy`,\n dockerTargetName,\n imageTags: [dockerImageTag],\n });\n\n // Add shared constructs\n const iac = await resolveIac(tree, options.iac);\n await sharedConstructsGenerator(tree, { iac });\n\n // AG-UI uses HTTP as the AgentCore protocol type (AG-UI is HTTP-based with SSE over POST).\n const infraProtocol: 'http' | 'a2a' =\n protocol === 'ag-ui' ? 'http' : (protocol as 'http' | 'a2a');\n\n await addAgentInfra(tree, {\n agentNameKebabCase: name,\n agentNameClassName,\n projectName: project.name,\n dockerImageTag,\n dockerOutputDir,\n iac,\n auth,\n serverProtocol: infraProtocol,\n containers,\n });\n }\n\n // Add dependencies\n addDependenciesToPackageJson(\n tree,\n withVersions([\n 'zod',\n '@strands-agents/sdk',\n '@aws-sdk/credential-providers',\n '@aws-sdk/client-appconfigdata',\n '@aws-lambda-powertools/parameters',\n '@modelcontextprotocol/sdk',\n ...(protocol === 'a2a'\n ? (['express', '@a2a-js/sdk'] as const)\n : protocol === 'ag-ui'\n ? ([\n '@ag-ui/aws-strands',\n // @ag-ui/aws-strands declares these as peer dependencies but\n // statically imports them, so they must be installed for the\n // bundler to resolve and inline them into the runtime image.\n '@ag-ui/a2ui-toolkit',\n '@ag-ui/client',\n '@ag-ui/core',\n '@ag-ui/encoder',\n 'express',\n 'cors',\n ] as const)\n : ([\n '@trpc/server',\n '@trpc/client',\n 'ws',\n 'cors',\n 'aws4fetch',\n ] as const)),\n ]),\n withVersions([\n '@types/node',\n // The chat CLI runs standalone via tsx and resolves the deployed agent\n // from AppConfig when `RUNTIME_CONFIG_APP_ID` is set.\n 'agent-chat-cli',\n '@aws-lambda-powertools/parameters',\n '@aws-sdk/client-appconfigdata',\n ...(auth === 'iam'\n ? (['aws4fetch', '@aws-sdk/credential-providers'] as const)\n : ([] as const)),\n // A2A chat builds a signed @a2a-js client factory for the deployed agent.\n ...(protocol === 'a2a' ? (['@a2a-js/sdk'] as const) : ([] as const)),\n ...(protocol === 'a2a' || protocol === 'ag-ui'\n ? (['@types/express', '@types/cors'] as const)\n : (['@types/ws', '@types/cors'] as const)),\n ]),\n joinPathFragments(project.root, 'package.json'),\n );\n addDependenciesToPackageJson(tree, {}, withVersions(['tsx']));\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: TS_AGENT_GENERATOR_INFO, name: agentTargetPrefix },\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 const scriptsDir = joinPathFragments(\n project.root,\n 'scripts',\n agentTargetPrefix,\n );\n addAgentChatScripts(tree, {\n scriptsDir,\n protocol,\n language: 'ts',\n agentNameClassName,\n auth,\n relativeAgentImport: `../../${targetSourceDirRelativeToProjectRoot}`,\n });\n\n const chatUrl =\n protocol === 'http'\n ? `ws://localhost:${localDevPort}/ws`\n : protocol === 'ag-ui'\n ? `http://localhost:${localDevPort}/invocations`\n : `http://localhost:${localDevPort}`;\n const chatCommand = `tsx ./scripts/${agentTargetPrefix}/chat.ts`;\n\n const agentTargets = {\n ...project.targets,\n [`${agentTargetPrefix}-serve`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [`tsx --watch ${relativeSourceDir}/index.ts`],\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: [`tsx --watch ${relativeSourceDir}/index.ts`],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n LOCAL_DEV: 'true',\n },\n },\n },\n [`${agentTargetPrefix}-chat`]: {\n executor: 'nx:run-commands',\n options: {\n commands: [chatCommand],\n cwd: '{projectRoot}',\n env: {\n URL: chatUrl,\n },\n },\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 // Sort targets so their order is stable regardless of insertion order on\n // first run vs re-run.\n targets: sortObjectKeys(agentTargets),\n });\n\n addComponentGeneratorMetadata(\n tree,\n project.name,\n TS_AGENT_GENERATOR_INFO,\n targetSourceDirRelativeToProjectRoot,\n agentTargetPrefix,\n { port: localDevPort, rc: agentNameClassName, auth, protocol },\n );\n\n await addGeneratorMetricsIfApplicable(tree, [TS_AGENT_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nexport default tsAgentGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","addAgentChatScripts","addTypeScriptFrameworkBase","ensureTypeScriptAgentConnectionProject","addAgentInfra","addTypeScriptBundleTarget","resolveContainers","addDependenciesToPackageJson","addDockerScanTarget","formatFilesInSubtree","FsCommands","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","esmVars","kebabCase","toClassName","getNpmScope","addComponentDevTarget","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","readProjectConfigurationUnqualified","sortObjectKeys","assignPort","sharedConstructsGenerator","BASE_IMAGES","TS_VERSIONS","withVersions","TS_AGENT_GENERATOR_INFO","filename","tsAgentGenerator","tree","options","project","exists","root","Error","defaultName","name","split","pop","agentNameClassName","agentTargetPrefix","targetSourceDirRelativeToProjectRoot","targetSourceDir","relativeSourceDir","replace","distDir","infra","protocol","auth","console","warn","templateContext","agentConnectionImport","dirname","overwriteStrategy","KeepExisting","toLowerCase","containers","dockerImageTag","targetFilePath","bundleOutputDir","adotVersion","jaegerVersion","nodeBaseImage","node","npmVersion","npm","dockerOutputDir","dockerTargetName","fs","targets","cache","outputs","executor","commands","cp","parallel","dependsOn","containerEngine","trivyTargetName","imageTags","iac","infraProtocol","agentNameKebabCase","projectName","serverProtocol","localDevPortStart","localDevPort","component","info","scriptsDir","language","relativeAgentImport","chatUrl","chatCommand","agentTargets","continuous","cwd","env","PORT","LOCAL_DEV","URL","port","rc","preferInstallDependencies","languages"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/ts/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 { addAgentChatScripts } from '../../utils/agent-chat/agent-chat';\nimport {\n addTypeScriptFrameworkBase,\n ensureTypeScriptAgentConnectionProject,\n} from '../../utils/agent-connection/agent-connection';\nimport { addAgentInfra } from '../../utils/agent-core-constructs/agent-core-constructs';\nimport { addTypeScriptBundleTarget } from '../../utils/bundle/bundle';\nimport { resolveContainers } from '../../utils/containers';\nimport { addDependenciesToPackageJson } from '../../utils/dependencies';\nimport { addDockerScanTarget, nodeImageVersions } from '../../utils/docker';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { FsCommands } from '../../utils/fs';\nimport { resolveIac } from '../../utils/iac';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport { esmVars } from '../../utils/module-format';\nimport { kebabCase, toClassName } from '../../utils/names';\nimport { getNpmScope } from '../../utils/npm-scope';\nimport {\n addComponentDevTarget,\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport { assignPort } from '../../utils/port';\nimport { sharedConstructsGenerator } from '../../utils/shared-constructs';\nimport { BASE_IMAGES, TS_VERSIONS, withVersions } from '../../utils/versions';\nimport type { TsAgentGeneratorSchema } from './schema';\n\nexport const TS_AGENT_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const tsAgentGenerator = async (\n tree: Tree,\n options: TsAgentGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const project = readProjectConfigurationUnqualified(tree, options.project);\n\n if (!tree.exists(joinPathFragments(project.root, 'tsconfig.json'))) {\n throw new Error(\n `Unsupported project ${options.project}. Expected a TypeScript project (with a tsconfig.json)`,\n );\n }\n\n const defaultName = `${kebabCase(project.name.split('/').pop())}-agent`;\n const name = kebabCase(options.name || defaultName);\n const agentNameClassName = toClassName(name);\n const agentTargetPrefix = options.name ? name : 'agent';\n const targetSourceDirRelativeToProjectRoot = joinPathFragments(\n 'src',\n agentTargetPrefix,\n );\n const targetSourceDir = joinPathFragments(\n project.root,\n targetSourceDirRelativeToProjectRoot,\n );\n const relativeSourceDir = targetSourceDir.replace(project.root + '/', './');\n const distDir = joinPathFragments('dist', project.root);\n\n const infra = options.infra ?? 'agentcore';\n const protocol = options.protocol ?? 'http';\n\n if (infra === 'none' && options.auth && options.auth !== 'iam') {\n console.warn(\n 'Warning: auth is ignored when no infrastructure is configured (no infrastructure is generated)',\n );\n }\n\n const auth = options.auth ?? 'iam';\n\n // Ensure the shared agent-connection project exists so the server entry\n // point can import `runWithSessionId` and propagate the AgentCore session\n // ID to any downstream MCP / A2A clients a later connection generator\n // wires into this agent.\n await ensureTypeScriptAgentConnectionProject(tree);\n // The agent server imports the framework base helpers (session cache + model\n // error logging) regardless of whether a connection client is wired in.\n await addTypeScriptFrameworkBase(tree);\n\n const templateContext = {\n name,\n agentNameClassName,\n distDir,\n agentConnectionImport: `@${getNpmScope(tree)}/agent-connection`,\n ...esmVars(tree),\n };\n\n // Generate common files shared by both protocols\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'common'),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // Generate protocol-specific files\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', protocol.toLowerCase()),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n if (infra === 'agentcore') {\n const containers = await resolveContainers(tree, 'inherit');\n const dockerImageTag = `${getNpmScope(tree)}-${name}:latest`;\n\n // Add bundle target\n await addTypeScriptBundleTarget(tree, project, {\n targetFilePath: `${targetSourceDirRelativeToProjectRoot}/index.ts`,\n bundleOutputDir: joinPathFragments('agent', name),\n });\n\n // Add the Dockerfile\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'deploy'),\n targetSourceDir,\n {\n distDir,\n name,\n protocol,\n adotVersion:\n TS_VERSIONS['@aws/aws-distro-opentelemetry-node-autoinstrumentation'],\n jaegerVersion: TS_VERSIONS['@opentelemetry/propagator-jaeger'],\n nodeBaseImage: BASE_IMAGES.node,\n ...nodeImageVersions(),\n ...esmVars(tree),\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n const dockerOutputDir = joinPathFragments(\n 'dist',\n project.root,\n 'bundle',\n 'agent',\n name,\n );\n const dockerTargetName = `${agentTargetPrefix}-docker`;\n\n const fs = new FsCommands(tree);\n project.targets[dockerTargetName] = {\n cache: true,\n outputs: [`{workspaceRoot}/${dockerOutputDir}/Dockerfile`],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.cp(\n `${targetSourceDir}/Dockerfile`,\n `${dockerOutputDir}/Dockerfile`,\n ),\n `${containers} build --platform linux/arm64 -t ${dockerImageTag} ${dockerOutputDir}`,\n ],\n parallel: false,\n },\n dependsOn: ['bundle'],\n };\n\n addDependencyToTargetIfNotPresent(project, 'docker', dockerTargetName);\n addDependencyToTargetIfNotPresent(project, 'build', 'docker');\n\n addDockerScanTarget(tree, {\n project,\n containerEngine: containers,\n trivyTargetName: `${agentTargetPrefix}-trivy`,\n dockerTargetName,\n imageTags: [dockerImageTag],\n });\n\n // Add shared constructs\n const iac = await resolveIac(tree, options.iac);\n await sharedConstructsGenerator(tree, { iac });\n\n // AG-UI uses HTTP as the AgentCore protocol type (AG-UI is HTTP-based with SSE over POST).\n const infraProtocol: 'http' | 'a2a' =\n protocol === 'ag-ui' ? 'http' : (protocol as 'http' | 'a2a');\n\n await addAgentInfra(tree, {\n agentNameKebabCase: name,\n agentNameClassName,\n projectName: project.name,\n dockerImageTag,\n dockerOutputDir,\n iac,\n auth,\n serverProtocol: infraProtocol,\n containers,\n });\n }\n\n // Add dependencies\n addDependenciesToPackageJson(\n tree,\n withVersions([\n 'zod',\n '@strands-agents/sdk',\n '@aws-sdk/credential-providers',\n '@aws-sdk/client-appconfigdata',\n '@aws-lambda-powertools/parameters',\n '@modelcontextprotocol/sdk',\n ...(protocol === 'a2a'\n ? (['express', '@a2a-js/sdk'] as const)\n : protocol === 'ag-ui'\n ? ([\n '@ag-ui/aws-strands',\n // @ag-ui/aws-strands declares these as peer dependencies but\n // statically imports them, so they must be installed for the\n // bundler to resolve and inline them into the runtime image.\n '@ag-ui/a2ui-toolkit',\n '@ag-ui/client',\n '@ag-ui/core',\n '@ag-ui/encoder',\n 'express',\n 'cors',\n ] as const)\n : ([\n '@trpc/server',\n '@trpc/client',\n 'ws',\n 'cors',\n 'aws4fetch',\n ] as const)),\n ]),\n withVersions([\n '@types/node',\n // The chat CLI runs standalone via tsx and resolves the deployed agent\n // from AppConfig when `RUNTIME_CONFIG_APP_ID` is set.\n 'agent-chat-cli',\n '@aws-lambda-powertools/parameters',\n '@aws-sdk/client-appconfigdata',\n ...(auth === 'iam'\n ? (['aws4fetch', '@aws-sdk/credential-providers'] as const)\n : ([] as const)),\n // A2A chat builds a signed @a2a-js client factory for the deployed agent.\n ...(protocol === 'a2a' ? (['@a2a-js/sdk'] as const) : ([] as const)),\n ...(protocol === 'a2a' || protocol === 'ag-ui'\n ? (['@types/express', '@types/cors'] as const)\n : (['@types/ws', '@types/cors'] as const)),\n ]),\n joinPathFragments(project.root, 'package.json'),\n );\n addDependenciesToPackageJson(tree, {}, withVersions(['tsx']));\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: TS_AGENT_GENERATOR_INFO, name: agentTargetPrefix },\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 const scriptsDir = joinPathFragments(\n project.root,\n 'scripts',\n agentTargetPrefix,\n );\n addAgentChatScripts(tree, {\n scriptsDir,\n protocol,\n language: 'ts',\n agentNameClassName,\n auth,\n relativeAgentImport: `../../${targetSourceDirRelativeToProjectRoot}`,\n });\n\n const chatUrl =\n protocol === 'http'\n ? `ws://localhost:${localDevPort}/ws`\n : protocol === 'ag-ui'\n ? `http://localhost:${localDevPort}/invocations`\n : `http://localhost:${localDevPort}`;\n const chatCommand = `tsx ./scripts/${agentTargetPrefix}/chat.ts`;\n\n const agentTargets = {\n ...project.targets,\n [`${agentTargetPrefix}-serve`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [`tsx --watch ${relativeSourceDir}/index.ts`],\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: [`tsx --watch ${relativeSourceDir}/index.ts`],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n LOCAL_DEV: 'true',\n },\n },\n },\n [`${agentTargetPrefix}-chat`]: {\n executor: 'nx:run-commands',\n options: {\n commands: [chatCommand],\n cwd: '{projectRoot}',\n env: {\n URL: chatUrl,\n },\n },\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 // Sort targets so their order is stable regardless of insertion order on\n // first run vs re-run.\n targets: sortObjectKeys(agentTargets),\n });\n\n addComponentGeneratorMetadata(\n tree,\n project.name,\n TS_AGENT_GENERATOR_INFO,\n targetSourceDirRelativeToProjectRoot,\n agentTargetPrefix,\n { port: localDevPort, rc: agentNameClassName, auth, protocol },\n );\n\n await addGeneratorMetricsIfApplicable(tree, [TS_AGENT_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nexport default tsAgentGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","addAgentChatScripts","addTypeScriptFrameworkBase","ensureTypeScriptAgentConnectionProject","addAgentInfra","addTypeScriptBundleTarget","resolveContainers","addDependenciesToPackageJson","addDockerScanTarget","nodeImageVersions","formatFilesInSubtree","FsCommands","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","esmVars","kebabCase","toClassName","getNpmScope","addComponentDevTarget","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","readProjectConfigurationUnqualified","sortObjectKeys","assignPort","sharedConstructsGenerator","BASE_IMAGES","TS_VERSIONS","withVersions","TS_AGENT_GENERATOR_INFO","filename","tsAgentGenerator","tree","options","project","exists","root","Error","defaultName","name","split","pop","agentNameClassName","agentTargetPrefix","targetSourceDirRelativeToProjectRoot","targetSourceDir","relativeSourceDir","replace","distDir","infra","protocol","auth","console","warn","templateContext","agentConnectionImport","dirname","overwriteStrategy","KeepExisting","toLowerCase","containers","dockerImageTag","targetFilePath","bundleOutputDir","adotVersion","jaegerVersion","nodeBaseImage","node","dockerOutputDir","dockerTargetName","fs","targets","cache","outputs","executor","commands","cp","parallel","dependsOn","containerEngine","trivyTargetName","imageTags","iac","infraProtocol","agentNameKebabCase","projectName","serverProtocol","localDevPortStart","localDevPort","component","info","scriptsDir","language","relativeAgentImport","chatUrl","chatCommand","agentTargets","continuous","cwd","env","PORT","LOCAL_DEV","URL","port","rc","preferInstallDependencies","languages"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`ts#agent#mcp-connection generator > should match snapshot for agent-connection src files > agent-connection-index.ts 1`] = `
|
|
4
4
|
"export * from './app/inventory-mcp-client-strands.js';
|
|
5
|
+
export * from './core/tool-errors-strands.js';
|
|
5
6
|
export * from './core/model-errors-strands.js';
|
|
6
7
|
export * from './core/with-session-id-strands.js';
|
|
7
8
|
export * from './core/session-context.js';
|
|
@@ -7,11 +7,15 @@ WORKDIR /app
|
|
|
7
7
|
|
|
8
8
|
# Add AWS Distro for OpenTelemetry for observability
|
|
9
9
|
# https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/observability-configure.html
|
|
10
|
-
# The
|
|
11
|
-
#
|
|
10
|
+
# The overrides pin transitive dependencies with known HIGH/CRITICAL
|
|
11
|
+
# vulnerabilities to fixed versions. npm is removed once the install is done —
|
|
12
|
+
# the runtime only needs node, and npm's own bundled dependencies would
|
|
13
|
+
# otherwise carry vulnerabilities into the image.
|
|
12
14
|
RUN npm init -y \
|
|
13
15
|
&& npm pkg set "overrides.@opentelemetry/propagator-jaeger=<%- jaegerVersion %>" \
|
|
14
|
-
&& npm
|
|
16
|
+
&& npm pkg set "overrides.minimatch=<%- minimatchVersion %>" \
|
|
17
|
+
&& npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation@<%- adotVersion %> \
|
|
18
|
+
&& npm uninstall -g npm
|
|
15
19
|
|
|
16
20
|
# Copy bundled streamable http server
|
|
17
21
|
COPY index.js /app
|
|
@@ -8,7 +8,7 @@ import { addMcpServerInfra } from "../../utils/agent-core-constructs/agent-core-
|
|
|
8
8
|
import { addTypeScriptBundleTarget } from "../../utils/bundle/bundle.js";
|
|
9
9
|
import { resolveContainers } from "../../utils/containers.js";
|
|
10
10
|
import { addDependenciesToPackageJson } from "../../utils/dependencies.js";
|
|
11
|
-
import { addDockerScanTarget } from "../../utils/docker.js";
|
|
11
|
+
import { addDockerScanTarget, nodeImageVersions } from "../../utils/docker.js";
|
|
12
12
|
import { formatFilesInSubtree } from "../../utils/format.js";
|
|
13
13
|
import { FsCommands } from "../../utils/fs.js";
|
|
14
14
|
import { resolveIac } from "../../utils/iac.js";
|
|
@@ -53,7 +53,7 @@ export const tsMcpServerGenerator = async (tree, options)=>{
|
|
|
53
53
|
adotVersion: TS_VERSIONS['@aws/aws-distro-opentelemetry-node-autoinstrumentation'],
|
|
54
54
|
jaegerVersion: TS_VERSIONS['@opentelemetry/propagator-jaeger'],
|
|
55
55
|
nodeBaseImage: BASE_IMAGES.node,
|
|
56
|
-
|
|
56
|
+
...nodeImageVersions()
|
|
57
57
|
}, {
|
|
58
58
|
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
59
59
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/ts/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 detectPackageManager,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n readJson,\n type Tree,\n updateJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { ensureLicenseExceptions } from '../../license/config';\nimport { MCP_INSPECTOR_EXCEPTIONS } from '../../license/known-exceptions';\nimport { addMcpServerInfra } from '../../utils/agent-core-constructs/agent-core-constructs';\nimport { addTypeScriptBundleTarget } from '../../utils/bundle/bundle';\nimport { resolveContainers } from '../../utils/containers';\nimport { addDependenciesToPackageJson } from '../../utils/dependencies';\nimport { addDockerScanTarget } from '../../utils/docker';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { FsCommands } from '../../utils/fs';\nimport { resolveIac } from '../../utils/iac';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport { isEsmWorkspace } from '../../utils/module-format';\nimport { kebabCase, toClassName } from '../../utils/names';\nimport { getNpmScope } from '../../utils/npm-scope';\nimport {\n addComponentDevTarget,\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport { assignPort } from '../../utils/port';\nimport { sharedConstructsGenerator } from '../../utils/shared-constructs';\nimport { BASE_IMAGES, TS_VERSIONS, withVersions } from '../../utils/versions';\nimport type { TsMcpServerGeneratorSchema } from './schema';\n\nexport const TS_MCP_SERVER_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const tsMcpServerGenerator = async (\n tree: Tree,\n options: TsMcpServerGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const project = readProjectConfigurationUnqualified(tree, options.project);\n\n if (!tree.exists(joinPathFragments(project.root, 'tsconfig.json'))) {\n throw new Error(\n `Unsupported project ${options.project}. Expected a TypeScript project (with a tsconfig.json)`,\n );\n }\n\n const defaultName = `${kebabCase(project.name.split('/').pop())}-mcp-server`;\n const name = kebabCase(options.name || defaultName);\n const mcpServerNameClassName = toClassName(name);\n const mcpTargetPrefix = options.name ? name : 'mcp-server';\n const targetSourceDirRelativeToProjectRoot = joinPathFragments(\n 'src',\n mcpTargetPrefix,\n );\n const targetSourceDir = joinPathFragments(\n project.root,\n targetSourceDirRelativeToProjectRoot,\n );\n const relativeSourceDir = targetSourceDir.replace(project.root + '/', './');\n const distDir = joinPathFragments('dist', project.root);\n\n const infra = options.infra ?? 'agentcore';\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 const projectPackageJsonPath = joinPathFragments(\n project.root,\n 'package.json',\n );\n\n // Generate esm if the project's package.json is `type: module`, falling\n // back to the workspace format when the project has no manifest.\n const esm = tree.exists(projectPackageJsonPath)\n ? readJson(tree, projectPackageJsonPath).type === 'module'\n : isEsmWorkspace(tree);\n\n // Generate example server\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files'),\n targetSourceDir,\n {\n name,\n esm,\n distDir,\n adotVersion:\n TS_VERSIONS['@aws/aws-distro-opentelemetry-node-autoinstrumentation'],\n jaegerVersion: TS_VERSIONS['@opentelemetry/propagator-jaeger'],\n nodeBaseImage: BASE_IMAGES.node,\n npmVersion: TS_VERSIONS.npm,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // Add dependencies\n const deps = withVersions([\n '@modelcontextprotocol/sdk',\n 'zod',\n 'express',\n '@aws-lambda-powertools/parameters',\n '@aws-sdk/client-appconfigdata',\n ]);\n const devDeps = withVersions(['@types/express']);\n // tsx (local dev) and the MCP inspector are shared tooling.\n const rootDevDeps = withVersions(['tsx', '@modelcontextprotocol/inspector']);\n\n // Add hosting based on infra\n if (infra === 'agentcore') {\n const containers = await resolveContainers(tree, 'inherit');\n const dockerImageTag = `${getNpmScope(tree)}-${name}:latest`;\n\n // Add bundle target\n await addTypeScriptBundleTarget(tree, project, {\n targetFilePath: `${targetSourceDirRelativeToProjectRoot}/http.ts`,\n bundleOutputDir: joinPathFragments('mcp', name),\n });\n\n const dockerOutputDir = joinPathFragments(\n 'dist',\n project.root,\n 'bundle',\n 'mcp',\n name,\n );\n const dockerTargetName = `${mcpTargetPrefix}-docker`;\n\n const fs = new FsCommands(tree);\n project.targets[dockerTargetName] = {\n cache: true,\n outputs: [`{workspaceRoot}/${dockerOutputDir}/Dockerfile`],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.cp(\n `${targetSourceDir}/Dockerfile`,\n `${dockerOutputDir}/Dockerfile`,\n ),\n `${containers} build --platform linux/arm64 -t ${dockerImageTag} ${dockerOutputDir}`,\n ],\n parallel: false,\n },\n dependsOn: ['bundle'],\n };\n\n addDependencyToTargetIfNotPresent(project, 'docker', dockerTargetName);\n addDependencyToTargetIfNotPresent(project, 'build', 'docker');\n\n addDockerScanTarget(tree, {\n project,\n containerEngine: containers,\n trivyTargetName: `${mcpTargetPrefix}-trivy`,\n dockerTargetName,\n imageTags: [dockerImageTag],\n });\n\n // Add shared constructs\n const iac = await resolveIac(tree, options.iac);\n await sharedConstructsGenerator(tree, { iac });\n\n // Add the construct to deploy the mcp server\n await addMcpServerInfra(tree, {\n mcpServerNameKebabCase: name,\n mcpServerNameClassName,\n projectName: project.name,\n dockerImageTag,\n dockerOutputDir,\n iac,\n auth,\n containers,\n });\n } else {\n // No Dockerfile needed for non-hosted MCP\n tree.delete(joinPathFragments(targetSourceDir, 'Dockerfile'));\n }\n\n // Runtime deps go in the project manifest; shared tooling goes to the root.\n addDependenciesToPackageJson(tree, deps, devDeps, projectPackageJsonPath);\n addDependenciesToPackageJson(tree, {}, rootDevDeps);\n\n // @modelcontextprotocol/sdk declares zod as a peer dependency with a wide range\n // (^3.25 || ^4.0). Yarn does not dedupe the peer to the workspace's pinned zod, so\n // without a resolution it installs a separate zod under the SDK's own node_modules.\n // The two zod copies have structurally incompatible types, which breaks type\n // inference for registerTool inputSchema. Scope the resolution to the SDK so\n // other consumers (e.g. @tanstack/router-generator pinning zod@3) are unaffected.\n if (detectPackageManager() === 'yarn') {\n updateJson(tree, 'package.json', (packageJson) => {\n packageJson.resolutions = {\n ...packageJson.resolutions,\n '**/@modelcontextprotocol/sdk/zod': TS_VERSIONS['zod'],\n };\n return packageJson;\n });\n }\n\n const localDevPort = assignPort(tree, project, 8000, {\n component: { info: TS_MCP_SERVER_GENERATOR_INFO, name: mcpTargetPrefix },\n });\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: [`tsx --watch ${relativeSourceDir}/stdio.ts`],\n cwd: '{projectRoot}',\n },\n },\n [`${mcpTargetPrefix}-serve`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [`tsx --watch ${relativeSourceDir}/http.ts`],\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: [`tsx --watch ${relativeSourceDir}/http.ts`],\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 -- tsx --watch ${relativeSourceDir}/stdio.ts`,\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 // Sort targets so their order is stable regardless of insertion order on\n // first run vs re-run.\n targets: sortObjectKeys(mcpTargets),\n });\n\n addComponentGeneratorMetadata(\n tree,\n project.name,\n TS_MCP_SERVER_GENERATOR_INFO,\n targetSourceDirRelativeToProjectRoot,\n mcpTargetPrefix,\n {\n port: localDevPort,\n rc: mcpServerNameClassName,\n auth,\n },\n );\n\n await addGeneratorMetricsIfApplicable(tree, [TS_MCP_SERVER_GENERATOR_INFO]);\n\n await ensureLicenseExceptions(tree, MCP_INSPECTOR_EXCEPTIONS);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nexport default tsMcpServerGenerator;\n"],"names":["detectPackageManager","generateFiles","joinPathFragments","OverwriteStrategy","readJson","updateJson","updateProjectConfiguration","ensureLicenseExceptions","MCP_INSPECTOR_EXCEPTIONS","addMcpServerInfra","addTypeScriptBundleTarget","resolveContainers","addDependenciesToPackageJson","addDockerScanTarget","formatFilesInSubtree","FsCommands","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","isEsmWorkspace","kebabCase","toClassName","getNpmScope","addComponentDevTarget","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","readProjectConfigurationUnqualified","sortObjectKeys","assignPort","sharedConstructsGenerator","BASE_IMAGES","TS_VERSIONS","withVersions","TS_MCP_SERVER_GENERATOR_INFO","filename","tsMcpServerGenerator","tree","options","project","exists","root","Error","defaultName","name","split","pop","mcpServerNameClassName","mcpTargetPrefix","targetSourceDirRelativeToProjectRoot","targetSourceDir","relativeSourceDir","replace","distDir","infra","auth","console","warn","projectPackageJsonPath","esm","type","dirname","adotVersion","jaegerVersion","nodeBaseImage","node","npmVersion","npm","overwriteStrategy","KeepExisting","deps","devDeps","rootDevDeps","containers","dockerImageTag","targetFilePath","bundleOutputDir","dockerOutputDir","dockerTargetName","fs","targets","cache","outputs","executor","commands","cp","parallel","dependsOn","containerEngine","trivyTargetName","imageTags","iac","mcpServerNameKebabCase","projectName","delete","packageJson","resolutions","localDevPort","component","info","mcpTargets","continuous","cwd","env","PORT","LOCAL_DEV","port","rc","preferInstallDependencies","languages"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/ts/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 detectPackageManager,\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n readJson,\n type Tree,\n updateJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { ensureLicenseExceptions } from '../../license/config';\nimport { MCP_INSPECTOR_EXCEPTIONS } from '../../license/known-exceptions';\nimport { addMcpServerInfra } from '../../utils/agent-core-constructs/agent-core-constructs';\nimport { addTypeScriptBundleTarget } from '../../utils/bundle/bundle';\nimport { resolveContainers } from '../../utils/containers';\nimport { addDependenciesToPackageJson } from '../../utils/dependencies';\nimport { addDockerScanTarget, nodeImageVersions } from '../../utils/docker';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { FsCommands } from '../../utils/fs';\nimport { resolveIac } from '../../utils/iac';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport { isEsmWorkspace } from '../../utils/module-format';\nimport { kebabCase, toClassName } from '../../utils/names';\nimport { getNpmScope } from '../../utils/npm-scope';\nimport {\n addComponentDevTarget,\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport { assignPort } from '../../utils/port';\nimport { sharedConstructsGenerator } from '../../utils/shared-constructs';\nimport { BASE_IMAGES, TS_VERSIONS, withVersions } from '../../utils/versions';\nimport type { TsMcpServerGeneratorSchema } from './schema';\n\nexport const TS_MCP_SERVER_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const tsMcpServerGenerator = async (\n tree: Tree,\n options: TsMcpServerGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const project = readProjectConfigurationUnqualified(tree, options.project);\n\n if (!tree.exists(joinPathFragments(project.root, 'tsconfig.json'))) {\n throw new Error(\n `Unsupported project ${options.project}. Expected a TypeScript project (with a tsconfig.json)`,\n );\n }\n\n const defaultName = `${kebabCase(project.name.split('/').pop())}-mcp-server`;\n const name = kebabCase(options.name || defaultName);\n const mcpServerNameClassName = toClassName(name);\n const mcpTargetPrefix = options.name ? name : 'mcp-server';\n const targetSourceDirRelativeToProjectRoot = joinPathFragments(\n 'src',\n mcpTargetPrefix,\n );\n const targetSourceDir = joinPathFragments(\n project.root,\n targetSourceDirRelativeToProjectRoot,\n );\n const relativeSourceDir = targetSourceDir.replace(project.root + '/', './');\n const distDir = joinPathFragments('dist', project.root);\n\n const infra = options.infra ?? 'agentcore';\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 const projectPackageJsonPath = joinPathFragments(\n project.root,\n 'package.json',\n );\n\n // Generate esm if the project's package.json is `type: module`, falling\n // back to the workspace format when the project has no manifest.\n const esm = tree.exists(projectPackageJsonPath)\n ? readJson(tree, projectPackageJsonPath).type === 'module'\n : isEsmWorkspace(tree);\n\n // Generate example server\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files'),\n targetSourceDir,\n {\n name,\n esm,\n distDir,\n adotVersion:\n TS_VERSIONS['@aws/aws-distro-opentelemetry-node-autoinstrumentation'],\n jaegerVersion: TS_VERSIONS['@opentelemetry/propagator-jaeger'],\n nodeBaseImage: BASE_IMAGES.node,\n ...nodeImageVersions(),\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // Add dependencies\n const deps = withVersions([\n '@modelcontextprotocol/sdk',\n 'zod',\n 'express',\n '@aws-lambda-powertools/parameters',\n '@aws-sdk/client-appconfigdata',\n ]);\n const devDeps = withVersions(['@types/express']);\n // tsx (local dev) and the MCP inspector are shared tooling.\n const rootDevDeps = withVersions(['tsx', '@modelcontextprotocol/inspector']);\n\n // Add hosting based on infra\n if (infra === 'agentcore') {\n const containers = await resolveContainers(tree, 'inherit');\n const dockerImageTag = `${getNpmScope(tree)}-${name}:latest`;\n\n // Add bundle target\n await addTypeScriptBundleTarget(tree, project, {\n targetFilePath: `${targetSourceDirRelativeToProjectRoot}/http.ts`,\n bundleOutputDir: joinPathFragments('mcp', name),\n });\n\n const dockerOutputDir = joinPathFragments(\n 'dist',\n project.root,\n 'bundle',\n 'mcp',\n name,\n );\n const dockerTargetName = `${mcpTargetPrefix}-docker`;\n\n const fs = new FsCommands(tree);\n project.targets[dockerTargetName] = {\n cache: true,\n outputs: [`{workspaceRoot}/${dockerOutputDir}/Dockerfile`],\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.cp(\n `${targetSourceDir}/Dockerfile`,\n `${dockerOutputDir}/Dockerfile`,\n ),\n `${containers} build --platform linux/arm64 -t ${dockerImageTag} ${dockerOutputDir}`,\n ],\n parallel: false,\n },\n dependsOn: ['bundle'],\n };\n\n addDependencyToTargetIfNotPresent(project, 'docker', dockerTargetName);\n addDependencyToTargetIfNotPresent(project, 'build', 'docker');\n\n addDockerScanTarget(tree, {\n project,\n containerEngine: containers,\n trivyTargetName: `${mcpTargetPrefix}-trivy`,\n dockerTargetName,\n imageTags: [dockerImageTag],\n });\n\n // Add shared constructs\n const iac = await resolveIac(tree, options.iac);\n await sharedConstructsGenerator(tree, { iac });\n\n // Add the construct to deploy the mcp server\n await addMcpServerInfra(tree, {\n mcpServerNameKebabCase: name,\n mcpServerNameClassName,\n projectName: project.name,\n dockerImageTag,\n dockerOutputDir,\n iac,\n auth,\n containers,\n });\n } else {\n // No Dockerfile needed for non-hosted MCP\n tree.delete(joinPathFragments(targetSourceDir, 'Dockerfile'));\n }\n\n // Runtime deps go in the project manifest; shared tooling goes to the root.\n addDependenciesToPackageJson(tree, deps, devDeps, projectPackageJsonPath);\n addDependenciesToPackageJson(tree, {}, rootDevDeps);\n\n // @modelcontextprotocol/sdk declares zod as a peer dependency with a wide range\n // (^3.25 || ^4.0). Yarn does not dedupe the peer to the workspace's pinned zod, so\n // without a resolution it installs a separate zod under the SDK's own node_modules.\n // The two zod copies have structurally incompatible types, which breaks type\n // inference for registerTool inputSchema. Scope the resolution to the SDK so\n // other consumers (e.g. @tanstack/router-generator pinning zod@3) are unaffected.\n if (detectPackageManager() === 'yarn') {\n updateJson(tree, 'package.json', (packageJson) => {\n packageJson.resolutions = {\n ...packageJson.resolutions,\n '**/@modelcontextprotocol/sdk/zod': TS_VERSIONS['zod'],\n };\n return packageJson;\n });\n }\n\n const localDevPort = assignPort(tree, project, 8000, {\n component: { info: TS_MCP_SERVER_GENERATOR_INFO, name: mcpTargetPrefix },\n });\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: [`tsx --watch ${relativeSourceDir}/stdio.ts`],\n cwd: '{projectRoot}',\n },\n },\n [`${mcpTargetPrefix}-serve`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [`tsx --watch ${relativeSourceDir}/http.ts`],\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: [`tsx --watch ${relativeSourceDir}/http.ts`],\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 -- tsx --watch ${relativeSourceDir}/stdio.ts`,\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 // Sort targets so their order is stable regardless of insertion order on\n // first run vs re-run.\n targets: sortObjectKeys(mcpTargets),\n });\n\n addComponentGeneratorMetadata(\n tree,\n project.name,\n TS_MCP_SERVER_GENERATOR_INFO,\n targetSourceDirRelativeToProjectRoot,\n mcpTargetPrefix,\n {\n port: localDevPort,\n rc: mcpServerNameClassName,\n auth,\n },\n );\n\n await addGeneratorMetricsIfApplicable(tree, [TS_MCP_SERVER_GENERATOR_INFO]);\n\n await ensureLicenseExceptions(tree, MCP_INSPECTOR_EXCEPTIONS);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nexport default tsMcpServerGenerator;\n"],"names":["detectPackageManager","generateFiles","joinPathFragments","OverwriteStrategy","readJson","updateJson","updateProjectConfiguration","ensureLicenseExceptions","MCP_INSPECTOR_EXCEPTIONS","addMcpServerInfra","addTypeScriptBundleTarget","resolveContainers","addDependenciesToPackageJson","addDockerScanTarget","nodeImageVersions","formatFilesInSubtree","FsCommands","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","isEsmWorkspace","kebabCase","toClassName","getNpmScope","addComponentDevTarget","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","readProjectConfigurationUnqualified","sortObjectKeys","assignPort","sharedConstructsGenerator","BASE_IMAGES","TS_VERSIONS","withVersions","TS_MCP_SERVER_GENERATOR_INFO","filename","tsMcpServerGenerator","tree","options","project","exists","root","Error","defaultName","name","split","pop","mcpServerNameClassName","mcpTargetPrefix","targetSourceDirRelativeToProjectRoot","targetSourceDir","relativeSourceDir","replace","distDir","infra","auth","console","warn","projectPackageJsonPath","esm","type","dirname","adotVersion","jaegerVersion","nodeBaseImage","node","overwriteStrategy","KeepExisting","deps","devDeps","rootDevDeps","containers","dockerImageTag","targetFilePath","bundleOutputDir","dockerOutputDir","dockerTargetName","fs","targets","cache","outputs","executor","commands","cp","parallel","dependsOn","containerEngine","trivyTargetName","imageTags","iac","mcpServerNameKebabCase","projectName","delete","packageJson","resolutions","localDevPort","component","info","mcpTargets","continuous","cwd","env","PORT","LOCAL_DEV","port","rc","preferInstallDependencies","languages"],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Tree } from '@nx/devkit';
|
|
2
|
+
import { createTreeUsingTsSolutionSetup } from '<%- testImportPath %>';
|
|
3
|
+
import migration from './migration';
|
|
4
|
+
|
|
5
|
+
describe('<%= name %> migration', () => {
|
|
6
|
+
let tree: Tree;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
tree = createTreeUsingTsSolutionSetup();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('should apply to the shape your generators produce', async () => {
|
|
13
|
+
// TODO: arrange the "before" state and assert the expected changes.
|
|
14
|
+
const result = await migration(tree);
|
|
15
|
+
expect(result.nextSteps).toBeDefined();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should skip and report a customised file', () => {
|
|
19
|
+
// TODO: arrange a diverged file and assert it is left untouched and
|
|
20
|
+
// reported via nextSteps.
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should be idempotent', () => {
|
|
24
|
+
// TODO: run the migration twice and assert the second run is a no-op.
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type MigrationReturnObject, type Tree } from '@nx/devkit';
|
|
2
|
+
import { formatFilesInSubtree } from '<%- formatImportPath %>';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* <%= description %>
|
|
6
|
+
<%_ if (isHybrid) { _%>
|
|
7
|
+
*
|
|
8
|
+
* Hybrid migration: this codemod does the mechanical part, then the paired
|
|
9
|
+
* prompt (prompt.md) hands off to the user's agent for the rest.
|
|
10
|
+
*
|
|
11
|
+
* How to write a migration:
|
|
12
|
+
* - https://nx.dev/docs/kb/migration-generators
|
|
13
|
+
* - `nextSteps` and `agentContext`: https://nx.dev/docs/reference/devkit/MigrationReturnObject
|
|
14
|
+
*
|
|
15
|
+
* Guardrails:
|
|
16
|
+
* - Pattern-match before writing: skip files that have diverged from the shape
|
|
17
|
+
* your generators produce, and report them via `agentContext` so the prompt
|
|
18
|
+
* can pick them up, rather than clobbering the user's changes.
|
|
19
|
+
* - Idempotent: re-running must be a no-op.
|
|
20
|
+
* - Format what you write: finish with `formatFilesInSubtree` so the files your
|
|
21
|
+
* migration wrote are formatted correctly.
|
|
22
|
+
*/
|
|
23
|
+
<%_ } else { _%>
|
|
24
|
+
*
|
|
25
|
+
* How to write a migration:
|
|
26
|
+
* - https://nx.dev/docs/kb/migration-generators
|
|
27
|
+
* - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject
|
|
28
|
+
*
|
|
29
|
+
* Guardrails:
|
|
30
|
+
* - Pattern-match before writing: skip files that have diverged from the shape
|
|
31
|
+
* your generators produce and report them via `nextSteps`, or consider a
|
|
32
|
+
* hybrid migration, rather than clobbering the user's changes.
|
|
33
|
+
* - Idempotent: re-running must be a no-op.
|
|
34
|
+
* - Format what you write: finish with `formatFilesInSubtree` so the files your
|
|
35
|
+
* migration wrote are formatted correctly.
|
|
36
|
+
*/
|
|
37
|
+
<%_ } _%>
|
|
38
|
+
export default async function migration(
|
|
39
|
+
tree: Tree,
|
|
40
|
+
): Promise<MigrationReturnObject> {
|
|
41
|
+
const nextSteps: string[] = [];
|
|
42
|
+
<% if (isHybrid) { %> const agentContext: string[] = [];
|
|
43
|
+
<% } %>
|
|
44
|
+
// TODO: read the workspace's files and update the ones matching the shape
|
|
45
|
+
// your generators produce, noting any you skip in `nextSteps`.
|
|
46
|
+
<% if (isHybrid) { %>
|
|
47
|
+
// `agentContext` reaches the paired prompt under `--agentic` and is dropped
|
|
48
|
+
// otherwise.
|
|
49
|
+
// TODO: describe what changed in `agentContext`, e.g.:
|
|
50
|
+
// agentContext.push('Renamed the `foo` target to `bar` in every project.json.');
|
|
51
|
+
<% } %>
|
|
52
|
+
await formatFilesInSubtree(tree);
|
|
53
|
+
|
|
54
|
+
return { nextSteps<% if (isHybrid) { %>, agentContext<% } %> };
|
|
55
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<%_ if (isHybrid) { _%>
|
|
2
|
+
<!-- Authoring guide (delete before shipping): this file is the `prompt` for the
|
|
3
|
+
agentic half of a hybrid migration. The codemod half (migration.ts) has already
|
|
4
|
+
run its mechanical changes and passes a summary via `agentContext`. The prompt is
|
|
5
|
+
applied by the user's AI coding agent, and shown verbatim to users who run
|
|
6
|
+
`nx migrate` without one, so write self-contained, human-actionable steps.
|
|
7
|
+
See https://nx.dev/docs/kb/migration-generators -->
|
|
8
|
+
<%_ } else { _%>
|
|
9
|
+
<!-- Authoring guide (delete before shipping): this file is the `prompt` for an
|
|
10
|
+
agentic migration. It is applied by the user's AI coding agent, and shown
|
|
11
|
+
verbatim to users who run `nx migrate` without one, so write self-contained,
|
|
12
|
+
human-actionable steps.
|
|
13
|
+
See https://nx.dev/docs/kb/migration-generators -->
|
|
14
|
+
<%_ } _%>
|
|
15
|
+
|
|
16
|
+
# <%= description %>
|
|
17
|
+
|
|
18
|
+
## Overview
|
|
19
|
+
|
|
20
|
+
<%_ if (isHybrid) { _%>
|
|
21
|
+
<!-- TODO: describe the breaking change and what remains to be done in
|
|
22
|
+
user-owned code after the codemod has run. -->
|
|
23
|
+
<%_ } else { _%>
|
|
24
|
+
<!-- TODO: describe the breaking change and what the workspace needs to end up
|
|
25
|
+
looking like. -->
|
|
26
|
+
<%_ } _%>
|
|
27
|
+
|
|
28
|
+
## Steps
|
|
29
|
+
|
|
30
|
+
<%_ if (isHybrid) { _%>
|
|
31
|
+
1. <!-- TODO: identify the user-owned call sites the codemod could not update
|
|
32
|
+
(e.g. "handlers that call the renamed API"). -->
|
|
33
|
+
<%_ } else { _%>
|
|
34
|
+
1. <!-- TODO: identify the files/patterns affected (e.g. "search for `oldApi(`
|
|
35
|
+
across the workspace"). -->
|
|
36
|
+
<%_ } _%>
|
|
37
|
+
2. <!-- TODO: describe the transformation with before/after examples. -->
|
|
38
|
+
3. <!-- TODO: how to verify: run `nx run-many --target build --all` (and any
|
|
39
|
+
relevant tests) and confirm they pass. -->
|
|
40
|
+
|
|
41
|
+
## Guard rails
|
|
42
|
+
|
|
43
|
+
- Only change what these instructions describe. Do not reformat unrelated code.
|
|
44
|
+
- Do not weaken or delete tests to make them pass.
|
|
45
|
+
- If a file has been customised in a way these instructions don't cover, leave
|
|
46
|
+
it and note it for the user rather than guessing.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { type GeneratorCallback, type Tree } from '@nx/devkit';
|
|
6
|
+
import { type NxGeneratorInfo } from '../../utils/nx';
|
|
7
|
+
import type { TsNxMigrationGeneratorSchema } from './schema';
|
|
8
|
+
export declare const NX_MIGRATION_GENERATOR_INFO: NxGeneratorInfo;
|
|
9
|
+
/**
|
|
10
|
+
* Scaffolds a migration in an Nx Plugin project and registers it in the
|
|
11
|
+
* plugin's `migrations.json` (creating the manifest and wiring the
|
|
12
|
+
* `nx-migrations` field into the plugin's `package.json` if absent), so
|
|
13
|
+
* `nx migrate` applies it when users upgrade the plugin.
|
|
14
|
+
*
|
|
15
|
+
* Supports all three migration kinds:
|
|
16
|
+
* - `deterministic`: a codemod (`implementation`).
|
|
17
|
+
* - `agentic`: a `prompt` markdown file applied by the user's agent.
|
|
18
|
+
* - `hybrid`: both — the codemod does the mechanical part and returns
|
|
19
|
+
* `agentContext`, then the prompt hands off to the agent for the rest.
|
|
20
|
+
*
|
|
21
|
+
* No `version` is written — the plugin author stamps versions at release time.
|
|
22
|
+
*/
|
|
23
|
+
export declare const tsNxMigrationGenerator: (tree: Tree, options: TsNxMigrationGeneratorSchema) => Promise<GeneratorCallback | void>;
|
|
24
|
+
export default tsNxMigrationGenerator;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { generateFiles, joinPathFragments, OverwriteStrategy, readJson, writeJson } from "@nx/devkit";
|
|
5
|
+
import PackageJson from "../../../package.json" with {
|
|
6
|
+
type: 'json'
|
|
7
|
+
};
|
|
8
|
+
import { formatFilesInSubtree } from "../../utils/format.js";
|
|
9
|
+
import { installDependencies } from "../../utils/install.js";
|
|
10
|
+
import { addGeneratorMetricsIfApplicable } from "../../utils/metrics.js";
|
|
11
|
+
import { LATEST_MIGRATIONS_DIR, migrationKey } from "../../utils/migration-versions.js";
|
|
12
|
+
import { kebabCase } from "../../utils/names.js";
|
|
13
|
+
import { getGeneratorInfo, isNxPluginForAwsWorkspace } from "../../utils/nx.js";
|
|
14
|
+
import { sortObjectKeys } from "../../utils/object.js";
|
|
15
|
+
import { addNxPluginDependencies, configureNxPluginPackageJson, readNxPluginProject } from "../nx-plugin/utils.js";
|
|
16
|
+
export const NX_MIGRATION_GENERATOR_INFO = getGeneratorInfo(import.meta.filename);
|
|
17
|
+
/**
|
|
18
|
+
* Scaffolds a migration in an Nx Plugin project and registers it in the
|
|
19
|
+
* plugin's `migrations.json` (creating the manifest and wiring the
|
|
20
|
+
* `nx-migrations` field into the plugin's `package.json` if absent), so
|
|
21
|
+
* `nx migrate` applies it when users upgrade the plugin.
|
|
22
|
+
*
|
|
23
|
+
* Supports all three migration kinds:
|
|
24
|
+
* - `deterministic`: a codemod (`implementation`).
|
|
25
|
+
* - `agentic`: a `prompt` markdown file applied by the user's agent.
|
|
26
|
+
* - `hybrid`: both — the codemod does the mechanical part and returns
|
|
27
|
+
* `agentContext`, then the prompt hands off to the agent for the rest.
|
|
28
|
+
*
|
|
29
|
+
* No `version` is written — the plugin author stamps versions at release time.
|
|
30
|
+
*/ export const tsNxMigrationGenerator = async (tree, options)=>{
|
|
31
|
+
const name = kebabCase(options.name);
|
|
32
|
+
// Shown by `nx migrate` when the migration runs, so it needs to say something
|
|
33
|
+
const description = options.description ?? 'TODO: Add short description of the migration';
|
|
34
|
+
const kind = options.kind ?? 'deterministic';
|
|
35
|
+
const hasImplementation = kind === 'deterministic' || kind === 'hybrid';
|
|
36
|
+
const hasPrompt = kind === 'agentic' || kind === 'hybrid';
|
|
37
|
+
const isHybrid = kind === 'hybrid';
|
|
38
|
+
const plugin = readNxPluginProject(tree, options.project);
|
|
39
|
+
const sourceRoot = plugin.sourceRoot ?? joinPathFragments(plugin.root, 'src');
|
|
40
|
+
const srcDir = sourceRoot.split('/').filter(Boolean).pop();
|
|
41
|
+
// Migrations are grouped by the release that ships them. A new one lands in
|
|
42
|
+
// `latest` — the release that picks it up moves it into its version folder.
|
|
43
|
+
const migrationPath = `${srcDir}/migrations/${LATEST_MIGRATIONS_DIR}/${name}`;
|
|
44
|
+
const migrationDir = joinPathFragments(sourceRoot, 'migrations', LATEST_MIGRATIONS_DIR, name);
|
|
45
|
+
const key = migrationKey(LATEST_MIGRATIONS_DIR, name);
|
|
46
|
+
const isNxPluginForAws = isNxPluginForAwsWorkspace(tree);
|
|
47
|
+
// Point the plugin at its migrations manifest so `nx migrate` finds them
|
|
48
|
+
const pluginPackageJsonPath = configureNxPluginPackageJson(tree, plugin, 'nx-migrations', {
|
|
49
|
+
migrations: './migrations.json'
|
|
50
|
+
});
|
|
51
|
+
// Migrations sit three levels below the source root, so in this repo the
|
|
52
|
+
// shared utils are relative. Elsewhere they come from the SDK.
|
|
53
|
+
const formatImportPath = isNxPluginForAws ? '../../../utils/format' : `${PackageJson.name}/sdk/utils/format`;
|
|
54
|
+
const testImportPath = isNxPluginForAws ? '../../../utils/test' : `${PackageJson.name}/sdk/utils/test`;
|
|
55
|
+
// One template set covers all kinds — scaffold it, then prune what this kind
|
|
56
|
+
// doesn't use.
|
|
57
|
+
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files'), migrationDir, {
|
|
58
|
+
name,
|
|
59
|
+
description,
|
|
60
|
+
isHybrid,
|
|
61
|
+
formatImportPath,
|
|
62
|
+
testImportPath
|
|
63
|
+
}, {
|
|
64
|
+
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
65
|
+
});
|
|
66
|
+
if (!hasImplementation) {
|
|
67
|
+
tree.delete(joinPathFragments(migrationDir, 'migration.ts'));
|
|
68
|
+
tree.delete(joinPathFragments(migrationDir, 'migration.spec.ts'));
|
|
69
|
+
}
|
|
70
|
+
if (!hasPrompt) {
|
|
71
|
+
tree.delete(joinPathFragments(migrationDir, 'prompt.md'));
|
|
72
|
+
}
|
|
73
|
+
// Register the migration under its folder-prefixed key. The fields present
|
|
74
|
+
// discriminate the kind for nx, and paths are relative to migrations.json.
|
|
75
|
+
// No version is written, but an already-stamped one is preserved.
|
|
76
|
+
const migrationsJsonPath = joinPathFragments(plugin.root, 'migrations.json');
|
|
77
|
+
const migrationsJson = tree.exists(migrationsJsonPath) ? readJson(tree, migrationsJsonPath) : {
|
|
78
|
+
$schema: 'http://json-schema.org/schema',
|
|
79
|
+
name: readJson(tree, pluginPackageJsonPath).name ?? plugin.name,
|
|
80
|
+
generators: {}
|
|
81
|
+
};
|
|
82
|
+
writeJson(tree, migrationsJsonPath, {
|
|
83
|
+
...migrationsJson,
|
|
84
|
+
generators: sortObjectKeys({
|
|
85
|
+
...migrationsJson.generators,
|
|
86
|
+
[key]: {
|
|
87
|
+
...migrationsJson.generators?.[key]?.version ? {
|
|
88
|
+
version: migrationsJson.generators[key].version
|
|
89
|
+
} : {},
|
|
90
|
+
description,
|
|
91
|
+
...hasImplementation ? {
|
|
92
|
+
implementation: `./${migrationPath}/migration`
|
|
93
|
+
} : {},
|
|
94
|
+
...hasPrompt ? {
|
|
95
|
+
prompt: `./${migrationPath}/prompt.md`
|
|
96
|
+
} : {}
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
});
|
|
100
|
+
// Codemods import @nx/devkit and the @aws/nx-plugin SDK, both of which must
|
|
101
|
+
// resolve for nx to run them
|
|
102
|
+
if (hasImplementation) {
|
|
103
|
+
addNxPluginDependencies(tree, pluginPackageJsonPath);
|
|
104
|
+
}
|
|
105
|
+
await addGeneratorMetricsIfApplicable(tree, [
|
|
106
|
+
NX_MIGRATION_GENERATOR_INFO
|
|
107
|
+
]);
|
|
108
|
+
await formatFilesInSubtree(tree);
|
|
109
|
+
if (hasImplementation && !isNxPluginForAws) {
|
|
110
|
+
return ()=>installDependencies(tree, options.preferInstallDependencies, {
|
|
111
|
+
languages: [
|
|
112
|
+
'typescript'
|
|
113
|
+
],
|
|
114
|
+
ensureResolvable: [
|
|
115
|
+
'@nx/devkit'
|
|
116
|
+
]
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
export default tsNxMigrationGenerator;
|
|
121
|
+
|
|
122
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/ts/nx-migration/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 readJson,\n type Tree,\n writeJson,\n} from '@nx/devkit';\nimport PackageJson from '../../../package.json' with { type: 'json' };\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport {\n LATEST_MIGRATIONS_DIR,\n migrationKey,\n} from '../../utils/migration-versions';\nimport { kebabCase } from '../../utils/names';\nimport {\n getGeneratorInfo,\n isNxPluginForAwsWorkspace,\n type NxGeneratorInfo,\n} from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport {\n addNxPluginDependencies,\n configureNxPluginPackageJson,\n readNxPluginProject,\n} from '../nx-plugin/utils';\nimport type { TsNxMigrationGeneratorSchema } from './schema';\n\nexport const NX_MIGRATION_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\n/**\n * Scaffolds a migration in an Nx Plugin project and registers it in the\n * plugin's `migrations.json` (creating the manifest and wiring the\n * `nx-migrations` field into the plugin's `package.json` if absent), so\n * `nx migrate` applies it when users upgrade the plugin.\n *\n * Supports all three migration kinds:\n * - `deterministic`: a codemod (`implementation`).\n * - `agentic`: a `prompt` markdown file applied by the user's agent.\n * - `hybrid`: both — the codemod does the mechanical part and returns\n * `agentContext`, then the prompt hands off to the agent for the rest.\n *\n * No `version` is written — the plugin author stamps versions at release time.\n */\nexport const tsNxMigrationGenerator = async (\n tree: Tree,\n options: TsNxMigrationGeneratorSchema,\n): Promise<GeneratorCallback | void> => {\n const name = kebabCase(options.name);\n // Shown by `nx migrate` when the migration runs, so it needs to say something\n const description =\n options.description ?? 'TODO: Add short description of the migration';\n const kind = options.kind ?? 'deterministic';\n\n const hasImplementation = kind === 'deterministic' || kind === 'hybrid';\n const hasPrompt = kind === 'agentic' || kind === 'hybrid';\n const isHybrid = kind === 'hybrid';\n\n const plugin = readNxPluginProject(tree, options.project);\n\n const sourceRoot = plugin.sourceRoot ?? joinPathFragments(plugin.root, 'src');\n const srcDir = sourceRoot.split('/').filter(Boolean).pop();\n // Migrations are grouped by the release that ships them. A new one lands in\n // `latest` — the release that picks it up moves it into its version folder.\n const migrationPath = `${srcDir}/migrations/${LATEST_MIGRATIONS_DIR}/${name}`;\n const migrationDir = joinPathFragments(\n sourceRoot,\n 'migrations',\n LATEST_MIGRATIONS_DIR,\n name,\n );\n const key = migrationKey(LATEST_MIGRATIONS_DIR, name);\n\n const isNxPluginForAws = isNxPluginForAwsWorkspace(tree);\n\n // Point the plugin at its migrations manifest so `nx migrate` finds them\n const pluginPackageJsonPath = configureNxPluginPackageJson(\n tree,\n plugin,\n 'nx-migrations',\n { migrations: './migrations.json' },\n );\n\n // Migrations sit three levels below the source root, so in this repo the\n // shared utils are relative. Elsewhere they come from the SDK.\n const formatImportPath = isNxPluginForAws\n ? '../../../utils/format'\n : `${PackageJson.name}/sdk/utils/format`;\n const testImportPath = isNxPluginForAws\n ? '../../../utils/test'\n : `${PackageJson.name}/sdk/utils/test`;\n\n // One template set covers all kinds — scaffold it, then prune what this kind\n // doesn't use.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files'),\n migrationDir,\n { name, description, isHybrid, formatImportPath, testImportPath },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n if (!hasImplementation) {\n tree.delete(joinPathFragments(migrationDir, 'migration.ts'));\n tree.delete(joinPathFragments(migrationDir, 'migration.spec.ts'));\n }\n if (!hasPrompt) {\n tree.delete(joinPathFragments(migrationDir, 'prompt.md'));\n }\n\n // Register the migration under its folder-prefixed key. The fields present\n // discriminate the kind for nx, and paths are relative to migrations.json.\n // No version is written, but an already-stamped one is preserved.\n const migrationsJsonPath = joinPathFragments(plugin.root, 'migrations.json');\n const migrationsJson = tree.exists(migrationsJsonPath)\n ? readJson(tree, migrationsJsonPath)\n : {\n $schema: 'http://json-schema.org/schema',\n name: readJson(tree, pluginPackageJsonPath).name ?? plugin.name,\n generators: {},\n };\n writeJson(tree, migrationsJsonPath, {\n ...migrationsJson,\n generators: sortObjectKeys({\n ...migrationsJson.generators,\n [key]: {\n ...(migrationsJson.generators?.[key]?.version\n ? { version: migrationsJson.generators[key].version }\n : {}),\n description,\n ...(hasImplementation\n ? { implementation: `./${migrationPath}/migration` }\n : {}),\n ...(hasPrompt ? { prompt: `./${migrationPath}/prompt.md` } : {}),\n },\n }),\n });\n\n // Codemods import @nx/devkit and the @aws/nx-plugin SDK, both of which must\n // resolve for nx to run them\n if (hasImplementation) {\n addNxPluginDependencies(tree, pluginPackageJsonPath);\n }\n\n await addGeneratorMetricsIfApplicable(tree, [NX_MIGRATION_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n\n if (hasImplementation && !isNxPluginForAws) {\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n ensureResolvable: ['@nx/devkit'],\n });\n }\n};\n\nexport default tsNxMigrationGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","readJson","writeJson","PackageJson","type","formatFilesInSubtree","installDependencies","addGeneratorMetricsIfApplicable","LATEST_MIGRATIONS_DIR","migrationKey","kebabCase","getGeneratorInfo","isNxPluginForAwsWorkspace","sortObjectKeys","addNxPluginDependencies","configureNxPluginPackageJson","readNxPluginProject","NX_MIGRATION_GENERATOR_INFO","filename","tsNxMigrationGenerator","tree","options","name","description","kind","hasImplementation","hasPrompt","isHybrid","plugin","project","sourceRoot","root","srcDir","split","filter","Boolean","pop","migrationPath","migrationDir","key","isNxPluginForAws","pluginPackageJsonPath","migrations","formatImportPath","testImportPath","dirname","overwriteStrategy","KeepExisting","delete","migrationsJsonPath","migrationsJson","exists","$schema","generators","version","implementation","prompt","preferInstallDependencies","languages","ensureResolvable"],"mappings":"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"}
|