nx 23.0.0-beta.2 → 23.0.0-beta.21
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/dist/bin/init-local.js +11 -20
- package/dist/bin/nx.d.ts +1 -0
- package/dist/bin/nx.js +28 -2
- package/dist/plugins/package-json.js +4 -2
- package/dist/src/adapter/ngcli-adapter.d.ts +2 -1
- package/dist/src/adapter/ngcli-adapter.js +25 -2
- package/dist/src/ai/clone-ai-config-repo.js +20 -3
- package/dist/src/analytics/analytics.js +10 -1
- package/dist/src/command-line/add/completion.d.ts +1 -0
- package/dist/src/command-line/add/completion.js +15 -0
- package/dist/src/command-line/affected/completion.d.ts +1 -0
- package/dist/src/command-line/affected/completion.js +15 -0
- package/dist/src/command-line/completion/argv-layout.d.ts +6 -0
- package/dist/src/command-line/completion/argv-layout.js +19 -0
- package/dist/src/command-line/completion/command-completions.d.ts +19 -0
- package/dist/src/command-line/completion/command-completions.js +120 -0
- package/dist/src/command-line/completion/command-handlers.d.ts +30 -0
- package/dist/src/command-line/completion/command-handlers.js +69 -0
- package/dist/src/command-line/completion/command-object.d.ts +10 -0
- package/dist/src/command-line/completion/command-object.js +95 -0
- package/dist/src/command-line/completion/completion-providers.d.ts +21 -0
- package/dist/src/command-line/completion/completion-providers.js +194 -0
- package/dist/src/command-line/completion/infix-targets.d.ts +1 -0
- package/dist/src/command-line/completion/infix-targets.js +48 -0
- package/dist/src/command-line/completion/metadata.d.ts +22 -0
- package/dist/src/command-line/completion/metadata.js +71 -0
- package/dist/src/command-line/completion/registrations.d.ts +9 -0
- package/dist/src/command-line/completion/registrations.js +16 -0
- package/dist/src/command-line/completion/scripts/bash.sh +51 -0
- package/dist/src/command-line/completion/scripts/fish.fish +47 -0
- package/dist/src/command-line/completion/scripts/powershell.ps1 +52 -0
- package/dist/src/command-line/completion/scripts/zsh.zsh +69 -0
- package/dist/src/command-line/completion/scripts.d.ts +18 -0
- package/dist/src/command-line/completion/scripts.js +140 -0
- package/dist/src/command-line/completion/trigger.d.ts +3 -0
- package/dist/src/command-line/completion/trigger.js +21 -0
- package/dist/src/command-line/completion/value-completions.d.ts +3 -0
- package/dist/src/command-line/completion/value-completions.js +21 -0
- package/dist/src/command-line/examples.js +1 -1
- package/dist/src/command-line/format/format.js +15 -5
- package/dist/src/command-line/generate/completion.d.ts +1 -0
- package/dist/src/command-line/generate/completion.js +9 -0
- package/dist/src/command-line/graph/completion.d.ts +1 -0
- package/dist/src/command-line/graph/completion.js +13 -0
- package/dist/src/command-line/init/implementation/angular/standalone-workspace.js +14 -18
- package/dist/src/command-line/init/implementation/dot-nx/add-nx-scripts.js +1 -0
- package/dist/src/command-line/init/implementation/utils.d.ts +7 -1
- package/dist/src/command-line/init/implementation/utils.js +51 -14
- package/dist/src/command-line/migrate/agentic/capture-generator-output.d.ts +22 -0
- package/dist/src/command-line/migrate/agentic/capture-generator-output.js +100 -0
- package/dist/src/command-line/migrate/agentic/cli-args.d.ts +12 -0
- package/dist/src/command-line/migrate/agentic/cli-args.js +38 -0
- package/dist/src/command-line/migrate/agentic/definitions.d.ts +6 -0
- package/dist/src/command-line/migrate/agentic/definitions.js +98 -0
- package/dist/src/command-line/migrate/agentic/detect-installed.d.ts +10 -0
- package/dist/src/command-line/migrate/agentic/detect-installed.js +68 -0
- package/dist/src/command-line/migrate/agentic/handoff-gitignore.d.ts +46 -0
- package/dist/src/command-line/migrate/agentic/handoff-gitignore.js +87 -0
- package/dist/src/command-line/migrate/agentic/handoff.d.ts +63 -0
- package/dist/src/command-line/migrate/agentic/handoff.js +183 -0
- package/dist/src/command-line/migrate/agentic/inception.d.ts +9 -0
- package/dist/src/command-line/migrate/agentic/inception.js +15 -0
- package/dist/src/command-line/migrate/agentic/print-dropped-agent-context.d.ts +22 -0
- package/dist/src/command-line/migrate/agentic/print-dropped-agent-context.js +50 -0
- package/dist/src/command-line/migrate/agentic/prompts/generic-validation.d.ts +51 -0
- package/dist/src/command-line/migrate/agentic/prompts/generic-validation.js +65 -0
- package/dist/src/command-line/migrate/agentic/prompts/hybrid-prompt-migration.d.ts +44 -0
- package/dist/src/command-line/migrate/agentic/prompts/hybrid-prompt-migration.js +52 -0
- package/dist/src/command-line/migrate/agentic/prompts/prompt-migration.d.ts +21 -0
- package/dist/src/command-line/migrate/agentic/prompts/prompt-migration.js +26 -0
- package/dist/src/command-line/migrate/agentic/prompts/shared-rendering.d.ts +18 -0
- package/dist/src/command-line/migrate/agentic/prompts/shared-rendering.js +130 -0
- package/dist/src/command-line/migrate/agentic/prompts/system-prompt.d.ts +46 -0
- package/dist/src/command-line/migrate/agentic/prompts/system-prompt.js +88 -0
- package/dist/src/command-line/migrate/agentic/run-step.d.ts +51 -0
- package/dist/src/command-line/migrate/agentic/run-step.js +121 -0
- package/dist/src/command-line/migrate/agentic/runner.d.ts +33 -0
- package/dist/src/command-line/migrate/agentic/runner.js +442 -0
- package/dist/src/command-line/migrate/agentic/select.d.ts +14 -0
- package/dist/src/command-line/migrate/agentic/select.js +150 -0
- package/dist/src/command-line/migrate/agentic/types.d.ts +102 -0
- package/dist/src/command-line/migrate/agentic/types.js +2 -0
- package/dist/src/command-line/migrate/command-object.d.ts +1 -0
- package/dist/src/command-line/migrate/command-object.js +32 -7
- package/dist/src/command-line/migrate/migrate-commits.d.ts +50 -0
- package/dist/src/command-line/migrate/migrate-commits.js +102 -0
- package/dist/src/command-line/migrate/migrate-output.d.ts +180 -0
- package/dist/src/command-line/migrate/migrate-output.js +258 -0
- package/dist/src/command-line/migrate/migrate.d.ts +122 -12
- package/dist/src/command-line/migrate/migrate.js +1036 -217
- package/dist/src/command-line/migrate/migration-shape.d.ts +8 -0
- package/dist/src/command-line/migrate/migration-shape.js +13 -0
- package/dist/src/command-line/migrate/multi-major.d.ts +30 -0
- package/dist/src/command-line/migrate/multi-major.js +185 -0
- package/dist/src/command-line/migrate/prompt-files.d.ts +31 -0
- package/dist/src/command-line/migrate/prompt-files.js +141 -0
- package/dist/src/command-line/migrate/run-migration-process.js +28 -6
- package/dist/src/command-line/migrate/safe-prompt.d.ts +28 -0
- package/dist/src/command-line/migrate/safe-prompt.js +49 -0
- package/dist/src/command-line/migrate/update-filters.d.ts +11 -0
- package/dist/src/command-line/migrate/update-filters.js +44 -0
- package/dist/src/command-line/migrate/version-utils.d.ts +6 -0
- package/dist/src/command-line/migrate/version-utils.js +59 -0
- package/dist/src/command-line/nx-commands.js +9 -0
- package/dist/src/command-line/release/config/config.d.ts +3 -6
- package/dist/src/command-line/release/config/config.js +77 -45
- package/dist/src/command-line/release/config/use-legacy-versioning.d.ts +2 -0
- package/dist/src/command-line/release/config/use-legacy-versioning.js +8 -0
- package/dist/src/command-line/release/utils/release-graph.js +2 -3
- package/dist/src/command-line/release/utils/repository-git-tags.js +1 -1
- package/dist/src/command-line/release/utils/resolve-changelog-renderer.js +7 -19
- package/dist/src/command-line/release/version/resolve-current-version.js +1 -1
- package/dist/src/command-line/release/version/version-actions.js +3 -7
- package/dist/src/command-line/report/report.js +2 -2
- package/dist/src/command-line/run/completion.d.ts +1 -0
- package/dist/src/command-line/run/completion.js +7 -0
- package/dist/src/command-line/run-many/completion.d.ts +1 -0
- package/dist/src/command-line/run-many/completion.js +13 -0
- package/dist/src/command-line/show/completion.d.ts +1 -0
- package/dist/src/command-line/show/completion.js +27 -0
- package/dist/src/command-line/show/show-target/info.d.ts +1 -0
- package/dist/src/command-line/show/show-target/info.js +100 -19
- package/dist/src/command-line/watch/command-object.js +24 -4
- package/dist/src/command-line/watch/completion.d.ts +1 -0
- package/dist/src/command-line/watch/completion.js +10 -0
- package/dist/src/command-line/watch/watch.d.ts +7 -0
- package/dist/src/command-line/watch/watch.js +1 -1
- package/dist/src/config/misc-interfaces.d.ts +25 -2
- package/dist/src/config/nx-json.d.ts +43 -56
- package/dist/src/config/schema-utils.d.ts +21 -0
- package/dist/src/config/schema-utils.js +92 -18
- package/dist/src/config/task-graph.d.ts +4 -107
- package/dist/src/core/graph/main.js +1 -1
- package/dist/src/core/graph/styles.css +2 -3
- package/dist/src/core/graph/styles.js +1 -1
- package/dist/src/daemon/client/client.d.ts +1 -1
- package/dist/src/daemon/server/file-watching/file-watcher-sockets.d.ts +1 -1
- package/dist/src/daemon/server/file-watching/file-watcher-sockets.js +1 -1
- package/dist/src/daemon/server/file-watching/route-workspace-changes.d.ts +9 -0
- package/dist/src/daemon/server/file-watching/route-workspace-changes.js +76 -0
- package/dist/src/daemon/server/project-graph-incremental-recomputation.js +45 -11
- package/dist/src/daemon/server/server.js +4 -43
- package/dist/src/daemon/server/start.d.ts +1 -1
- package/dist/src/daemon/server/start.js +2 -0
- package/dist/src/devkit-exports.d.ts +2 -2
- package/dist/src/devkit-internals.d.ts +5 -1
- package/dist/src/devkit-internals.js +17 -1
- package/dist/src/executors/run-commands/running-tasks.d.ts +7 -0
- package/dist/src/executors/run-commands/running-tasks.js +178 -105
- package/dist/src/executors/run-script/run-script.impl.js +3 -10
- package/dist/src/executors/utils/convert-nx-executor.js +1 -1
- package/dist/src/hasher/hash-plan-inspector.d.ts +1 -1
- package/dist/src/hasher/task-hasher.js +6 -4
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +0 -3
- package/dist/src/migrations/update-16-2-0/remove-run-commands-output-path.js +6 -2
- package/dist/src/migrations/update-17-0-0/move-cache-directory.md +31 -0
- package/dist/src/migrations/update-17-0-0/use-minimal-config-for-tasks-runner-options.js +20 -4
- package/dist/src/migrations/update-20-0-0/move-use-daemon-process.md +27 -0
- package/dist/src/migrations/update-20-0-1/use-legacy-cache.md +24 -0
- package/dist/src/migrations/update-21-0-0/release-changelog-config-changes.md +49 -0
- package/dist/src/migrations/update-21-0-0/release-version-config-changes.md +54 -0
- package/dist/src/migrations/update-21-0-0/remove-custom-tasks-runner.md +28 -0
- package/dist/src/migrations/update-21-0-0/remove-legacy-cache.md +22 -0
- package/dist/src/migrations/update-22-2-0/add-self-healing-to-gitignore.md +11 -0
- package/dist/src/migrations/update-23-0-0/add-migrate-runs-to-git-ignore.d.ts +2 -0
- package/dist/src/migrations/update-23-0-0/add-migrate-runs-to-git-ignore.js +16 -0
- package/dist/src/migrations/update-23-0-0/consolidate-release-tag-config.d.ts +9 -0
- package/dist/src/migrations/update-23-0-0/consolidate-release-tag-config.js +18 -0
- package/dist/src/migrations/update-23-0-0/convert-target-defaults-to-array.d.ts +35 -0
- package/dist/src/migrations/update-23-0-0/convert-target-defaults-to-array.js +139 -0
- package/dist/src/migrations/update-23-0-0/convert-target-defaults-to-array.md +66 -0
- package/dist/src/native/index.d.ts +79 -2
- package/dist/src/native/native-bindings.js +3 -0
- 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/lock-file/npm-parser.js +37 -19
- package/dist/src/plugins/js/lock-file/pnpm-parser.js +51 -4
- package/dist/src/plugins/js/lock-file/project-graph-pruning.js +12 -4
- package/dist/src/plugins/js/utils/packages.js +1 -1
- package/dist/src/plugins/js/utils/register.d.ts +103 -14
- package/dist/src/plugins/js/utils/register.js +434 -39
- package/dist/src/plugins/js/utils/typescript.d.ts +7 -0
- package/dist/src/plugins/js/utils/typescript.js +39 -0
- package/dist/src/plugins/package-json/create-nodes.d.ts +3 -2
- package/dist/src/plugins/package-json/create-nodes.js +7 -5
- package/dist/src/project-graph/affected/locators/project-glob-changes.js +2 -1
- package/dist/src/project-graph/build-project-graph.d.ts +5 -0
- package/dist/src/project-graph/build-project-graph.js +6 -2
- package/dist/src/project-graph/file-map-utils.d.ts +5 -0
- package/dist/src/project-graph/file-map-utils.js +10 -1
- package/dist/src/project-graph/plugins/get-plugins.d.ts +7 -2
- package/dist/src/project-graph/plugins/get-plugins.js +8 -5
- package/dist/src/project-graph/plugins/isolation/plugin-worker.d.ts +1 -0
- package/dist/src/project-graph/plugins/isolation/plugin-worker.js +2 -0
- package/dist/src/project-graph/plugins/resolve-plugin.d.ts +7 -4
- package/dist/src/project-graph/plugins/resolve-plugin.js +152 -33
- package/dist/src/project-graph/plugins/tasks-execution-hooks.js +4 -2
- package/dist/src/project-graph/plugins/transpiler.d.ts +12 -0
- package/dist/src/project-graph/plugins/transpiler.js +37 -0
- package/dist/src/project-graph/plugins/utils.js +13 -7
- package/dist/src/project-graph/project-graph.js +1 -1
- package/dist/src/project-graph/utils/project-configuration/target-defaults.d.ts +95 -4
- package/dist/src/project-graph/utils/project-configuration/target-defaults.js +515 -68
- package/dist/src/project-graph/utils/project-configuration-utils.d.ts +13 -5
- package/dist/src/project-graph/utils/project-configuration-utils.js +14 -6
- package/dist/src/project-graph/utils/retrieve-workspace-files.js +1 -1
- package/dist/src/tasks-runner/create-task-graph.d.ts +4 -4
- package/dist/src/tasks-runner/create-task-graph.js +1 -1
- package/dist/src/tasks-runner/default-tasks-runner.d.ts +0 -2
- package/dist/src/tasks-runner/forked-process-task-runner.d.ts +1 -1
- package/dist/src/tasks-runner/forked-process-task-runner.js +11 -6
- package/dist/src/tasks-runner/init-tasks-runner.d.ts +0 -15
- package/dist/src/tasks-runner/init-tasks-runner.js +0 -63
- package/dist/src/tasks-runner/legacy-depends-on-warning.d.ts +18 -0
- package/dist/src/tasks-runner/legacy-depends-on-warning.js +109 -0
- package/dist/src/tasks-runner/life-cycle.d.ts +7 -8
- package/dist/src/tasks-runner/life-cycles/invoke-runner-terminal-output-life-cycle.js +6 -6
- package/dist/src/tasks-runner/life-cycles/task-history-life-cycle-old.js +13 -2
- package/dist/src/tasks-runner/life-cycles/task-history-life-cycle.js +16 -5
- package/dist/src/tasks-runner/life-cycles/tui-summary-life-cycle.js +11 -2
- package/dist/src/tasks-runner/pseudo-terminal.d.ts +1 -1
- package/dist/src/tasks-runner/pseudo-terminal.js +22 -10
- package/dist/src/tasks-runner/run-command.js +8 -11
- package/dist/src/tasks-runner/running-tasks/batch-process.d.ts +1 -1
- package/dist/src/tasks-runner/running-tasks/batch-process.js +3 -5
- package/dist/src/tasks-runner/running-tasks/node-child-process.d.ts +2 -2
- package/dist/src/tasks-runner/running-tasks/node-child-process.js +5 -7
- package/dist/src/tasks-runner/task-env.d.ts +1 -1
- package/dist/src/tasks-runner/task-env.js +6 -1
- package/dist/src/tasks-runner/task-orchestrator.d.ts +11 -1
- package/dist/src/tasks-runner/task-orchestrator.js +112 -38
- package/dist/src/tasks-runner/tasks-schedule.js +3 -3
- package/dist/src/tasks-runner/utils.d.ts +7 -8
- package/dist/src/tasks-runner/utils.js +23 -27
- package/dist/src/utils/child-process.js +2 -2
- package/dist/src/utils/compile-cache.d.ts +24 -0
- package/dist/src/utils/compile-cache.js +49 -0
- package/dist/src/utils/enable-compile-cache.d.ts +1 -0
- package/dist/src/utils/enable-compile-cache.js +7 -0
- package/dist/src/utils/fileutils.d.ts +0 -8
- package/dist/src/utils/fileutils.js +0 -40
- package/dist/src/utils/git-utils.d.ts +15 -0
- package/dist/src/utils/git-utils.js +138 -0
- package/dist/src/utils/handle-import.d.ts +4 -1
- package/dist/src/utils/handle-import.js +56 -2
- package/dist/src/utils/has-nx-js-plugin.d.ts +9 -0
- package/dist/src/utils/has-nx-js-plugin.js +24 -0
- package/dist/src/utils/installed-nx-version.d.ts +14 -4
- package/dist/src/utils/installed-nx-version.js +54 -7
- package/dist/src/utils/logger.d.ts +12 -1
- package/dist/src/utils/logger.js +57 -36
- package/dist/src/utils/nx-key.d.ts +0 -1
- package/dist/src/utils/nx-key.js +20 -23
- package/dist/src/utils/nx-package-group.d.ts +8 -0
- package/dist/src/utils/nx-package-group.js +15 -0
- package/dist/src/utils/output.d.ts +3 -2
- package/dist/src/utils/output.js +29 -28
- package/dist/src/utils/package-json.d.ts +14 -1
- package/dist/src/utils/package-json.js +20 -21
- package/dist/src/utils/perf-logging.js +3 -1
- package/dist/src/utils/plugin-cache-utils.d.ts +13 -4
- package/dist/src/utils/plugin-cache-utils.js +23 -13
- package/dist/src/utils/plugins/local-plugins.d.ts +18 -0
- package/dist/src/utils/plugins/local-plugins.js +30 -0
- package/dist/src/utils/tar.d.ts +8 -0
- package/dist/src/utils/tar.js +44 -0
- package/migrations.json +16 -0
- package/package.json +28 -28
- package/schemas/nx-schema.json +114 -80
- package/dist/src/plugins/js/project-graph/build-dependencies/strip-source-code.d.ts +0 -7
- package/dist/src/plugins/js/project-graph/build-dependencies/strip-source-code.js +0 -155
- package/dist/src/plugins/js/project-graph/build-dependencies/typescript-import-locator.d.ts +0 -16
- package/dist/src/plugins/js/project-graph/build-dependencies/typescript-import-locator.js +0 -121
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runDirPath = runDirPath;
|
|
4
|
+
exports.mkdirSafely = mkdirSafely;
|
|
5
|
+
exports.initRunDir = initRunDir;
|
|
6
|
+
exports.stepHandoffPath = stepHandoffPath;
|
|
7
|
+
exports.readHandoffWithReason = readHandoffWithReason;
|
|
8
|
+
exports.readHandoff = readHandoff;
|
|
9
|
+
exports.waitForValidHandoff = waitForValidHandoff;
|
|
10
|
+
const fs_1 = require("fs");
|
|
11
|
+
const path_1 = require("path");
|
|
12
|
+
/** Returns the run directory for a given workspace + run id (target version). */
|
|
13
|
+
function runDirPath(workspaceRoot, runId) {
|
|
14
|
+
return (0, path_1.join)(workspaceRoot, '.nx', 'migrate-runs', runId);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* `mkdir -p` with a contextual error wrapper. Without this, the raw
|
|
18
|
+
* ENOSPC/EACCES/EROFS surfaces with no indication of which directory the
|
|
19
|
+
* migrate orchestrator was trying to create.
|
|
20
|
+
*/
|
|
21
|
+
function mkdirSafely(dir, purpose) {
|
|
22
|
+
try {
|
|
23
|
+
(0, fs_1.mkdirSync)(dir, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
const code = err?.code;
|
|
27
|
+
// `{ cause }` preserves the original ErrnoException so callers can read
|
|
28
|
+
// `.cause.code`/`.cause.path`/`.cause.syscall` for targeted remediation.
|
|
29
|
+
// Without it the only signal beyond the formatted message would be the
|
|
30
|
+
// code string we splice in below.
|
|
31
|
+
throw new Error(`Could not create ${purpose} at ${dir}${code ? ` (${code})` : ''}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Wipes any prior contents for this run id and recreates an empty directory.
|
|
36
|
+
*
|
|
37
|
+
* Scope of the wipe is intentionally narrow (only `<run-id>/`) so that handoff
|
|
38
|
+
* artifacts from prior runs targeting different versions remain on disk for
|
|
39
|
+
* inspection.
|
|
40
|
+
*/
|
|
41
|
+
function initRunDir(workspaceRoot, runId) {
|
|
42
|
+
const dir = runDirPath(workspaceRoot, runId);
|
|
43
|
+
(0, fs_1.rmSync)(dir, { recursive: true, force: true });
|
|
44
|
+
mkdirSafely(dir, 'nx migrate run directory');
|
|
45
|
+
return dir;
|
|
46
|
+
}
|
|
47
|
+
// Windows reserved device names fail to open even with an extension —
|
|
48
|
+
// a migration named `CON` would otherwise produce a `CON.json` that the
|
|
49
|
+
// agent can't write to.
|
|
50
|
+
const WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\..*)?$/i;
|
|
51
|
+
/**
|
|
52
|
+
* The bare `.` / `..` check must come first — otherwise a malformed migration
|
|
53
|
+
* name of exactly `..` would let the handoff write escape the run directory.
|
|
54
|
+
*/
|
|
55
|
+
function sanitizeSegment(value) {
|
|
56
|
+
if (value === '.' || value === '..')
|
|
57
|
+
return '_';
|
|
58
|
+
let sanitized = value.replace(/[\x00-\x1f<>:"/\\|?*]/g, '_');
|
|
59
|
+
// Windows forbids trailing dots/spaces on file/directory names.
|
|
60
|
+
sanitized = sanitized.replace(/[. ]+$/, '');
|
|
61
|
+
if (WINDOWS_RESERVED_NAMES.test(sanitized)) {
|
|
62
|
+
sanitized = `_${sanitized}`;
|
|
63
|
+
}
|
|
64
|
+
return sanitized || '_';
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Absolute path of the handoff file for a migration step within a run.
|
|
68
|
+
* The package's scope (if any) becomes a real subdirectory so the package name
|
|
69
|
+
* stays readable; two packages can ship a migration with the same name without
|
|
70
|
+
* colliding because they land in different package subdirectories. Each
|
|
71
|
+
* segment is sanitized so the path is always writable on every platform.
|
|
72
|
+
*/
|
|
73
|
+
function stepHandoffPath(runDir, migration) {
|
|
74
|
+
return (0, path_1.join)(runDir, ...migration.package.split('/').map(sanitizeSegment), `${sanitizeSegment(migration.name)}.json`);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Reads and validates a handoff file written by an agent. Returns a tagged
|
|
78
|
+
* result so callers (the in-loop poller and the post-exit resolver) can
|
|
79
|
+
* distinguish "file not yet written" from "file written but garbage" — the
|
|
80
|
+
* latter is surfaced to the user instead of being collapsed into the same
|
|
81
|
+
* generic ambiguous-outcome prompt.
|
|
82
|
+
*/
|
|
83
|
+
function readHandoffWithReason(filePath) {
|
|
84
|
+
let raw;
|
|
85
|
+
try {
|
|
86
|
+
raw = (0, fs_1.readFileSync)(filePath, 'utf-8');
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
const code = err?.code;
|
|
90
|
+
if (code === 'ENOENT')
|
|
91
|
+
return { ok: false, reason: 'missing' };
|
|
92
|
+
return {
|
|
93
|
+
ok: false,
|
|
94
|
+
reason: 'read-error',
|
|
95
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
let parsed;
|
|
99
|
+
try {
|
|
100
|
+
parsed = JSON.parse(raw);
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
return {
|
|
104
|
+
ok: false,
|
|
105
|
+
reason: 'parse-error',
|
|
106
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (!parsed ||
|
|
110
|
+
typeof parsed !== 'object' ||
|
|
111
|
+
Array.isArray(parsed) ||
|
|
112
|
+
typeof parsed.summary !== 'string') {
|
|
113
|
+
return { ok: false, reason: 'shape-mismatch' };
|
|
114
|
+
}
|
|
115
|
+
const obj = parsed;
|
|
116
|
+
const status = obj.status;
|
|
117
|
+
const summary = obj.summary;
|
|
118
|
+
if (status !== 'success' && status !== 'failed') {
|
|
119
|
+
return { ok: false, reason: 'shape-mismatch' };
|
|
120
|
+
}
|
|
121
|
+
// Null-prototype object guards against a prototype-pollution gadget:
|
|
122
|
+
// JSON.parse materializes `__proto__` as an own enumerable property, and
|
|
123
|
+
// a rest-spread would carry it through to wherever extras gets merged.
|
|
124
|
+
const extras = Object.create(null);
|
|
125
|
+
for (const key of Object.keys(obj)) {
|
|
126
|
+
if (key === 'status' || key === 'summary')
|
|
127
|
+
continue;
|
|
128
|
+
extras[key] = obj[key];
|
|
129
|
+
}
|
|
130
|
+
const handoff = { status, summary: summary };
|
|
131
|
+
if (Object.keys(extras).length > 0) {
|
|
132
|
+
handoff.extras = extras;
|
|
133
|
+
}
|
|
134
|
+
return { ok: true, handoff };
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Convenience wrapper preserving the original null-on-any-failure contract.
|
|
138
|
+
* Used by the polling loop (`waitForValidHandoff`) where every failure mode
|
|
139
|
+
* is "keep waiting" — the file may be missing, mid-write, or being rewritten.
|
|
140
|
+
*/
|
|
141
|
+
function readHandoff(filePath) {
|
|
142
|
+
const result = readHandoffWithReason(filePath);
|
|
143
|
+
return result.ok ? result.handoff : null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Polls for a valid handoff file. Resolves once `readHandoff` accepts the
|
|
147
|
+
* file's contents. Used to detect when the agent has finished its work so the
|
|
148
|
+
* orchestrator can close the agent's session without depending on the agent
|
|
149
|
+
* exiting on its own.
|
|
150
|
+
*
|
|
151
|
+
* Rejects with the abort reason when `options.signal` is aborted.
|
|
152
|
+
*/
|
|
153
|
+
function waitForValidHandoff(handoffFilePath, options = {}) {
|
|
154
|
+
const intervalMs = options.intervalMs ?? 500;
|
|
155
|
+
const { signal } = options;
|
|
156
|
+
return new Promise((resolve, reject) => {
|
|
157
|
+
if (signal?.aborted) {
|
|
158
|
+
reject(signal.reason ?? new Error('aborted'));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
let timer;
|
|
162
|
+
const onAbort = () => {
|
|
163
|
+
if (timer)
|
|
164
|
+
clearTimeout(timer);
|
|
165
|
+
signal?.removeEventListener('abort', onAbort);
|
|
166
|
+
reject(signal.reason ?? new Error('aborted'));
|
|
167
|
+
};
|
|
168
|
+
const tick = () => {
|
|
169
|
+
if (signal?.aborted) {
|
|
170
|
+
onAbort();
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (readHandoff(handoffFilePath) !== null) {
|
|
174
|
+
signal?.removeEventListener('abort', onAbort);
|
|
175
|
+
resolve();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
timer = setTimeout(tick, intervalMs);
|
|
179
|
+
};
|
|
180
|
+
signal?.addEventListener('abort', onAbort);
|
|
181
|
+
timer = setTimeout(tick, intervalMs);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true when `nx migrate` is itself being run from inside another AI
|
|
3
|
+
* agent's terminal session. Used to short-circuit the agentic flow so we never
|
|
4
|
+
* spawn an inner agent inside an outer agent.
|
|
5
|
+
*
|
|
6
|
+
* Native `isAiAgent()` covers all supported agents (Claude Code, Cursor,
|
|
7
|
+
* OpenCode, Codex, Gemini, Replit) via parent-process env-var sniffing.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isInsideAgent(): boolean;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isInsideAgent = isInsideAgent;
|
|
4
|
+
const native_1 = require("../../../native");
|
|
5
|
+
/**
|
|
6
|
+
* Returns true when `nx migrate` is itself being run from inside another AI
|
|
7
|
+
* agent's terminal session. Used to short-circuit the agentic flow so we never
|
|
8
|
+
* spawn an inner agent inside an outer agent.
|
|
9
|
+
*
|
|
10
|
+
* Native `isAiAgent()` covers all supported agents (Claude Code, Cursor,
|
|
11
|
+
* OpenCode, Codex, Gemini, Replit) via parent-process env-var sniffing.
|
|
12
|
+
*/
|
|
13
|
+
function isInsideAgent() {
|
|
14
|
+
return (0, native_1.isAiAgent)();
|
|
15
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surfaces a migration's `agentContext` to stdout in an XML-tagged block so an
|
|
3
|
+
* outer AI agent driving `nx migrate` can ingest the hints when no inner agent
|
|
4
|
+
* step ran to consume them.
|
|
5
|
+
*
|
|
6
|
+
* Used only when `agentic.kind === 'inside-agent'`. Under `enabled`, the inner
|
|
7
|
+
* step consumes `agentContext` via the prompt builders. Under `disabled` the
|
|
8
|
+
* run is human-driven and printing agent-targeted context would only add noise.
|
|
9
|
+
*
|
|
10
|
+
* The label format is unambiguous so the outer agent can locate the block
|
|
11
|
+
* within the mixed stdout stream (logger output, migration progress, etc.).
|
|
12
|
+
*/
|
|
13
|
+
export interface DroppedAgentContextInput {
|
|
14
|
+
migration: {
|
|
15
|
+
package: string;
|
|
16
|
+
name: string;
|
|
17
|
+
prompt?: string;
|
|
18
|
+
};
|
|
19
|
+
agentContext: string[];
|
|
20
|
+
}
|
|
21
|
+
export declare function formatDroppedAgentContextForOuterAgent(input: DroppedAgentContextInput): string;
|
|
22
|
+
export declare function printDroppedAgentContextForOuterAgent(input: DroppedAgentContextInput): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatDroppedAgentContextForOuterAgent = formatDroppedAgentContextForOuterAgent;
|
|
4
|
+
exports.printDroppedAgentContextForOuterAgent = printDroppedAgentContextForOuterAgent;
|
|
5
|
+
const shared_rendering_1 = require("./prompts/shared-rendering");
|
|
6
|
+
function formatDroppedAgentContextForOuterAgent(input) {
|
|
7
|
+
const entries = (0, shared_rendering_1.filterNonEmptyStrings)(input.agentContext);
|
|
8
|
+
if (entries.length === 0) {
|
|
9
|
+
return '';
|
|
10
|
+
}
|
|
11
|
+
const id = `${input.migration.package}:${input.migration.name}`;
|
|
12
|
+
// Migration metadata and agentContext entries are user-authored (migrations
|
|
13
|
+
// are published by third-party packages); escape any `<` / `&` so a hostile
|
|
14
|
+
// value can't break out of the surrounding XML-framed block. The agent
|
|
15
|
+
// reads `</agent_context>` as literal text, not a closing tag.
|
|
16
|
+
const safeName = (0, shared_rendering_1.escapeXmlBody)(input.migration.name);
|
|
17
|
+
const safePrompt = input.migration.prompt
|
|
18
|
+
? (0, shared_rendering_1.escapeXmlBody)(input.migration.prompt)
|
|
19
|
+
: undefined;
|
|
20
|
+
const preamble = safePrompt
|
|
21
|
+
? `ℹ Hints from the ${safeName} generator for the AI agent driving this run, when applying ${safePrompt}:`
|
|
22
|
+
: `ℹ Hints from the ${safeName} generator for the AI agent driving this run:`;
|
|
23
|
+
return [
|
|
24
|
+
preamble,
|
|
25
|
+
``,
|
|
26
|
+
`<agent_context migration="${escapeXmlAttr(id)}">`,
|
|
27
|
+
...entries.map((entry) => (0, shared_rendering_1.renderListItem)((0, shared_rendering_1.escapeXmlBody)(entry))),
|
|
28
|
+
`</agent_context>`,
|
|
29
|
+
].join('\n');
|
|
30
|
+
}
|
|
31
|
+
// Migration package/name come from arbitrary user-authored package.json /
|
|
32
|
+
// migrations.json — a name with `"` / `<` / `>` / `&` would produce malformed
|
|
33
|
+
// XML the outer agent can't parse. `'` is not strictly required for
|
|
34
|
+
// double-quoted attribute values but is included for defense.
|
|
35
|
+
function escapeXmlAttr(value) {
|
|
36
|
+
return value
|
|
37
|
+
.replace(/&/g, '&')
|
|
38
|
+
.replace(/</g, '<')
|
|
39
|
+
.replace(/>/g, '>')
|
|
40
|
+
.replace(/"/g, '"')
|
|
41
|
+
.replace(/'/g, ''');
|
|
42
|
+
}
|
|
43
|
+
function printDroppedAgentContextForOuterAgent(input) {
|
|
44
|
+
const block = formatDroppedAgentContextForOuterAgent(input);
|
|
45
|
+
if (block) {
|
|
46
|
+
// Bare newline pair frames the block so adjacent stdout (logger output,
|
|
47
|
+
// migration progress) doesn't run into the opening or closing tag.
|
|
48
|
+
process.stdout.write(`\n${block}\n\n`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { FileChange } from '../../../../generators/tree';
|
|
2
|
+
export interface GenericValidationPromptContext {
|
|
3
|
+
package: string;
|
|
4
|
+
name: string;
|
|
5
|
+
version: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
/** Absolute path the agent must write its handoff file to. */
|
|
8
|
+
handoffFileAbsolutePath: string;
|
|
9
|
+
/** Context captured from the deterministic generator phase. */
|
|
10
|
+
impl: {
|
|
11
|
+
/** Raw output from the generator (devkit logger + console). */
|
|
12
|
+
logs?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Files the generator changed. Rendered inside `<files_changed>` as a
|
|
15
|
+
* `[TYPE] path` list — only when `hasDiffContext` is false; when true the
|
|
16
|
+
* agent is instead instructed to inspect via git.
|
|
17
|
+
*/
|
|
18
|
+
changes: FileChange[];
|
|
19
|
+
/** Strings the generator author put in `agentContext`. */
|
|
20
|
+
agentContext?: string[];
|
|
21
|
+
/**
|
|
22
|
+
* True when per-migration commits are in effect (git repo + commits
|
|
23
|
+
* enabled). The prompt instructs the agent to use `git status`/`git diff`
|
|
24
|
+
* for the file list. When false (no git, or commits disabled), the
|
|
25
|
+
* `<files_changed>` block is embedded with `changes` instead.
|
|
26
|
+
*/
|
|
27
|
+
hasDiffContext: boolean;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Cap on the number of file entries rendered verbatim inside `<files_changed>`
|
|
32
|
+
* when the embedded-list path is used (no per-migration commits / no git).
|
|
33
|
+
* Excess entries collapse into a `… and N more files.` line.
|
|
34
|
+
*/
|
|
35
|
+
export declare const GENERIC_VALIDATION_FILE_LIST_CAP = 50;
|
|
36
|
+
/**
|
|
37
|
+
* Builds the user prompt for the framework-owned generic-validation agent step
|
|
38
|
+
* that runs after a generator-only migration produces changes (when `--validate`
|
|
39
|
+
* is enabled and `--agentic` resolves to an enabled agent).
|
|
40
|
+
*
|
|
41
|
+
* Differences from `buildHybridPromptUserPrompt`:
|
|
42
|
+
* - No `<instructions_file>` block — the framework owns the instructions, and
|
|
43
|
+
* they live inline in `<validation_instructions>` below.
|
|
44
|
+
* - No `<precedence>` block — there's no external instructions file to defer
|
|
45
|
+
* to.
|
|
46
|
+
* - File-list cap: when the diff exceeds `GENERIC_VALIDATION_FILE_LIST_CAP`,
|
|
47
|
+
* the first N entries render verbatim and the remainder collapses into a
|
|
48
|
+
* `… and N more files.` count line.
|
|
49
|
+
* - The lead sentence frames the agent as a validator, not an applier.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildGenericValidationUserPrompt(ctx: GenericValidationPromptContext): string;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GENERIC_VALIDATION_FILE_LIST_CAP = void 0;
|
|
4
|
+
exports.buildGenericValidationUserPrompt = buildGenericValidationUserPrompt;
|
|
5
|
+
const shared_rendering_1 = require("./shared-rendering");
|
|
6
|
+
/**
|
|
7
|
+
* Cap on the number of file entries rendered verbatim inside `<files_changed>`
|
|
8
|
+
* when the embedded-list path is used (no per-migration commits / no git).
|
|
9
|
+
* Excess entries collapse into a `… and N more files.` line.
|
|
10
|
+
*/
|
|
11
|
+
exports.GENERIC_VALIDATION_FILE_LIST_CAP = 50;
|
|
12
|
+
/**
|
|
13
|
+
* Builds the user prompt for the framework-owned generic-validation agent step
|
|
14
|
+
* that runs after a generator-only migration produces changes (when `--validate`
|
|
15
|
+
* is enabled and `--agentic` resolves to an enabled agent).
|
|
16
|
+
*
|
|
17
|
+
* Differences from `buildHybridPromptUserPrompt`:
|
|
18
|
+
* - No `<instructions_file>` block — the framework owns the instructions, and
|
|
19
|
+
* they live inline in `<validation_instructions>` below.
|
|
20
|
+
* - No `<precedence>` block — there's no external instructions file to defer
|
|
21
|
+
* to.
|
|
22
|
+
* - File-list cap: when the diff exceeds `GENERIC_VALIDATION_FILE_LIST_CAP`,
|
|
23
|
+
* the first N entries render verbatim and the remainder collapses into a
|
|
24
|
+
* `… and N more files.` count line.
|
|
25
|
+
* - The lead sentence frames the agent as a validator, not an applier.
|
|
26
|
+
*/
|
|
27
|
+
function buildGenericValidationUserPrompt(ctx) {
|
|
28
|
+
const lines = [
|
|
29
|
+
`You are validating the output of an Nx migration's deterministic generator phase. The generator has already run; inspect what it produced, verify the workspace is in a consistent state for what this migration intended to accomplish, apply any minor in-scope fixes the generator should have produced cleanly, and report findings.`,
|
|
30
|
+
...(0, shared_rendering_1.renderMigrationBlock)(ctx),
|
|
31
|
+
];
|
|
32
|
+
const logs = (0, shared_rendering_1.escapeXmlBody)((0, shared_rendering_1.stripAnsi)(ctx.impl.logs ?? '').trim());
|
|
33
|
+
lines.push(...(0, shared_rendering_1.renderGeneratorOutputBlock)(logs));
|
|
34
|
+
if (!ctx.impl.hasDiffContext && ctx.impl.changes.length > 0) {
|
|
35
|
+
lines.push(``, `<files_changed>`, ...renderFileListBody(ctx.impl.changes), `</files_changed>`);
|
|
36
|
+
}
|
|
37
|
+
const agentContext = (0, shared_rendering_1.filterNonEmptyStrings)(ctx.impl.agentContext ?? []);
|
|
38
|
+
if (agentContext.length > 0) {
|
|
39
|
+
lines.push(...(0, shared_rendering_1.renderAdvisoryContext)('hints emitted by the generator; treat as supplementary context, not separate tasks', agentContext));
|
|
40
|
+
}
|
|
41
|
+
const firstStep = ctx.impl.hasDiffContext
|
|
42
|
+
? `1. Inspect this migration's changes. ${(0, shared_rendering_1.renderGitInspectInstruction)()} Resolve each affected path to its owning Nx project via \`nx show project <name>\` (or by reading the project's \`project.json\` / \`package.json\`) to discover which targets each project actually defines — do not assume \`typecheck\` / \`test\` / \`lint\` exist. If no typecheck-equivalent exists, \`build\` is an acceptable substitute.`
|
|
43
|
+
: `1. Resolve each path in <files_changed> to its owning Nx project. Use \`nx show project <name>\` (or read the project's \`project.json\` / \`package.json\`) to discover which targets each project actually defines — do not assume \`typecheck\` / \`test\` / \`lint\` exist. If no typecheck-equivalent exists, \`build\` is an acceptable substitute.`;
|
|
44
|
+
lines.push(``, `<validation_instructions>`, firstStep, `2. Pick the smallest relevant subset of available targets to verify the change. Prefer \`nx affected -t <target>\` (or \`nx run <project>:<target>\` for a single project). When many small projects are affected, you may use \`nx run-many -t <target> -p <project1>,<project2>\` with the project list derived from the changed files. Unscoped \`nx run-many\` (no \`-p\`) is forbidden.`, `3. If a verification surfaces an issue the migration should have produced cleanly (e.g. a missing import, a type annotation the generator's template missed), you may apply a minor in-scope fix. The boundary is "what this migration intended to accomplish" — do not refactor, do not modify functionality unrelated to the migration, do not extend the migration's scope, do not touch code the migration was not concerned with. If you are unsure whether a fix is in scope, report it in \`summary\` instead of applying.`, `4. Apply every fix you can within scope, then write your handoff. On \`status: "success"\`, summarize what you verified and any fixes you applied. On \`status: "failed"\`, enumerate the unresolved findings in \`summary\` so the user can address them; no commit will be created from a failed run, so the generator's changes and your partial fixes will sit uncommitted in the working tree for the user to review.`, `</validation_instructions>`, ``, `Once you finish, write your handoff JSON to:`, ...(0, shared_rendering_1.renderHandoffPathFooter)(ctx.handoffFileAbsolutePath));
|
|
45
|
+
return lines.join('\n');
|
|
46
|
+
}
|
|
47
|
+
function renderFileListBody(changes) {
|
|
48
|
+
// File paths from `tree.write` are user-authored; escape `<` / `&` so a
|
|
49
|
+
// hostile path can't break out of `<files_changed>`. `change.type` is an
|
|
50
|
+
// nx-controlled enum (CREATE/UPDATE/DELETE) and needs no escape.
|
|
51
|
+
const safe = changes.map((change) => ({
|
|
52
|
+
...change,
|
|
53
|
+
path: (0, shared_rendering_1.escapeXmlBody)(change.path),
|
|
54
|
+
}));
|
|
55
|
+
if (safe.length <= exports.GENERIC_VALIDATION_FILE_LIST_CAP) {
|
|
56
|
+
return safe.map(shared_rendering_1.renderFileEntry);
|
|
57
|
+
}
|
|
58
|
+
const shown = safe.slice(0, exports.GENERIC_VALIDATION_FILE_LIST_CAP);
|
|
59
|
+
const remaining = safe.length - exports.GENERIC_VALIDATION_FILE_LIST_CAP;
|
|
60
|
+
return [
|
|
61
|
+
...shown.map(shared_rendering_1.renderFileEntry),
|
|
62
|
+
``,
|
|
63
|
+
`… and ${remaining} more file${remaining === 1 ? '' : 's'}.`,
|
|
64
|
+
];
|
|
65
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { FileChange } from '../../../../generators/tree';
|
|
2
|
+
export interface HybridPromptMigrationContext {
|
|
3
|
+
package: string;
|
|
4
|
+
name: string;
|
|
5
|
+
version: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
/** Workspace-relative path to the prompt `.md` file. */
|
|
8
|
+
promptPath: string;
|
|
9
|
+
/** Absolute path the agent must write its handoff file to. */
|
|
10
|
+
handoffFileAbsolutePath: string;
|
|
11
|
+
/** Context captured from the deterministic generator phase. */
|
|
12
|
+
impl?: {
|
|
13
|
+
/** Raw output from the generator (devkit logger + console). */
|
|
14
|
+
logs?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Files the generator changed. Rendered inside `<files_changed>` as a
|
|
17
|
+
* `[TYPE] path` list — only when `hasDiffContext` is false; when true the
|
|
18
|
+
* agent is instead pointed at `git status` / `git diff`.
|
|
19
|
+
*/
|
|
20
|
+
changes?: FileChange[];
|
|
21
|
+
/** Strings the generator author put in `agentContext`. */
|
|
22
|
+
agentContext?: string[];
|
|
23
|
+
/**
|
|
24
|
+
* True when per-migration commits are in effect (git repo + commits
|
|
25
|
+
* enabled). The prompt then points the agent at git for the file list;
|
|
26
|
+
* when false (no git or commits disabled), `changes` is embedded.
|
|
27
|
+
*/
|
|
28
|
+
hasDiffContext?: boolean;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Builds the user prompt for a hybrid migration's prompt phase (`implementation`
|
|
33
|
+
* + `prompt`). The deterministic generator has already run; sections of the
|
|
34
|
+
* prompt summarize what it did so the agent can complete the paired step with
|
|
35
|
+
* awareness of the generator's output.
|
|
36
|
+
*
|
|
37
|
+
* Structure: XML tags carry section boundaries; markdown (fenced blocks,
|
|
38
|
+
* bullet lists) sits inside tags for inline structure. This is the
|
|
39
|
+
* multi-section case where both Anthropic and OpenAI guidance most clearly
|
|
40
|
+
* favors XML for unambiguous parsing. Each impl section is omitted when its
|
|
41
|
+
* source is empty so the prompt stays minimal when the generator made no
|
|
42
|
+
* meaningful contribution.
|
|
43
|
+
*/
|
|
44
|
+
export declare function buildHybridPromptUserPrompt(ctx: HybridPromptMigrationContext): string;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildHybridPromptUserPrompt = buildHybridPromptUserPrompt;
|
|
4
|
+
const shared_rendering_1 = require("./shared-rendering");
|
|
5
|
+
/**
|
|
6
|
+
* Builds the user prompt for a hybrid migration's prompt phase (`implementation`
|
|
7
|
+
* + `prompt`). The deterministic generator has already run; sections of the
|
|
8
|
+
* prompt summarize what it did so the agent can complete the paired step with
|
|
9
|
+
* awareness of the generator's output.
|
|
10
|
+
*
|
|
11
|
+
* Structure: XML tags carry section boundaries; markdown (fenced blocks,
|
|
12
|
+
* bullet lists) sits inside tags for inline structure. This is the
|
|
13
|
+
* multi-section case where both Anthropic and OpenAI guidance most clearly
|
|
14
|
+
* favors XML for unambiguous parsing. Each impl section is omitted when its
|
|
15
|
+
* source is empty so the prompt stays minimal when the generator made no
|
|
16
|
+
* meaningful contribution.
|
|
17
|
+
*/
|
|
18
|
+
function buildHybridPromptUserPrompt(ctx) {
|
|
19
|
+
const lines = [
|
|
20
|
+
`Complete the AI-driven step that follows the generator phase of a two-phase Nx migration. The deterministic generator phase has already run; the sections below summarize what it did. The step may apply additional changes, verify the generator's output, or both — follow the instructions file.`,
|
|
21
|
+
...(0, shared_rendering_1.renderMigrationBlock)(ctx),
|
|
22
|
+
];
|
|
23
|
+
const logs = (0, shared_rendering_1.escapeXmlBody)((0, shared_rendering_1.stripAnsi)(ctx.impl?.logs ?? '').trim());
|
|
24
|
+
const agentContext = (0, shared_rendering_1.filterNonEmptyStrings)(ctx.impl?.agentContext ?? []);
|
|
25
|
+
const hasDiffContext = !!ctx.impl?.hasDiffContext;
|
|
26
|
+
const hasChanges = !!ctx.impl?.changes && ctx.impl.changes.length > 0;
|
|
27
|
+
lines.push(...(0, shared_rendering_1.renderGeneratorOutputBlock)(logs));
|
|
28
|
+
if (hasDiffContext && hasChanges) {
|
|
29
|
+
// Live view via git. Suppressed when the generator made no changes —
|
|
30
|
+
// pointing the agent at `git status` for an empty diff is noise.
|
|
31
|
+
lines.push(``, `<inspect_changes>`, (0, shared_rendering_1.renderGitInspectInstruction)(), `</inspect_changes>`);
|
|
32
|
+
}
|
|
33
|
+
else if (!hasDiffContext) {
|
|
34
|
+
const embeddedFileList = renderFileList(ctx.impl?.changes);
|
|
35
|
+
if (embeddedFileList) {
|
|
36
|
+
lines.push(``, `<files_changed>`, embeddedFileList, `</files_changed>`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (agentContext.length > 0) {
|
|
40
|
+
lines.push(...(0, shared_rendering_1.renderAdvisoryContext)('hints from the generator phase; consult while following the instructions, not as separate tasks', agentContext));
|
|
41
|
+
}
|
|
42
|
+
lines.push(``, `<instructions_file>${(0, shared_rendering_1.escapeXmlBody)(ctx.promptPath)}</instructions_file>`, ``, `<precedence>If anything in the sections above conflicts with the instructions file, the instructions file wins.</precedence>`, ``, `Open the instructions file (path is workspace-relative), follow its instructions step by step using the sections above as context, then write your handoff JSON to:`, ...(0, shared_rendering_1.renderHandoffPathFooter)(ctx.handoffFileAbsolutePath));
|
|
43
|
+
return lines.join('\n');
|
|
44
|
+
}
|
|
45
|
+
function renderFileList(changes) {
|
|
46
|
+
if (!changes || changes.length === 0)
|
|
47
|
+
return '';
|
|
48
|
+
return changes
|
|
49
|
+
.map((change) => ({ ...change, path: (0, shared_rendering_1.escapeXmlBody)(change.path) }))
|
|
50
|
+
.map(shared_rendering_1.renderFileEntry)
|
|
51
|
+
.join('\n');
|
|
52
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface PromptMigrationContext {
|
|
2
|
+
package: string;
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
/** Workspace-relative path to the prompt `.md` file. */
|
|
7
|
+
promptPath: string;
|
|
8
|
+
/** Absolute path the agent must write its handoff file to. */
|
|
9
|
+
handoffFileAbsolutePath: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Builds the first user-facing message for a prompt-migration step.
|
|
13
|
+
*
|
|
14
|
+
* Keeps the framing short — the heavy lifting (handoff contract, scope rules)
|
|
15
|
+
* already lives in the system prompt; this message just identifies the
|
|
16
|
+
* migration and points at the instructions file.
|
|
17
|
+
*
|
|
18
|
+
* XML tags wrap path values and the migration metadata so the agent does
|
|
19
|
+
* not misread them as headers or prose.
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildPromptMigrationUserPrompt(ctx: PromptMigrationContext): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildPromptMigrationUserPrompt = buildPromptMigrationUserPrompt;
|
|
4
|
+
const shared_rendering_1 = require("./shared-rendering");
|
|
5
|
+
/**
|
|
6
|
+
* Builds the first user-facing message for a prompt-migration step.
|
|
7
|
+
*
|
|
8
|
+
* Keeps the framing short — the heavy lifting (handoff contract, scope rules)
|
|
9
|
+
* already lives in the system prompt; this message just identifies the
|
|
10
|
+
* migration and points at the instructions file.
|
|
11
|
+
*
|
|
12
|
+
* XML tags wrap path values and the migration metadata so the agent does
|
|
13
|
+
* not misread them as headers or prose.
|
|
14
|
+
*/
|
|
15
|
+
function buildPromptMigrationUserPrompt(ctx) {
|
|
16
|
+
const lines = [
|
|
17
|
+
`Apply one prompt-based migration to this Nx workspace.`,
|
|
18
|
+
...(0, shared_rendering_1.renderMigrationBlock)(ctx),
|
|
19
|
+
``,
|
|
20
|
+
`<instructions_file>${(0, shared_rendering_1.escapeXmlBody)(ctx.promptPath)}</instructions_file>`,
|
|
21
|
+
``,
|
|
22
|
+
`Open the instructions file (path is workspace-relative), follow its instructions step by step, then write your handoff JSON to:`,
|
|
23
|
+
...(0, shared_rendering_1.renderHandoffPathFooter)(ctx.handoffFileAbsolutePath),
|
|
24
|
+
];
|
|
25
|
+
return lines.join('\n');
|
|
26
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FileChange } from '../../../../generators/tree';
|
|
2
|
+
export declare function renderFileEntry(change: FileChange): string;
|
|
3
|
+
export declare function renderListItem(entry: string): string;
|
|
4
|
+
export declare function renderKeyMultilineValue(key: string, value: string): string[];
|
|
5
|
+
export declare function stripAnsi(text: string): string;
|
|
6
|
+
export declare function filterNonEmptyStrings(entries: unknown[]): string[];
|
|
7
|
+
export declare function escapeXmlBody(value: string): string;
|
|
8
|
+
export declare function renderGitInspectInstruction(): string;
|
|
9
|
+
export declare function renderGeneratorOutputBlock(logs: string): string[];
|
|
10
|
+
export interface MigrationBlockContext {
|
|
11
|
+
package: string;
|
|
12
|
+
name: string;
|
|
13
|
+
version: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function renderMigrationBlock(ctx: MigrationBlockContext): string[];
|
|
17
|
+
export declare function renderHandoffPathFooter(handoffFileAbsolutePath: string): string[];
|
|
18
|
+
export declare function renderAdvisoryContext(note: string, entries: string[]): string[];
|