nx 23.2.0-beta.10 → 23.2.0-beta.12
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/README.md +2 -2
- package/dist/src/ai/constants.d.ts +15 -0
- package/dist/src/ai/constants.js +17 -1
- package/dist/src/ai/set-up-ai-agents/set-up-ai-agents.js +44 -16
- package/dist/src/ai/utils.d.ts +13 -0
- package/dist/src/ai/utils.js +29 -0
- package/dist/src/command-line/configure-ai-agents/configure-ai-agents.js +25 -8
- package/dist/src/command-line/init/implementation/utils.js +0 -8
- package/dist/src/command-line/init/init-v2.js +41 -14
- package/dist/src/command-line/reset/reset.js +17 -15
- package/dist/src/core/graph/main.js +1 -1
- package/dist/src/daemon/client/client.d.ts +0 -7
- package/dist/src/daemon/client/client.js +41 -22
- package/dist/src/daemon/client/daemon-environment.d.ts +32 -0
- package/dist/src/daemon/client/daemon-environment.js +95 -6
- package/dist/src/daemon/message-types/daemon-message.d.ts +2 -1
- package/dist/src/daemon/message-types/daemon-message.js +25 -2
- package/dist/src/daemon/sandbox-socket-hint.d.ts +27 -0
- package/dist/src/daemon/sandbox-socket-hint.js +136 -0
- package/dist/src/daemon/server/dotenv-graph-changes.d.ts +97 -0
- package/dist/src/daemon/server/dotenv-graph-changes.js +284 -0
- package/dist/src/daemon/server/handle-client-env.d.ts +8 -0
- package/dist/src/daemon/server/handle-client-env.js +92 -0
- package/dist/src/daemon/server/handle-outputs-changes.d.ts +10 -0
- package/dist/src/daemon/server/handle-outputs-changes.js +86 -0
- package/dist/src/daemon/server/project-graph-incremental-recomputation.d.ts +21 -0
- package/dist/src/daemon/server/project-graph-incremental-recomputation.js +159 -6
- package/dist/src/daemon/server/server.js +19 -48
- package/dist/src/daemon/tmp-dir.d.ts +10 -0
- package/dist/src/daemon/tmp-dir.js +21 -37
- package/dist/src/devkit-internals.d.ts +6 -2
- package/dist/src/devkit-internals.js +19 -4
- package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
- package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
- package/dist/src/plugins/js/utils/register.d.ts +11 -0
- package/dist/src/plugins/js/utils/register.js +40 -6
- package/dist/src/project-graph/plugins/get-plugins.d.ts +27 -1
- package/dist/src/project-graph/plugins/get-plugins.js +110 -5
- package/dist/src/project-graph/plugins/isolation/enabled.js +1 -4
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +16 -0
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +47 -3
- package/dist/src/project-graph/plugins/isolation/plugin-worker.js +14 -1
- package/dist/src/project-graph/project-graph.js +27 -2
- package/dist/src/project-graph/utils/project-configuration/target-defaults.js +47 -21
- package/dist/src/tasks-runner/run-command.js +3 -3
- package/dist/src/tasks-runner/task-env.d.ts +25 -0
- package/dist/src/tasks-runner/task-env.js +39 -0
- package/dist/src/utils/cache-directory.d.ts +62 -3
- package/dist/src/utils/cache-directory.js +276 -25
- package/dist/src/utils/db-connection.js +8 -16
- package/dist/src/utils/git-utils.d.ts +4 -0
- package/dist/src/utils/git-utils.js +248 -11
- package/dist/src/utils/has-nx-js-plugin.d.ts +1 -1
- package/dist/src/utils/has-nx-js-plugin.js +1 -1
- package/dist/src/utils/kill-child-on-host-exit.d.ts +7 -0
- package/dist/src/utils/kill-child-on-host-exit.js +42 -0
- package/dist/src/utils/nx-tmp-dir.d.ts +5 -0
- package/dist/src/utils/nx-tmp-dir.js +7 -2
- package/dist/src/utils/owned-private-dir.d.ts +13 -0
- package/dist/src/utils/owned-private-dir.js +39 -0
- package/dist/src/utils/permission-errors.d.ts +11 -0
- package/dist/src/utils/permission-errors.js +17 -0
- package/dist/src/utils/socket-refused-exit-code.d.ts +15 -0
- package/dist/src/utils/socket-refused-exit-code.js +18 -0
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
<div style="text-align: center;">
|
|
9
9
|
|
|
10
|
-
[]()
|
|
10
|
+
[](<>)
|
|
11
11
|
[](https://www.npmjs.com/package/nx)
|
|
12
|
-
[]()
|
|
12
|
+
[](<>)
|
|
13
13
|
[](http://commitizen.github.io/cz-cli/)
|
|
14
14
|
[](https://go.nx.dev/community)
|
|
15
15
|
[](https://nx.dev/docs/features/ci-features/sandboxing)
|
|
@@ -29,3 +29,18 @@ export declare const nxMcpTomlHeader = "[mcp_servers.\"nx-mcp\"]";
|
|
|
29
29
|
* For Nx < 22, uses 'nx-mcp'
|
|
30
30
|
*/
|
|
31
31
|
export declare function getNxMcpTomlConfig(nxVersion: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* The Nx runtime roots as they belong in a *committed* sandbox allowlist.
|
|
34
|
+
*
|
|
35
|
+
* `~/.nx` is the literal tilde rather than an expanded `NX_HOME_TMP_DIR`: the
|
|
36
|
+
* sandbox expands it per user, which is the property that makes the entry worth
|
|
37
|
+
* committing at all. An absolute home would pin the file to whoever ran the
|
|
38
|
+
* generator.
|
|
39
|
+
*
|
|
40
|
+
* Both are listed because socket resolution walks a chain — `/tmp/.nx` first,
|
|
41
|
+
* `~/.nx` when a peer already owns the shared container. Allowing only the first
|
|
42
|
+
* leaves every user on a machine where someone else got there first silently
|
|
43
|
+
* uncovered. Windows resolves `NX_TMP_DIR` to a machine-specific `%TMP%` and has
|
|
44
|
+
* no sandbox to configure, so the POSIX root is the one that belongs here.
|
|
45
|
+
*/
|
|
46
|
+
export declare const NX_ALLOWLIST_ROOTS: readonly ["/tmp/.nx", '~/.nx'];
|
package/dist/src/ai/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.nxMcpTomlHeader = exports.analyticsDomain = exports.getAgentRulesWrapped = exports.rulesRegex = exports.nxRulesMarkerCommentEnd = exports.nxRulesMarkerCommentDescription = exports.nxRulesMarkerCommentStart = void 0;
|
|
3
|
+
exports.NX_ALLOWLIST_ROOTS = exports.nxMcpTomlHeader = exports.analyticsDomain = exports.getAgentRulesWrapped = exports.rulesRegex = exports.nxRulesMarkerCommentEnd = exports.nxRulesMarkerCommentDescription = exports.nxRulesMarkerCommentStart = void 0;
|
|
4
4
|
exports.agentsMdPath = agentsMdPath;
|
|
5
5
|
exports.geminiMdPath = geminiMdPath;
|
|
6
6
|
exports.parseGeminiSettings = parseGeminiSettings;
|
|
@@ -13,6 +13,7 @@ exports.getNxMcpTomlConfig = getNxMcpTomlConfig;
|
|
|
13
13
|
const path_1 = require("path");
|
|
14
14
|
const semver_1 = require("semver");
|
|
15
15
|
const fileutils_1 = require("../utils/fileutils");
|
|
16
|
+
const nx_tmp_dir_1 = require("../utils/nx-tmp-dir");
|
|
16
17
|
const get_agent_rules_1 = require("./set-up-ai-agents/get-agent-rules");
|
|
17
18
|
function agentsMdPath(root) {
|
|
18
19
|
return (0, path_1.join)(root, 'AGENTS.md');
|
|
@@ -74,3 +75,18 @@ command = "npx"
|
|
|
74
75
|
args = ${args}
|
|
75
76
|
`;
|
|
76
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* The Nx runtime roots as they belong in a *committed* sandbox allowlist.
|
|
80
|
+
*
|
|
81
|
+
* `~/.nx` is the literal tilde rather than an expanded `NX_HOME_TMP_DIR`: the
|
|
82
|
+
* sandbox expands it per user, which is the property that makes the entry worth
|
|
83
|
+
* committing at all. An absolute home would pin the file to whoever ran the
|
|
84
|
+
* generator.
|
|
85
|
+
*
|
|
86
|
+
* Both are listed because socket resolution walks a chain — `/tmp/.nx` first,
|
|
87
|
+
* `~/.nx` when a peer already owns the shared container. Allowing only the first
|
|
88
|
+
* leaves every user on a machine where someone else got there first silently
|
|
89
|
+
* uncovered. Windows resolves `NX_TMP_DIR` to a machine-specific `%TMP%` and has
|
|
90
|
+
* no sandbox to configure, so the POSIX root is the one that belongs here.
|
|
91
|
+
*/
|
|
92
|
+
exports.NX_ALLOWLIST_ROOTS = [nx_tmp_dir_1.NX_TMP_DIR_POSIX, '~/.nx'];
|
|
@@ -110,11 +110,43 @@ async function setupAiAgentsGeneratorImpl(tree, options) {
|
|
|
110
110
|
...json.enabledPlugins,
|
|
111
111
|
'nx@nx-claude-plugins': true,
|
|
112
112
|
},
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
// Allow Nx unix socket usage (daemon, plugin workers, forked processes)
|
|
114
|
+
// through Claude Code's sandbox, and analytics requests when the
|
|
115
|
+
// workspace has them on. Nx also copies its native binary into a cache
|
|
116
|
+
// under the same fixed tmp root before loading it, so the read/write
|
|
117
|
+
// grants cover that too. The root is a fixed /tmp path on macOS and
|
|
118
|
+
// Linux, so these entries are machine-independent and safe to commit.
|
|
119
|
+
sandbox: {
|
|
120
|
+
...json.sandbox,
|
|
121
|
+
filesystem: {
|
|
122
|
+
...json.sandbox?.filesystem,
|
|
123
|
+
allowRead: withEntries(json.sandbox?.filesystem?.allowRead, ...constants_1.NX_ALLOWLIST_ROOTS),
|
|
124
|
+
// Covers the whole tmp root, not just the socket dir: the native
|
|
125
|
+
// binary cache lives under it too, and without the cache a running
|
|
126
|
+
// daemon keeps an open handle on the binding inside node_modules,
|
|
127
|
+
// which blocks reinstalling or rebuilding dependencies. What keeps
|
|
128
|
+
// users apart is not this allowlist but the 0700 per-uid directories
|
|
129
|
+
// Nx verifies on every use (see ensureOwnedPrivateDir).
|
|
130
|
+
allowWrite: withEntries(json.sandbox?.filesystem?.allowWrite, ...constants_1.NX_ALLOWLIST_ROOTS),
|
|
131
|
+
},
|
|
132
|
+
network: {
|
|
133
|
+
...json.sandbox?.network,
|
|
134
|
+
// Egress follows the workspace's analytics opt-in (#36663). The
|
|
135
|
+
// socket grant does not: Nx needs its sockets either way.
|
|
136
|
+
...(analyticsEnabled
|
|
137
|
+
? {
|
|
138
|
+
allowedDomains: withEntries(json.sandbox?.network?.allowedDomains, constants_1.analyticsDomain),
|
|
139
|
+
}
|
|
140
|
+
: {}),
|
|
141
|
+
// Covers binding as well as connecting, so a fresh daemon, a plugin
|
|
142
|
+
// worker and a forked task can each create their own socket under
|
|
143
|
+
// these roots. Deliberately scoped rather than `allowAllUnixSockets`,
|
|
144
|
+
// which grants connect access to every socket on the machine —
|
|
145
|
+
// including the Docker and SSH-agent sockets — and grants nothing
|
|
146
|
+
// extra for creating Nx's own.
|
|
147
|
+
allowUnixSockets: withEntries(json.sandbox?.network?.allowUnixSockets, ...constants_1.NX_ALLOWLIST_ROOTS),
|
|
148
|
+
},
|
|
149
|
+
},
|
|
118
150
|
}));
|
|
119
151
|
// Clean up .mcp.json (nx-mcp now handled by plugin)
|
|
120
152
|
const mcpJsonPath = (0, constants_1.claudeMcpJsonPath)(options.directory);
|
|
@@ -308,17 +340,13 @@ async function setupAiAgentsGeneratorImpl(tree, options) {
|
|
|
308
340
|
};
|
|
309
341
|
};
|
|
310
342
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
? allowedDomains
|
|
319
|
-
: [...allowedDomains, constants_1.analyticsDomain],
|
|
320
|
-
},
|
|
321
|
-
};
|
|
343
|
+
/**
|
|
344
|
+
* The user's existing entries in their original order, plus any of `values`
|
|
345
|
+
* they do not already have. A Set does the deduping, so re-running the
|
|
346
|
+
* generator is a no-op rather than a growing list.
|
|
347
|
+
*/
|
|
348
|
+
function withEntries(existing, ...values) {
|
|
349
|
+
return [...new Set([...(existing ?? []), ...values])];
|
|
322
350
|
}
|
|
323
351
|
function writeAgentRules(tree, path, writeNxCloudRules) {
|
|
324
352
|
if (!tree.exists(path)) {
|
package/dist/src/ai/utils.d.ts
CHANGED
|
@@ -18,3 +18,16 @@ export declare function getAgentConfigurations(agentsToConsider: Agent[], worksp
|
|
|
18
18
|
disabledAgents: AgentConfiguration[];
|
|
19
19
|
}>;
|
|
20
20
|
export declare function configureAgents(agents: Agent[], workspaceRoot: string, useLatest?: boolean): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Explains a permission error thrown while writing agent configuration files.
|
|
23
|
+
*
|
|
24
|
+
* The errno alone does not identify the cause. Agent harnesses (e.g. Claude
|
|
25
|
+
* Code) deny writes to their own settings files from sandboxed shell commands,
|
|
26
|
+
* so `nx configure-ai-agents` run through an agent's bash tool fails with EPERM
|
|
27
|
+
* where the same command succeeds in a terminal — but a root-owned
|
|
28
|
+
* `.claude/settings.json` left by an earlier `sudo nx`, or a read-only
|
|
29
|
+
* checkout, produces the same errno with an unrelated remedy. The sandbox
|
|
30
|
+
* explanation is therefore only offered where a sandbox or an agent is
|
|
31
|
+
* actually detected, and the underlying message is kept either way.
|
|
32
|
+
*/
|
|
33
|
+
export declare function agentConfigWriteBlockedLines(error: unknown): string[];
|
package/dist/src/ai/utils.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.agentDisplayMap = exports.supportedAgents = void 0;
|
|
4
4
|
exports.getAgentConfigurations = getAgentConfigurations;
|
|
5
5
|
exports.configureAgents = configureAgents;
|
|
6
|
+
exports.agentConfigWriteBlockedLines = agentConfigWriteBlockedLines;
|
|
6
7
|
const tslib_1 = require("tslib");
|
|
7
8
|
const fs_1 = require("fs");
|
|
8
9
|
const path_1 = require("path");
|
|
@@ -10,6 +11,7 @@ const configuration_1 = require("../config/configuration");
|
|
|
10
11
|
const tree_1 = require("../generators/tree");
|
|
11
12
|
const native_1 = require("../native");
|
|
12
13
|
const fileutils_1 = require("../utils/fileutils");
|
|
14
|
+
const is_sandbox_1 = require("../utils/is-sandbox");
|
|
13
15
|
const nx_cloud_utils_1 = require("../utils/nx-cloud-utils");
|
|
14
16
|
const output_1 = require("../utils/output");
|
|
15
17
|
const constants_1 = require("./constants");
|
|
@@ -215,3 +217,30 @@ async function configureAgents(agents, workspaceRoot, useLatest) {
|
|
|
215
217
|
modificationResults.messages.forEach((message) => output_1.output.log(message));
|
|
216
218
|
modificationResults.errors.forEach((error) => output_1.output.error(error));
|
|
217
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Explains a permission error thrown while writing agent configuration files.
|
|
222
|
+
*
|
|
223
|
+
* The errno alone does not identify the cause. Agent harnesses (e.g. Claude
|
|
224
|
+
* Code) deny writes to their own settings files from sandboxed shell commands,
|
|
225
|
+
* so `nx configure-ai-agents` run through an agent's bash tool fails with EPERM
|
|
226
|
+
* where the same command succeeds in a terminal — but a root-owned
|
|
227
|
+
* `.claude/settings.json` left by an earlier `sudo nx`, or a read-only
|
|
228
|
+
* checkout, produces the same errno with an unrelated remedy. The sandbox
|
|
229
|
+
* explanation is therefore only offered where a sandbox or an agent is
|
|
230
|
+
* actually detected, and the underlying message is kept either way.
|
|
231
|
+
*/
|
|
232
|
+
function agentConfigWriteBlockedLines(error) {
|
|
233
|
+
const err = error;
|
|
234
|
+
const target = err?.path ?? 'an agent configuration file';
|
|
235
|
+
return [
|
|
236
|
+
`Writing ${target} failed: ${err?.message ?? 'permission denied'}`,
|
|
237
|
+
...((0, is_sandbox_1.isSandbox)() || (0, native_1.isAiAgent)()
|
|
238
|
+
? [
|
|
239
|
+
"Agent sandboxes protect their own settings files from writes made by sandboxed shell commands, so this command cannot finish when run through an agent's bash tool.",
|
|
240
|
+
'To complete the AI agent setup, run `nx configure-ai-agents` from a regular terminal and relaunch the agent harness.',
|
|
241
|
+
]
|
|
242
|
+
: [
|
|
243
|
+
'Check the ownership and mode of that path: an earlier `sudo nx` run or a read-only checkout produces this.',
|
|
244
|
+
]),
|
|
245
|
+
];
|
|
246
|
+
}
|
|
@@ -10,6 +10,7 @@ const pc = tslib_1.__importStar(require("picocolors"));
|
|
|
10
10
|
const constants_1 = require("../../ai/constants");
|
|
11
11
|
const detect_ai_agent_1 = require("../../ai/detect-ai-agent");
|
|
12
12
|
const utils_1 = require("../../ai/utils");
|
|
13
|
+
const permission_errors_1 = require("../../utils/permission-errors");
|
|
13
14
|
const client_1 = require("../../daemon/client/client");
|
|
14
15
|
const package_json_1 = require("../../utils/package-json");
|
|
15
16
|
const output_1 = require("../../utils/output");
|
|
@@ -214,10 +215,18 @@ async function configureAiAgentsHandlerImpl(options) {
|
|
|
214
215
|
}
|
|
215
216
|
catch (e) {
|
|
216
217
|
configSpinner.fail('Failed to configure AI agents');
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
218
|
+
if ((0, permission_errors_1.isPermissionDenied)(e)) {
|
|
219
|
+
output_1.output.error({
|
|
220
|
+
title: 'Nx was not permitted to write the AI agent configuration',
|
|
221
|
+
bodyLines: (0, utils_1.agentConfigWriteBlockedLines)(e),
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
output_1.output.error({
|
|
226
|
+
title: 'Error details:',
|
|
227
|
+
bodyLines: [e.message],
|
|
228
|
+
});
|
|
229
|
+
}
|
|
221
230
|
process.exit(1);
|
|
222
231
|
}
|
|
223
232
|
}
|
|
@@ -310,10 +319,18 @@ async function configureAiAgentsHandlerImpl(options) {
|
|
|
310
319
|
}
|
|
311
320
|
catch (e) {
|
|
312
321
|
configSpinner.fail('Failed to set up AI agents');
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
322
|
+
if ((0, permission_errors_1.isPermissionDenied)(e)) {
|
|
323
|
+
output_1.output.error({
|
|
324
|
+
title: 'Nx was not permitted to write the AI agent configuration',
|
|
325
|
+
bodyLines: (0, utils_1.agentConfigWriteBlockedLines)(e),
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
output_1.output.error({
|
|
330
|
+
title: 'Error details:',
|
|
331
|
+
bodyLines: [e.message],
|
|
332
|
+
});
|
|
333
|
+
}
|
|
317
334
|
process.exit(1);
|
|
318
335
|
}
|
|
319
336
|
}
|
|
@@ -196,14 +196,6 @@ function createNxJsonFromTurboJson(turboJson) {
|
|
|
196
196
|
nxJson.targetDefaults = targetDefaults;
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
|
-
/**
|
|
200
|
-
* The fact that cacheDir was in use suggests the user had a reason for deviating from the default.
|
|
201
|
-
* We can't know what that reason was, nor if it would still be applicable in Nx, but we can at least
|
|
202
|
-
* improve discoverability of the relevant Nx option by explicitly including it with its default value.
|
|
203
|
-
*/
|
|
204
|
-
if (turboJson.cacheDir) {
|
|
205
|
-
nxJson.cacheDirectory = '.nx/cache';
|
|
206
|
-
}
|
|
207
199
|
const defaultBase = (0, deduce_default_base_1.deduceDefaultBase)();
|
|
208
200
|
// Do not add defaultBase if it is inferred to be the Nx default value of main
|
|
209
201
|
if (defaultBase !== 'main') {
|
|
@@ -30,11 +30,14 @@ const utils_1 = require("./implementation/utils");
|
|
|
30
30
|
const provenance_1 = require("../../utils/provenance");
|
|
31
31
|
const handle_import_1 = require("../../utils/handle-import");
|
|
32
32
|
const native_1 = require("../../native");
|
|
33
|
+
const utils_2 = require("../../ai/utils");
|
|
34
|
+
const permission_errors_1 = require("../../utils/permission-errors");
|
|
33
35
|
const detect_ai_agent_1 = require("../../ai/detect-ai-agent");
|
|
34
36
|
const ab_testing_1 = require("../../utils/ab-testing");
|
|
35
37
|
const analytics_prompt_1 = require("../../utils/analytics-prompt");
|
|
36
38
|
const is_ci_1 = require("../../utils/is-ci");
|
|
37
39
|
const ai_output_1 = require("./utils/ai-output");
|
|
40
|
+
const is_sandbox_1 = require("../../utils/is-sandbox");
|
|
38
41
|
async function initHandler(options, inner = false) {
|
|
39
42
|
// Use environment variable to force local execution
|
|
40
43
|
if (process.env.NX_USE_LOCAL === 'true' || inner) {
|
|
@@ -119,8 +122,15 @@ async function runInit(options, baseMeta) {
|
|
|
119
122
|
}
|
|
120
123
|
// AI agent mode: apply defaults for non-interactive operation
|
|
121
124
|
const aiMode = (0, native_1.isAiAgent)();
|
|
125
|
+
const isSandboxed = (0, is_sandbox_1.isSandbox)();
|
|
122
126
|
if (aiMode) {
|
|
123
127
|
options.interactive = false; // Force non-interactive
|
|
128
|
+
if (isSandboxed) {
|
|
129
|
+
// During init, before configuring AI agents, the daemon and
|
|
130
|
+
// plugin socket connections are not available
|
|
131
|
+
process.env.NX_DAEMON = 'false';
|
|
132
|
+
process.env.NX_ISOLATE_PLUGINS = 'false';
|
|
133
|
+
}
|
|
124
134
|
if (options.nxCloud === undefined) {
|
|
125
135
|
options.nxCloud = false; // Default to skip Nx Cloud
|
|
126
136
|
}
|
|
@@ -320,21 +330,38 @@ async function runInit(options, baseMeta) {
|
|
|
320
330
|
await (0, configure_plugins_1.configurePlugins)(pluginsToInstall, updatePackageScripts, pmc, repoRoot, options.verbose);
|
|
321
331
|
}
|
|
322
332
|
}
|
|
323
|
-
|
|
333
|
+
// AI agent mode configures the detected agent automatically (aiAgents is
|
|
334
|
+
// pre-filled above); interactive humans are always prompted — even in the
|
|
335
|
+
// minimum setup — since agent configuration also writes the sandbox
|
|
336
|
+
// allowances the Nx daemon needs when driven by an agent later.
|
|
337
|
+
const selectedAgents = await (0, ai_agent_prompts_1.determineAiAgents)(options.aiAgents, options.interactive);
|
|
324
338
|
if (selectedAgents && selectedAgents.length > 0) {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
339
|
+
try {
|
|
340
|
+
const tree = new tree_1.FsTree(repoRoot, false);
|
|
341
|
+
const aiAgentsCallback = await (0, set_up_ai_agents_1.setupAiAgentsGenerator)(tree, {
|
|
342
|
+
directory: '.',
|
|
343
|
+
writeNxCloudRules: options.nxCloud !== false,
|
|
344
|
+
packageVersion: 'latest',
|
|
345
|
+
agents: [...selectedAgents],
|
|
346
|
+
});
|
|
347
|
+
const changes = tree.listChanges();
|
|
348
|
+
(0, tree_1.flushChanges)(repoRoot, changes);
|
|
349
|
+
if (aiAgentsCallback) {
|
|
350
|
+
const results = await aiAgentsCallback();
|
|
351
|
+
results.messages.forEach((m) => output_1.output.log(m));
|
|
352
|
+
results.errors.forEach((e) => output_1.output.error(e));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
catch (e) {
|
|
356
|
+
if (!(0, permission_errors_1.isPermissionDenied)(e)) {
|
|
357
|
+
throw e;
|
|
358
|
+
}
|
|
359
|
+
// Don't fail the whole init over this — everything else succeeded.
|
|
360
|
+
// Warned rather than thrown so the rest of the init result still stands.
|
|
361
|
+
output_1.output.warn({
|
|
362
|
+
title: 'AI agent configuration could not be written from this process',
|
|
363
|
+
bodyLines: (0, utils_2.agentConfigWriteBlockedLines)(e),
|
|
364
|
+
});
|
|
338
365
|
}
|
|
339
366
|
}
|
|
340
367
|
let nxCloudChoice;
|
|
@@ -8,7 +8,6 @@ const tmp_dir_1 = require("../../daemon/tmp-dir");
|
|
|
8
8
|
const cache_directory_1 = require("../../utils/cache-directory");
|
|
9
9
|
const output_1 = require("../../utils/output");
|
|
10
10
|
const native_file_cache_location_1 = require("../../native/native-file-cache-location");
|
|
11
|
-
const native_1 = require("../../native");
|
|
12
11
|
const workspace_root_1 = require("../../utils/workspace-root");
|
|
13
12
|
const client_2 = require("../../nx-cloud/utilities/client");
|
|
14
13
|
const get_cloud_options_1 = require("../../nx-cloud/utilities/get-cloud-options");
|
|
@@ -133,8 +132,19 @@ function removeInstalledNxCloudClient() {
|
|
|
133
132
|
function cleanupCacheEntries() {
|
|
134
133
|
return incrementalBackoff(INCREMENTAL_BACKOFF_FIRST_DELAY, INCREMENTAL_BACKOFF_MAX_DURATION, () => {
|
|
135
134
|
(0, node_fs_1.rmSync)(cache_directory_1.cacheDir, { recursive: true, force: true });
|
|
135
|
+
// `cacheDir` is the shared directory whenever sharing is available, so
|
|
136
|
+
// this is the checkout's own `.nx/cache`: still there from before the
|
|
137
|
+
// move, and still what a later run falls back to if `~/.nx` stops being
|
|
138
|
+
// reachable. Reset means both.
|
|
139
|
+
removeIfDistinct((0, cache_directory_1.cacheDirectoryForWorkspace)(workspace_root_1.workspaceRoot), cache_directory_1.cacheDir);
|
|
136
140
|
});
|
|
137
141
|
}
|
|
142
|
+
/** Skips the no-op when the two resolve to one directory. */
|
|
143
|
+
function removeIfDistinct(dir, from) {
|
|
144
|
+
if (dir !== from) {
|
|
145
|
+
(0, node_fs_1.rmSync)(dir, { recursive: true, force: true });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
138
148
|
function cleanupNativeFileCache() {
|
|
139
149
|
return incrementalBackoff(INCREMENTAL_BACKOFF_FIRST_DELAY, INCREMENTAL_BACKOFF_MAX_DURATION, () => {
|
|
140
150
|
// Null when the native cache root is not a real directory we own, which
|
|
@@ -148,20 +158,12 @@ function cleanupNativeFileCache() {
|
|
|
148
158
|
function cleanupWorkspaceData() {
|
|
149
159
|
return incrementalBackoff(INCREMENTAL_BACKOFF_FIRST_DELAY, INCREMENTAL_BACKOFF_MAX_DURATION, () => {
|
|
150
160
|
(0, node_fs_1.rmSync)(cache_directory_1.workspaceDataDirectory, { recursive: true, force: true });
|
|
151
|
-
//
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (sharedDir !== cache_directory_1.workspaceDataDirectory) {
|
|
158
|
-
(0, node_fs_1.rmSync)(sharedDir, { recursive: true, force: true });
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
catch {
|
|
163
|
-
// Worktree detection is best-effort during reset
|
|
164
|
-
}
|
|
161
|
+
// Also clean wherever the DB actually lives, which is outside this
|
|
162
|
+
// checkout whenever the shared root is reachable. Resolved through the
|
|
163
|
+
// same decision the DB itself uses, so reset cannot delete a directory
|
|
164
|
+
// this process never wrote to -- a sandboxed agent that fell back to its
|
|
165
|
+
// own checkout, or a configured location, yields nothing extra.
|
|
166
|
+
removeIfDistinct((0, cache_directory_1.sharedDataDirectory)(workspace_root_1.workspaceRoot, 'workspace-data'), cache_directory_1.workspaceDataDirectory);
|
|
165
167
|
});
|
|
166
168
|
}
|
|
167
169
|
async function incrementalBackoff(ms, maxDuration, callback) {
|