nx 21.6.1-beta.3 → 21.6.1-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/bin/nx.js +1 -0
  2. package/package.json +11 -11
  3. package/src/ai/constants.d.ts +15 -0
  4. package/src/ai/constants.d.ts.map +1 -0
  5. package/src/ai/constants.js +53 -0
  6. package/src/ai/set-up-ai-agents/schema.d.ts +1 -0
  7. package/src/ai/set-up-ai-agents/schema.json +9 -0
  8. package/src/ai/set-up-ai-agents/set-up-ai-agents.d.ts +7 -2
  9. package/src/ai/set-up-ai-agents/set-up-ai-agents.d.ts.map +1 -1
  10. package/src/ai/set-up-ai-agents/set-up-ai-agents.js +151 -22
  11. package/src/ai/utils.d.ts +20 -0
  12. package/src/ai/utils.d.ts.map +1 -0
  13. package/src/ai/utils.js +187 -0
  14. package/src/command-line/configure-ai-agents/command-object.d.ts +9 -0
  15. package/src/command-line/configure-ai-agents/command-object.d.ts.map +1 -0
  16. package/src/command-line/configure-ai-agents/command-object.js +32 -0
  17. package/src/command-line/configure-ai-agents/configure-ai-agents.d.ts +4 -0
  18. package/src/command-line/configure-ai-agents/configure-ai-agents.d.ts.map +1 -0
  19. package/src/command-line/configure-ai-agents/configure-ai-agents.js +217 -0
  20. package/src/command-line/format/format.js +5 -1
  21. package/src/command-line/migrate/migrate.d.ts.map +1 -1
  22. package/src/command-line/migrate/migrate.js +5 -0
  23. package/src/command-line/nx-commands.d.ts.map +1 -1
  24. package/src/command-line/nx-commands.js +17 -15
  25. package/src/command-line/release/publish.d.ts.map +1 -1
  26. package/src/command-line/release/publish.js +8 -0
  27. package/src/command-line/run/run-one.d.ts.map +1 -1
  28. package/src/command-line/run/run-one.js +9 -9
  29. package/src/config/workspace-json-project-json.d.ts +1 -0
  30. package/src/config/workspace-json-project-json.d.ts.map +1 -1
  31. package/src/core/graph/main.js +1 -1
  32. package/src/native/index.d.ts +15 -0
  33. package/src/native/native-bindings.js +4 -0
  34. package/src/native/nx.wasi.cjs +53 -45
  35. package/src/native/nx.wasm32-wasi.wasm +0 -0
  36. package/src/plugins/js/lock-file/npm-parser.d.ts.map +1 -1
  37. package/src/plugins/js/lock-file/npm-parser.js +4 -1
  38. package/src/plugins/js/project-graph/build-dependencies/explicit-package-json-dependencies.js +7 -7
  39. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts +1 -1
  40. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts.map +1 -1
  41. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +33 -2
  42. package/src/plugins/package-json/create-nodes.d.ts.map +1 -1
  43. package/src/plugins/package-json/create-nodes.js +2 -3
  44. package/src/project-graph/plugins/loaded-nx-plugin.d.ts.map +1 -1
  45. package/src/project-graph/plugins/public-api.d.ts +4 -0
  46. package/src/project-graph/plugins/public-api.d.ts.map +1 -1
  47. package/src/tasks-runner/cache.js +1 -1
  48. package/src/tasks-runner/life-cycle.d.ts.map +1 -1
  49. package/src/tasks-runner/run-command.d.ts.map +1 -1
  50. package/src/tasks-runner/run-command.js +7 -2
  51. package/src/tasks-runner/utils.d.ts.map +1 -1
  52. package/src/tasks-runner/utils.js +3 -1
  53. package/src/utils/package-json.d.ts.map +1 -1
  54. package/src/utils/package-json.js +2 -1
  55. package/src/utils/provenance.d.ts.map +1 -1
  56. package/src/utils/provenance.js +2 -3
  57. package/src/utils/split-target.d.ts.map +1 -1
  58. package/src/utils/split-target.js +46 -6
package/bin/nx.js CHANGED
@@ -36,6 +36,7 @@ async function main() {
36
36
  if (process.argv[2] === 'new' ||
37
37
  process.argv[2] === '_migrate' ||
38
38
  process.argv[2] === 'init' ||
39
+ process.argv[2] === 'configure-ai-agents' ||
39
40
  (process.argv[2] === 'graph' && !workspace)) {
40
41
  process.env.NX_DAEMON = 'false';
41
42
  require('nx/src/command-line/nx-commands').commandsObject.argv;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "21.6.1-beta.3",
3
+ "version": "21.6.1-rc.0",
4
4
  "private": false,
5
5
  "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
6
6
  "repository": {
@@ -83,16 +83,16 @@
83
83
  }
84
84
  },
85
85
  "optionalDependencies": {
86
- "@nx/nx-darwin-arm64": "21.6.1-beta.3",
87
- "@nx/nx-darwin-x64": "21.6.1-beta.3",
88
- "@nx/nx-freebsd-x64": "21.6.1-beta.3",
89
- "@nx/nx-linux-arm-gnueabihf": "21.6.1-beta.3",
90
- "@nx/nx-linux-arm64-gnu": "21.6.1-beta.3",
91
- "@nx/nx-linux-arm64-musl": "21.6.1-beta.3",
92
- "@nx/nx-linux-x64-gnu": "21.6.1-beta.3",
93
- "@nx/nx-linux-x64-musl": "21.6.1-beta.3",
94
- "@nx/nx-win32-arm64-msvc": "21.6.1-beta.3",
95
- "@nx/nx-win32-x64-msvc": "21.6.1-beta.3"
86
+ "@nx/nx-darwin-arm64": "21.6.1-rc.0",
87
+ "@nx/nx-darwin-x64": "21.6.1-rc.0",
88
+ "@nx/nx-freebsd-x64": "21.6.1-rc.0",
89
+ "@nx/nx-linux-arm-gnueabihf": "21.6.1-rc.0",
90
+ "@nx/nx-linux-arm64-gnu": "21.6.1-rc.0",
91
+ "@nx/nx-linux-arm64-musl": "21.6.1-rc.0",
92
+ "@nx/nx-linux-x64-gnu": "21.6.1-rc.0",
93
+ "@nx/nx-linux-x64-musl": "21.6.1-rc.0",
94
+ "@nx/nx-win32-arm64-msvc": "21.6.1-rc.0",
95
+ "@nx/nx-win32-x64-msvc": "21.6.1-rc.0"
96
96
  },
97
97
  "nx-migrations": {
98
98
  "migrations": "./migrations.json",
@@ -0,0 +1,15 @@
1
+ export declare function agentsMdPath(root: string): string;
2
+ export declare function geminiMdPath(root: string): string;
3
+ export declare function parseGeminiSettings(root: string): any | undefined;
4
+ export declare function geminiSettingsPath(root: string): string;
5
+ export declare function claudeMdPath(root: string): string;
6
+ export declare function claudeMcpPath(root: string): string;
7
+ export declare const codexConfigTomlPath: string;
8
+ export declare const nxRulesMarkerCommentStart = "<!-- nx configuration start-->";
9
+ export declare const nxRulesMarkerCommentDescription = "<!-- Leave the start & end comments to automatically receive updates. -->";
10
+ export declare const nxRulesMarkerCommentEnd = "<!-- nx configuration end-->";
11
+ export declare const rulesRegex: RegExp;
12
+ export declare const getAgentRulesWrapped: (writeNxCloudRules: boolean) => string;
13
+ export declare const nxMcpTomlHeader = "[mcp_servers.\"nx-mcp\"]";
14
+ export declare const nxMcpTomlConfig = "[mcp_servers.\"nx-mcp\"]\ntype = \"stdio\"\ncommand = \"npx\"\nargs = [\"nx\", \"mcp\"]\n";
15
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/ai/constants.ts"],"names":[],"mappings":"AAMA,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAOjE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,eAAO,MAAM,mBAAmB,QAA2C,CAAC;AAE5E,eAAO,MAAM,yBAAyB,mCAAmC,CAAC;AAC1E,eAAO,MAAM,+BAA+B,8EAA8E,CAAC;AAC3H,eAAO,MAAM,uBAAuB,iCAAiC,CAAC;AACtE,eAAO,MAAM,UAAU,QAGtB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,mBAAmB,OAAO,WAG9D,CAAC;AAEF,eAAO,MAAM,eAAe,6BAA2B,CAAC;AACxD,eAAO,MAAM,eAAe,8FAI3B,CAAC"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.nxMcpTomlConfig = exports.nxMcpTomlHeader = exports.getAgentRulesWrapped = exports.rulesRegex = exports.nxRulesMarkerCommentEnd = exports.nxRulesMarkerCommentDescription = exports.nxRulesMarkerCommentStart = exports.codexConfigTomlPath = void 0;
4
+ exports.agentsMdPath = agentsMdPath;
5
+ exports.geminiMdPath = geminiMdPath;
6
+ exports.parseGeminiSettings = parseGeminiSettings;
7
+ exports.geminiSettingsPath = geminiSettingsPath;
8
+ exports.claudeMdPath = claudeMdPath;
9
+ exports.claudeMcpPath = claudeMcpPath;
10
+ const os_1 = require("os");
11
+ const path_1 = require("path");
12
+ const fileutils_1 = require("../utils/fileutils");
13
+ const get_agent_rules_1 = require("./set-up-ai-agents/get-agent-rules");
14
+ function agentsMdPath(root) {
15
+ return (0, path_1.join)(root, 'AGENTS.md');
16
+ }
17
+ function geminiMdPath(root) {
18
+ return (0, path_1.join)(root, 'GEMINI.md');
19
+ }
20
+ function parseGeminiSettings(root) {
21
+ const settingsPath = geminiSettingsPath(root);
22
+ try {
23
+ return (0, fileutils_1.readJsonFile)(settingsPath);
24
+ }
25
+ catch {
26
+ return undefined;
27
+ }
28
+ }
29
+ function geminiSettingsPath(root) {
30
+ return (0, path_1.join)(root, '.gemini', 'settings.json');
31
+ }
32
+ function claudeMdPath(root) {
33
+ return (0, path_1.join)(root, 'CLAUDE.md');
34
+ }
35
+ function claudeMcpPath(root) {
36
+ return (0, path_1.join)(root, '.mcp.json');
37
+ }
38
+ exports.codexConfigTomlPath = (0, path_1.join)((0, os_1.homedir)(), '.codex', 'config.toml');
39
+ exports.nxRulesMarkerCommentStart = `<!-- nx configuration start-->`;
40
+ exports.nxRulesMarkerCommentDescription = `<!-- Leave the start & end comments to automatically receive updates. -->`;
41
+ exports.nxRulesMarkerCommentEnd = `<!-- nx configuration end-->`;
42
+ exports.rulesRegex = new RegExp(`${exports.nxRulesMarkerCommentStart}[\\s\\S]*?${exports.nxRulesMarkerCommentEnd}`, 'm');
43
+ const getAgentRulesWrapped = (writeNxCloudRules) => {
44
+ const agentRulesString = (0, get_agent_rules_1.getAgentRules)(writeNxCloudRules);
45
+ return `${exports.nxRulesMarkerCommentStart}\n${exports.nxRulesMarkerCommentDescription}\n${agentRulesString}\n${exports.nxRulesMarkerCommentEnd}`;
46
+ };
47
+ exports.getAgentRulesWrapped = getAgentRulesWrapped;
48
+ exports.nxMcpTomlHeader = `[mcp_servers."nx-mcp"]`;
49
+ exports.nxMcpTomlConfig = `${exports.nxMcpTomlHeader}
50
+ type = "stdio"
51
+ command = "npx"
52
+ args = ["nx", "mcp"]
53
+ `;
@@ -2,6 +2,7 @@ export type SetupAiAgentsGeneratorSchema = {
2
2
  directory: string;
3
3
  writeNxCloudRules?: boolean;
4
4
  packageVersion?: string;
5
+ agents?: Agent[];
5
6
  };
6
7
 
7
8
  export type NormalizedSetupAiAgentsGeneratorSchema =
@@ -19,6 +19,15 @@
19
19
  "type": "string",
20
20
  "description": "The version of the package to use",
21
21
  "default": "latest"
22
+ },
23
+ "agents": {
24
+ "type": "array",
25
+ "description": "The agents to setup Nx configuration for.",
26
+ "items": {
27
+ "type": "string",
28
+ "enum": ["claude", "gemini", "codex", "cursor", "copilot"]
29
+ },
30
+ "default": ["claude", "gemini", "codex", "cursor", "copilot"]
22
31
  }
23
32
  },
24
33
  "required": ["directory"]
@@ -1,6 +1,11 @@
1
1
  import { Tree } from '../../generators/tree';
2
+ import { CLIErrorMessageConfig, CLINoteMessageConfig } from '../../utils/output';
2
3
  import { NormalizedSetupAiAgentsGeneratorSchema, SetupAiAgentsGeneratorSchema } from './schema';
3
- export declare function setupAiAgentsGenerator(tree: Tree, options: SetupAiAgentsGeneratorSchema, inner?: boolean): Promise<any>;
4
- export declare function setupAiAgentsGeneratorImpl(tree: Tree, options: NormalizedSetupAiAgentsGeneratorSchema): Promise<void>;
4
+ export type ModificationResults = {
5
+ messages: CLINoteMessageConfig[];
6
+ errors: CLIErrorMessageConfig[];
7
+ };
8
+ export declare function setupAiAgentsGenerator(tree: Tree, options: SetupAiAgentsGeneratorSchema, inner?: boolean): Promise<(check?: boolean) => Promise<ModificationResults>>;
9
+ export declare function setupAiAgentsGeneratorImpl(tree: Tree, options: NormalizedSetupAiAgentsGeneratorSchema): Promise<() => Promise<ModificationResults>>;
5
10
  export default setupAiAgentsGenerator;
6
11
  //# sourceMappingURL=set-up-ai-agents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"set-up-ai-agents.d.ts","sourceRoot":"","sources":["../../../../../../packages/nx/src/ai/set-up-ai-agents/set-up-ai-agents.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAK7C,OAAO,EACL,sCAAsC,EACtC,4BAA4B,EAC7B,MAAM,UAAU,CAAC;AAElB,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,4BAA4B,EACrC,KAAK,UAAQ,gBAoCd;AAYD,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,sCAAsC,iBAgChD;AAqBD,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"set-up-ai-agents.d.ts","sourceRoot":"","sources":["../../../../../../packages/nx/src/ai/set-up-ai-agents/set-up-ai-agents.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAQ7C,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAc5B,OAAO,EACL,sCAAsC,EACtC,4BAA4B,EAC7B,MAAM,UAAU,CAAC;AAElB,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,oBAAoB,EAAE,CAAC;IACjC,MAAM,EAAE,qBAAqB,EAAE,CAAC;CACjC,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,4BAA4B,EACrC,KAAK,UAAQ,GACZ,OAAO,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAmC5D;AAaD,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,sCAAsC,GAC9C,OAAO,CAAC,MAAM,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAkJ7C;AAwDD,eAAe,sBAAsB,CAAC"}
@@ -2,12 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setupAiAgentsGenerator = setupAiAgentsGenerator;
4
4
  exports.setupAiAgentsGeneratorImpl = setupAiAgentsGeneratorImpl;
5
+ const fs_1 = require("fs");
6
+ const os_1 = require("os");
5
7
  const path_1 = require("path");
6
8
  const format_changed_files_with_prettier_if_available_1 = require("../../generators/internal-utils/format-changed-files-with-prettier-if-available");
7
9
  const json_1 = require("../../generators/utils/json");
10
+ const native_1 = require("../../native");
8
11
  const package_json_1 = require("../../utils/package-json");
9
12
  const provenance_1 = require("../../utils/provenance");
10
- const get_agent_rules_1 = require("./get-agent-rules");
13
+ const constants_1 = require("../constants");
14
+ const utils_1 = require("../utils");
15
+ const constants_2 = require("../constants");
11
16
  async function setupAiAgentsGenerator(tree, options, inner = false) {
12
17
  const normalizedOptions = normalizeOptions(options);
13
18
  // Use environment variable to force local execution
@@ -32,35 +37,159 @@ function normalizeOptions(options) {
32
37
  directory: options.directory,
33
38
  writeNxCloudRules: options.writeNxCloudRules ?? false,
34
39
  packageVersion: options.packageVersion ?? 'latest',
40
+ agents: options.agents ?? [...utils_1.supportedAgents],
35
41
  };
36
42
  }
37
43
  async function setupAiAgentsGeneratorImpl(tree, options) {
38
- const claudePath = (0, path_1.join)(options.directory, 'CLAUDE.md');
39
- if (!tree.exists(claudePath)) {
40
- tree.write(claudePath, (0, get_agent_rules_1.getAgentRules)(options.writeNxCloudRules));
44
+ const hasAgent = (agent) => options.agents.includes(agent);
45
+ const agentsMd = (0, constants_1.agentsMdPath)(options.directory);
46
+ // write AGENTS.md for most agents
47
+ if (hasAgent('cursor') || hasAgent('copilot') || hasAgent('codex')) {
48
+ writeAgentRules(tree, agentsMd, options.writeNxCloudRules);
41
49
  }
42
- const agentsPath = (0, path_1.join)(options.directory, 'AGENTS.md');
43
- if (!tree.exists(agentsPath)) {
44
- tree.write(agentsPath, (0, get_agent_rules_1.getAgentRules)(options.writeNxCloudRules));
50
+ if (hasAgent('claude')) {
51
+ const claudePath = (0, path_1.join)(options.directory, 'CLAUDE.md');
52
+ writeAgentRules(tree, claudePath, options.writeNxCloudRules);
53
+ const mcpJsonPath = (0, path_1.join)(options.directory, '.mcp.json');
54
+ if (!tree.exists(mcpJsonPath)) {
55
+ (0, json_1.writeJson)(tree, mcpJsonPath, {});
56
+ }
57
+ (0, json_1.updateJson)(tree, mcpJsonPath, mcpConfigUpdater);
45
58
  }
46
- const mcpJsonPath = (0, path_1.join)(options.directory, '.mcp.json');
47
- if (!tree.exists(mcpJsonPath)) {
48
- (0, json_1.writeJson)(tree, mcpJsonPath, {});
59
+ if (hasAgent('gemini')) {
60
+ const geminiSettingsPath = (0, path_1.join)(options.directory, '.gemini', 'settings.json');
61
+ if (!tree.exists(geminiSettingsPath)) {
62
+ (0, json_1.writeJson)(tree, geminiSettingsPath, {});
63
+ }
64
+ (0, json_1.updateJson)(tree, geminiSettingsPath, mcpConfigUpdater);
65
+ const contextFileName = (0, json_1.readJson)(tree, geminiSettingsPath).contextFileName;
66
+ const geminiMd = (0, constants_1.geminiMdPath)(options.directory);
67
+ // Only set contextFileName to AGENTS.md if GEMINI.md doesn't exist already to preserve existing setups
68
+ if (!contextFileName && !tree.exists(geminiMd)) {
69
+ writeAgentRules(tree, agentsMd, options.writeNxCloudRules);
70
+ (0, json_1.updateJson)(tree, geminiSettingsPath, (json) => ({
71
+ ...json,
72
+ contextFileName: 'AGENTS.md',
73
+ }));
74
+ }
75
+ else {
76
+ writeAgentRules(tree, contextFileName ?? geminiMd, options.writeNxCloudRules);
77
+ }
49
78
  }
50
- (0, json_1.updateJson)(tree, mcpJsonPath, mcpConfigUpdater);
51
- const geminiPath = (0, path_1.join)(options.directory, '.gemini', 'settings.json');
52
- if (!tree.exists(geminiPath)) {
53
- (0, json_1.writeJson)(tree, geminiPath, {});
79
+ await (0, format_changed_files_with_prettier_if_available_1.formatChangedFilesWithPrettierIfAvailable)(tree);
80
+ // we use the check variable to determine if we should actually make changes or just report what would be changed
81
+ return async (check = false) => {
82
+ const messages = [];
83
+ const errors = [];
84
+ if (hasAgent('codex')) {
85
+ if ((0, fs_1.existsSync)(constants_1.codexConfigTomlPath)) {
86
+ const tomlContents = (0, fs_1.readFileSync)(constants_1.codexConfigTomlPath, 'utf-8');
87
+ if (!tomlContents.includes(constants_2.nxMcpTomlHeader)) {
88
+ if (!check) {
89
+ (0, fs_1.appendFileSync)(constants_1.codexConfigTomlPath, `\n${constants_2.nxMcpTomlConfig}`);
90
+ }
91
+ messages.push({
92
+ title: `Updated ${constants_1.codexConfigTomlPath} with nx-mcp server`,
93
+ });
94
+ }
95
+ }
96
+ else {
97
+ if (!check) {
98
+ (0, fs_1.mkdirSync)((0, path_1.join)((0, os_1.homedir)(), '.codex'), { recursive: true });
99
+ (0, fs_1.writeFileSync)(constants_1.codexConfigTomlPath, constants_2.nxMcpTomlConfig);
100
+ }
101
+ messages.push({
102
+ title: `Created ${constants_1.codexConfigTomlPath} with nx-mcp server`,
103
+ });
104
+ }
105
+ }
106
+ if (hasAgent('copilot')) {
107
+ try {
108
+ if ((0, native_1.isEditorInstalled)(0 /* SupportedEditor.VSCode */) &&
109
+ (0, native_1.canInstallNxConsoleForEditor)(0 /* SupportedEditor.VSCode */)) {
110
+ if (!check) {
111
+ (0, native_1.installNxConsoleForEditor)(0 /* SupportedEditor.VSCode */);
112
+ }
113
+ messages.push({
114
+ title: `Installed Nx Console for VSCode`,
115
+ });
116
+ }
117
+ }
118
+ catch (e) {
119
+ errors.push({
120
+ title: `Failed to install Nx Console for VSCode. Please install it manually.`,
121
+ bodyLines: [e.message],
122
+ });
123
+ }
124
+ try {
125
+ if ((0, native_1.isEditorInstalled)(1 /* SupportedEditor.VSCodeInsiders */) &&
126
+ (0, native_1.canInstallNxConsoleForEditor)(1 /* SupportedEditor.VSCodeInsiders */)) {
127
+ if (!check) {
128
+ (0, native_1.installNxConsoleForEditor)(1 /* SupportedEditor.VSCodeInsiders */);
129
+ }
130
+ messages.push({
131
+ title: `Installed Nx Console for VSCode Insiders`,
132
+ });
133
+ }
134
+ }
135
+ catch (e) {
136
+ errors.push({
137
+ title: `Failed to install Nx Console for VSCode Insiders. Please install it manually.`,
138
+ bodyLines: [e.message],
139
+ });
140
+ }
141
+ }
142
+ if (hasAgent('cursor')) {
143
+ try {
144
+ if ((0, native_1.isEditorInstalled)(2 /* SupportedEditor.Cursor */) &&
145
+ (0, native_1.canInstallNxConsoleForEditor)(2 /* SupportedEditor.Cursor */)) {
146
+ if (!check) {
147
+ (0, native_1.installNxConsoleForEditor)(2 /* SupportedEditor.Cursor */);
148
+ }
149
+ messages.push({
150
+ title: `Installed Nx Console for Cursor`,
151
+ });
152
+ }
153
+ }
154
+ catch (e) {
155
+ errors.push({
156
+ title: `Failed to install Nx Console for Cursor. Please install it manually.`,
157
+ bodyLines: [e.message],
158
+ });
159
+ }
160
+ }
161
+ return {
162
+ messages,
163
+ errors,
164
+ };
165
+ };
166
+ }
167
+ function writeAgentRules(tree, path, writeNxCloudRules) {
168
+ const expectedRules = (0, constants_2.getAgentRulesWrapped)(writeNxCloudRules);
169
+ if (!tree.exists(path)) {
170
+ tree.write(path, expectedRules);
171
+ return;
54
172
  }
55
- (0, json_1.updateJson)(tree, geminiPath, mcpConfigUpdater);
56
- // Only set contextFileName to AGENTS.md if GEMINI.md doesn't exist already to preserve existing setups
57
- if (!tree.exists((0, path_1.join)(options.directory, 'GEMINI.md'))) {
58
- (0, json_1.updateJson)(tree, geminiPath, (json) => ({
59
- ...json,
60
- contextFileName: 'AGENTS.md',
61
- }));
173
+ const existing = tree.read(path, 'utf-8');
174
+ const regex = constants_2.rulesRegex;
175
+ const existingNxConfiguration = existing.match(regex);
176
+ if (existingNxConfiguration) {
177
+ const contentOnly = (str) => str
178
+ .replace(constants_2.nxRulesMarkerCommentStart, '')
179
+ .replace(constants_2.nxRulesMarkerCommentEnd, '')
180
+ .replace(constants_2.nxRulesMarkerCommentDescription, '')
181
+ .replace(/\s/g, '');
182
+ // we don't want to make updates on whitespace-only changes
183
+ if (contentOnly(existingNxConfiguration[0]) === contentOnly(expectedRules)) {
184
+ return;
185
+ }
186
+ // otherwise replace the existing configuration
187
+ const updatedContent = existing.replace(regex, expectedRules);
188
+ tree.write(path, updatedContent);
189
+ }
190
+ else {
191
+ tree.write(path, existing + '\n\n' + expectedRules);
62
192
  }
63
- await (0, format_changed_files_with_prettier_if_available_1.formatChangedFilesWithPrettierIfAvailable)(tree);
64
193
  }
65
194
  function mcpConfigUpdater(existing) {
66
195
  if (existing.mcpServers) {
@@ -0,0 +1,20 @@
1
+ export declare const supportedAgents: readonly ["claude", "codex", "copilot", "cursor", "gemini"];
2
+ export type Agent = (typeof supportedAgents)[number];
3
+ export declare const agentDisplayMap: Record<Agent, string>;
4
+ export type AgentConfiguration = {
5
+ rules: boolean;
6
+ mcp: boolean;
7
+ rulesPath: string;
8
+ mcpPath: string | null;
9
+ outdated: boolean;
10
+ disabled?: boolean;
11
+ };
12
+ export declare function getAgentConfigurations(agentsToConsider: Agent[], workspaceRoot: string): Promise<{
13
+ nonConfiguredAgents: Agent[];
14
+ partiallyConfiguredAgents: Agent[];
15
+ fullyConfiguredAgents: Agent[];
16
+ disabledAgents: Agent[];
17
+ agentConfigurations: Map<Agent, AgentConfiguration>;
18
+ }>;
19
+ export declare function configureAgents(agents: Agent[], workspaceRoot: string, useLatest?: boolean): Promise<void>;
20
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/ai/utils.ts"],"names":[],"mappings":"AA0BA,eAAO,MAAM,eAAe,6DAMlB,CAAC;AACX,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AACrD,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAMjD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,gBAAgB,EAAE,KAAK,EAAE,EACzB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IACT,mBAAmB,EAAE,KAAK,EAAE,CAAC;IAC7B,yBAAyB,EAAE,KAAK,EAAE,CAAC;IACnC,qBAAqB,EAAE,KAAK,EAAE,CAAC;IAC/B,cAAc,EAAE,KAAK,EAAE,CAAC;IACxB,mBAAmB,EAAE,GAAG,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;CACrD,CAAC,CA8BD;AA8ID,wBAAsB,eAAe,CACnC,MAAM,EAAE,KAAK,EAAE,EACf,aAAa,EAAE,MAAM,EACrB,SAAS,CAAC,EAAE,OAAO,GAClB,OAAO,CAAC,IAAI,CAAC,CAoBf"}
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.agentDisplayMap = exports.supportedAgents = void 0;
4
+ exports.getAgentConfigurations = getAgentConfigurations;
5
+ exports.configureAgents = configureAgents;
6
+ const fs_1 = require("fs");
7
+ const path_1 = require("path");
8
+ const configuration_1 = require("../config/configuration");
9
+ const tree_1 = require("../generators/tree");
10
+ const native_1 = require("../native");
11
+ const fileutils_1 = require("../utils/fileutils");
12
+ const nx_cloud_utils_1 = require("../utils/nx-cloud-utils");
13
+ const output_1 = require("../utils/output");
14
+ const constants_1 = require("./constants");
15
+ const set_up_ai_agents_1 = require("./set-up-ai-agents/set-up-ai-agents");
16
+ // when adding new agents, be sure to also update the list in
17
+ // packages/create-nx-workspace/src/create-workspace-options.ts
18
+ exports.supportedAgents = [
19
+ 'claude',
20
+ 'codex',
21
+ 'copilot',
22
+ 'cursor',
23
+ 'gemini',
24
+ ];
25
+ exports.agentDisplayMap = {
26
+ claude: 'Claude Code',
27
+ gemini: 'Gemini',
28
+ codex: 'OpenAI Codex',
29
+ copilot: 'GitHub Copilot for VSCode',
30
+ cursor: 'Cursor',
31
+ };
32
+ async function getAgentConfigurations(agentsToConsider, workspaceRoot) {
33
+ const nonConfiguredAgents = [];
34
+ const partiallyConfiguredAgents = [];
35
+ const fullyConfiguredAgents = [];
36
+ const disabledAgents = [];
37
+ const agentConfigurations = new Map();
38
+ for (const agent of agentsToConsider) {
39
+ const configured = await getAgentConfiguration(agent, workspaceRoot);
40
+ if (configured.disabled) {
41
+ disabledAgents.push(agent);
42
+ continue;
43
+ }
44
+ agentConfigurations.set(agent, configured);
45
+ if (configured.mcp && configured.rules) {
46
+ fullyConfiguredAgents.push(agent);
47
+ }
48
+ else if (!configured.mcp && !configured.rules) {
49
+ nonConfiguredAgents.push(agent);
50
+ }
51
+ else {
52
+ partiallyConfiguredAgents.push(agent);
53
+ }
54
+ }
55
+ return {
56
+ nonConfiguredAgents,
57
+ partiallyConfiguredAgents,
58
+ fullyConfiguredAgents,
59
+ disabledAgents,
60
+ agentConfigurations,
61
+ };
62
+ }
63
+ async function getAgentConfiguration(agent, workspaceRoot) {
64
+ let agentConfiguration;
65
+ switch (agent) {
66
+ case 'claude': {
67
+ const mcpPath = (0, constants_1.claudeMcpPath)(workspaceRoot);
68
+ let mcpConfigured;
69
+ try {
70
+ const mcpContents = (0, fileutils_1.readJsonFile)(mcpPath);
71
+ mcpConfigured = !!mcpContents?.['mcpServers']?.['nx-mcp'];
72
+ }
73
+ catch {
74
+ mcpConfigured = false;
75
+ }
76
+ const rulesPath = (0, constants_1.claudeMdPath)(workspaceRoot);
77
+ const rulesExists = (0, fs_1.existsSync)(rulesPath);
78
+ agentConfiguration = {
79
+ rules: rulesExists,
80
+ mcp: mcpConfigured,
81
+ rulesPath: rulesPath,
82
+ mcpPath: mcpPath,
83
+ };
84
+ break;
85
+ }
86
+ case 'gemini': {
87
+ const geminiRulePath = (0, constants_1.geminiMdPath)(workspaceRoot);
88
+ const geminiMdExists = (0, fs_1.existsSync)(geminiRulePath);
89
+ const settingsPath = (0, constants_1.geminiSettingsPath)(workspaceRoot);
90
+ let mcpConfigured;
91
+ const geminiSettings = (0, constants_1.parseGeminiSettings)(workspaceRoot);
92
+ const customContextFilePath = geminiSettings?.contextFileName;
93
+ const customContextFilePathExists = customContextFilePath
94
+ ? (0, fs_1.existsSync)((0, path_1.resolve)(workspaceRoot, customContextFilePath))
95
+ : false;
96
+ mcpConfigured = geminiSettings?.['mcpServers']?.['nx-mcp'];
97
+ agentConfiguration = {
98
+ rules: (!customContextFilePath && geminiMdExists) ||
99
+ (customContextFilePath && customContextFilePathExists),
100
+ mcp: mcpConfigured,
101
+ rulesPath: customContextFilePath ?? geminiRulePath,
102
+ mcpPath: settingsPath,
103
+ };
104
+ break;
105
+ }
106
+ case 'copilot': {
107
+ const rulesPath = (0, constants_1.agentsMdPath)(workspaceRoot);
108
+ const hasInstalledVSCode = (0, native_1.isEditorInstalled)(0 /* SupportedEditor.VSCode */);
109
+ const hasInstalledVSCodeInsiders = (0, native_1.isEditorInstalled)(1 /* SupportedEditor.VSCodeInsiders */);
110
+ const hasInstalledNxConsoleForVSCode = hasInstalledVSCode &&
111
+ !(0, native_1.canInstallNxConsoleForEditor)(0 /* SupportedEditor.VSCode */);
112
+ const hasInstalledNxConsoleForVSCodeInsiders = hasInstalledVSCodeInsiders &&
113
+ !(0, native_1.canInstallNxConsoleForEditor)(1 /* SupportedEditor.VSCodeInsiders */);
114
+ const agentsMdExists = (0, fs_1.existsSync)(rulesPath);
115
+ agentConfiguration = {
116
+ mcp: hasInstalledNxConsoleForVSCode ||
117
+ hasInstalledNxConsoleForVSCodeInsiders,
118
+ rules: agentsMdExists,
119
+ rulesPath,
120
+ mcpPath: null,
121
+ disabled: !hasInstalledVSCode && !hasInstalledVSCodeInsiders,
122
+ };
123
+ break;
124
+ }
125
+ case 'cursor': {
126
+ const rulesPath = (0, constants_1.agentsMdPath)(workspaceRoot);
127
+ const hasInstalledCursor = (0, native_1.isEditorInstalled)(2 /* SupportedEditor.Cursor */);
128
+ const hasInstalledNxConsole = !(0, native_1.canInstallNxConsoleForEditor)(2 /* SupportedEditor.Cursor */);
129
+ const agentsMdExists = (0, fs_1.existsSync)(rulesPath);
130
+ agentConfiguration = {
131
+ mcp: hasInstalledCursor ? hasInstalledNxConsole : false,
132
+ rules: agentsMdExists,
133
+ rulesPath,
134
+ mcpPath: null,
135
+ disabled: !hasInstalledCursor,
136
+ };
137
+ break;
138
+ }
139
+ case 'codex': {
140
+ const rulesPath = (0, constants_1.agentsMdPath)(workspaceRoot);
141
+ const agentsMdExists = (0, fs_1.existsSync)(rulesPath);
142
+ let mcpConfigured;
143
+ if ((0, fs_1.existsSync)(constants_1.codexConfigTomlPath)) {
144
+ const tomlContents = (0, fs_1.readFileSync)(constants_1.codexConfigTomlPath, 'utf-8');
145
+ mcpConfigured = tomlContents.includes(constants_1.nxMcpTomlHeader);
146
+ }
147
+ else {
148
+ mcpConfigured = false;
149
+ }
150
+ agentConfiguration = {
151
+ mcp: mcpConfigured,
152
+ rules: agentsMdExists,
153
+ rulesPath,
154
+ mcpPath: constants_1.codexConfigTomlPath,
155
+ };
156
+ break;
157
+ }
158
+ }
159
+ return {
160
+ ...agentConfiguration,
161
+ outdated: await isAgentOutdated(agent, workspaceRoot),
162
+ };
163
+ }
164
+ async function isAgentOutdated(agent, workspaceRoot) {
165
+ const tree = new tree_1.FsTree(workspaceRoot, false);
166
+ const callback = await (0, set_up_ai_agents_1.default)(tree, {
167
+ directory: '.',
168
+ agents: [agent],
169
+ writeNxCloudRules: (0, nx_cloud_utils_1.isNxCloudUsed)((0, configuration_1.readNxJson)()),
170
+ }, true);
171
+ const modificationResults = await callback(true);
172
+ return (tree.listChanges().length > 0 || modificationResults.messages.length > 0);
173
+ }
174
+ async function configureAgents(agents, workspaceRoot, useLatest) {
175
+ const writeNxCloudRules = (0, nx_cloud_utils_1.isNxCloudUsed)((0, configuration_1.readNxJson)());
176
+ const tree = new tree_1.FsTree(workspaceRoot, false);
177
+ const callback = await (0, set_up_ai_agents_1.default)(tree, {
178
+ directory: '.',
179
+ agents,
180
+ writeNxCloudRules,
181
+ }, !useLatest);
182
+ // changes that are out of scope for the generator itself because they do more than modify the tree
183
+ (0, tree_1.flushChanges)(workspaceRoot, tree.listChanges());
184
+ const modificationResults = await callback();
185
+ modificationResults.messages.forEach((message) => output_1.output.log(message));
186
+ modificationResults.errors.forEach((error) => output_1.output.error(error));
187
+ }
@@ -0,0 +1,9 @@
1
+ import { CommandModule } from 'yargs';
2
+ export interface ConfigureAiAgentsOptions {
3
+ agents?: string[];
4
+ interactive?: boolean;
5
+ verbose?: boolean;
6
+ check?: boolean;
7
+ }
8
+ export declare const yargsConfigureAiAgentsCommand: CommandModule<{}, ConfigureAiAgentsOptions>;
9
+ //# sourceMappingURL=command-object.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-object.d.ts","sourceRoot":"","sources":["../../../../../../packages/nx/src/command-line/configure-ai-agents/command-object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGtC,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,6BAA6B,EAAE,aAAa,CACvD,EAAE,EACF,wBAAwB,CA6CzB,CAAC"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.yargsConfigureAiAgentsCommand = void 0;
4
+ const shared_options_1 = require("../yargs-utils/shared-options");
5
+ exports.yargsConfigureAiAgentsCommand = {
6
+ command: 'configure-ai-agents',
7
+ describe: 'Configure and update AI agent configurations for your workspace.',
8
+ builder: (yargs) => (0, shared_options_1.withVerbose)(yargs)
9
+ .option('agents', {
10
+ type: 'array',
11
+ string: true,
12
+ description: 'List of AI agents to set up.',
13
+ choices: ['claude', 'codex', 'copilot', 'cursor', 'gemini'],
14
+ })
15
+ .option('interactive', {
16
+ type: 'boolean',
17
+ description: 'When false disables interactive input prompts for options.',
18
+ default: true,
19
+ })
20
+ .option('check', {
21
+ type: 'boolean',
22
+ description: 'Check if any configured agents are out of date and need to be updated. Does not make any changes.',
23
+ default: false,
24
+ })
25
+ .example('$0 configure-ai-agents', 'Interactively select AI agents to update and configure')
26
+ .example('$0 configure-ai-agents --agents claude gemini', 'Prompts for updates and and configuration of Claude and Gemini AI agents')
27
+ .example('$0 configure-ai-agents --check', 'Checks if any configured agents are out of date and need to be updated')
28
+ .example('$0 configure-ai-agents --agents claude gemini --no-interactive', 'Configures and updates Claude and Gemini AI agents without prompts'),
29
+ handler: async (args) => {
30
+ await (await Promise.resolve().then(() => require('./configure-ai-agents'))).configureAiAgentsHandler(args);
31
+ },
32
+ };
@@ -0,0 +1,4 @@
1
+ import { ConfigureAiAgentsOptions } from './command-object';
2
+ export declare function configureAiAgentsHandler(args: ConfigureAiAgentsOptions, inner?: boolean): Promise<void>;
3
+ export declare function configureAiAgentsHandlerImpl(options: ConfigureAiAgentsOptions): Promise<void>;
4
+ //# sourceMappingURL=configure-ai-agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure-ai-agents.d.ts","sourceRoot":"","sources":["../../../../../../packages/nx/src/command-line/configure-ai-agents/configure-ai-agents.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAI5D,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,wBAAwB,EAC9B,KAAK,UAAQ,GACZ,OAAO,CAAC,IAAI,CAAC,CA+Bf;AAED,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,IAAI,CAAC,CAkMf"}