nx 23.3.0-beta.2 → 23.3.0-beta.4
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 +7 -1
- package/dist/src/command-line/add/add.js +5 -1
- package/dist/src/command-line/init/implementation/utils.js +6 -1
- package/dist/src/command-line/migrate/agentic/capture-generator-output.d.ts +25 -0
- package/dist/src/command-line/migrate/agentic/capture-generator-output.js +121 -5
- package/dist/src/command-line/migrate/agentic/close-agent-session.d.ts +21 -0
- package/dist/src/command-line/migrate/agentic/close-agent-session.js +126 -0
- package/dist/src/command-line/migrate/agentic/definitions.d.ts +24 -0
- package/dist/src/command-line/migrate/agentic/definitions.js +5 -2
- package/dist/src/command-line/migrate/agentic/handoff.d.ts +23 -0
- package/dist/src/command-line/migrate/agentic/handoff.js +62 -3
- package/dist/src/command-line/migrate/agentic/master/invocations.d.ts +12 -0
- package/dist/src/command-line/migrate/agentic/master/invocations.js +54 -0
- package/dist/src/command-line/migrate/agentic/master/run-master-session.d.ts +12 -0
- package/dist/src/command-line/migrate/agentic/master/run-master-session.js +99 -0
- package/dist/src/command-line/migrate/agentic/master/spawn-master.d.ts +31 -0
- package/dist/src/command-line/migrate/agentic/master/spawn-master.js +217 -0
- package/dist/src/command-line/migrate/agentic/prompts/fragments.js +3 -0
- package/dist/src/command-line/migrate/agentic/runner.d.ts +0 -21
- package/dist/src/command-line/migrate/agentic/runner.js +12 -249
- package/dist/src/command-line/migrate/agentic/terminal-repair.d.ts +1 -0
- package/dist/src/command-line/migrate/agentic/terminal-repair.js +27 -0
- package/dist/src/command-line/migrate/agentic/windows-cmd.d.ts +33 -0
- package/dist/src/command-line/migrate/agentic/windows-cmd.js +88 -0
- package/dist/src/command-line/migrate/deferred-output.d.ts +44 -0
- package/dist/src/command-line/migrate/deferred-output.js +92 -0
- package/dist/src/command-line/migrate/execute-migration.d.ts +9 -3
- package/dist/src/command-line/migrate/execute-migration.js +53 -16
- package/dist/src/command-line/migrate/migrate-commits.d.ts +4 -4
- package/dist/src/command-line/migrate/migrate-commits.js +7 -6
- package/dist/src/command-line/migrate/migrate.js +28 -13
- package/dist/src/command-line/migrate/run/broker.d.ts +138 -0
- package/dist/src/command-line/migrate/run/broker.js +507 -0
- package/dist/src/command-line/migrate/run/clean-retry.d.ts +12 -0
- package/dist/src/command-line/migrate/run/clean-retry.js +98 -0
- package/dist/src/command-line/migrate/run/index.d.ts +4 -3
- package/dist/src/command-line/migrate/run/index.js +7 -1
- package/dist/src/command-line/migrate/run/issues.d.ts +8 -1
- package/dist/src/command-line/migrate/run/issues.js +40 -6
- package/dist/src/command-line/migrate/run/orchestrator.d.ts +18 -1
- package/dist/src/command-line/migrate/run/orchestrator.js +409 -377
- package/dist/src/command-line/migrate/run/run-state.d.ts +16 -0
- package/dist/src/command-line/migrate/run/run-state.js +33 -2
- package/dist/src/command-line/migrate/run/runbook.js +8 -4
- package/dist/src/command-line/migrate/run/state-machine.d.ts +24 -1
- package/dist/src/command-line/migrate/run/state-machine.js +112 -21
- package/dist/src/command-line/migrate/run/util.d.ts +2 -1
- package/dist/src/command-line/migrate/run/util.js +3 -3
- package/dist/src/command-line/migrate/run/worker.js +170 -164
- package/dist/src/core/graph/main.js +1 -1
- package/dist/src/daemon/server/server.js +11 -8
- package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
- package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
- package/dist/src/tasks-runner/run-command.js +3 -0
- package/dist/src/utils/git-utils.d.ts +12 -0
- package/dist/src/utils/git-utils.js +76 -30
- package/dist/src/utils/package-json.js +8 -0
- package/package.json +11 -11
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// A master session's agent runs the dispensed `nx migrate` commands inside
|
|
3
|
+
// its own sandbox, where a dependency install has no network and a commit
|
|
4
|
+
// cannot write `.git`. The parent nx that spawned the session advertises
|
|
5
|
+
// itself through NX_MIGRATE_BROKER, and a step then hands its install, and
|
|
6
|
+
// its commit when one is due, over a request/result file pair under
|
|
7
|
+
// <runDir>/broker/ instead of running them itself. Nothing here authorizes:
|
|
8
|
+
// every file the parent could consult is writable from the sandbox, so the
|
|
9
|
+
// parent's own invocation decides what it installs and commits.
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.MigrateCommitBroker = exports.TreeBusyError = exports.BrokerUnavailableError = exports.BrokerStaleRequestError = exports.BROKER_ENV_VAR = void 0;
|
|
12
|
+
exports.acquireTreeOperation = acquireTreeOperation;
|
|
13
|
+
exports.releaseTreeOperation = releaseTreeOperation;
|
|
14
|
+
exports.liveTreeOperation = liveTreeOperation;
|
|
15
|
+
exports.treeBusyMessage = treeBusyMessage;
|
|
16
|
+
exports.treeOperationLabel = treeOperationLabel;
|
|
17
|
+
exports.brokerDir = brokerDir;
|
|
18
|
+
exports.commitStepTree = commitStepTree;
|
|
19
|
+
exports.installStepTree = installStepTree;
|
|
20
|
+
exports.resetStepTree = resetStepTree;
|
|
21
|
+
const crypto_1 = require("crypto");
|
|
22
|
+
const fs_1 = require("fs");
|
|
23
|
+
const path_1 = require("path");
|
|
24
|
+
const native_1 = require("../../../native");
|
|
25
|
+
const fileutils_1 = require("../../../utils/fileutils");
|
|
26
|
+
const json_1 = require("../../../utils/json");
|
|
27
|
+
const handoff_1 = require("../agentic/handoff");
|
|
28
|
+
const deferred_output_1 = require("../deferred-output");
|
|
29
|
+
const execute_migration_1 = require("../execute-migration");
|
|
30
|
+
const migrate_commits_1 = require("../migrate-commits");
|
|
31
|
+
const atomic_write_1 = require("./atomic-write");
|
|
32
|
+
const run_state_1 = require("./run-state");
|
|
33
|
+
const state_lock_1 = require("./state-lock");
|
|
34
|
+
const state_machine_1 = require("./state-machine");
|
|
35
|
+
const issues_1 = require("./issues");
|
|
36
|
+
const clean_retry_1 = require("./clean-retry");
|
|
37
|
+
const util_1 = require("./util");
|
|
38
|
+
exports.BROKER_ENV_VAR = 'NX_MIGRATE_BROKER';
|
|
39
|
+
const BROKER_DIR_NAME = 'broker';
|
|
40
|
+
const CHILD_POLL_INTERVAL_MS = 250;
|
|
41
|
+
/** The request no longer matches the step: another attempt owns it. */
|
|
42
|
+
class BrokerStaleRequestError extends Error {
|
|
43
|
+
}
|
|
44
|
+
exports.BrokerStaleRequestError = BrokerStaleRequestError;
|
|
45
|
+
/**
|
|
46
|
+
* The advertised parent could not accept the request, or went away before
|
|
47
|
+
* answering it. It may have landed the install or the commit; the tree and
|
|
48
|
+
* the run state say.
|
|
49
|
+
*/
|
|
50
|
+
class BrokerUnavailableError extends Error {
|
|
51
|
+
}
|
|
52
|
+
exports.BrokerUnavailableError = BrokerUnavailableError;
|
|
53
|
+
/** Another live process holds the working tree for an operation of its own. */
|
|
54
|
+
class TreeBusyError extends Error {
|
|
55
|
+
}
|
|
56
|
+
exports.TreeBusyError = TreeBusyError;
|
|
57
|
+
/**
|
|
58
|
+
* Reserves the working tree for one operation in a single fresh-state write:
|
|
59
|
+
* the request must still be at its seam (else the attempt moved on and the
|
|
60
|
+
* request is stale), and no other live process may hold a reservation.
|
|
61
|
+
* A reservation whose owner process is gone holds nothing.
|
|
62
|
+
*/
|
|
63
|
+
function acquireTreeOperation(dir, request, owner = (0, crypto_1.randomBytes)(4).toString('hex')) {
|
|
64
|
+
// A commit marks its step as started; a mark already there belongs to an
|
|
65
|
+
// operation whose outcome is still unknown, and this one leaves it.
|
|
66
|
+
let marks = false;
|
|
67
|
+
(0, state_lock_1.updateRunState)(dir, (fresh) => {
|
|
68
|
+
if (!atSeam(fresh, request)) {
|
|
69
|
+
throw new BrokerStaleRequestError(`The request for this step no longer matches its attempt; nothing was installed or committed.`);
|
|
70
|
+
}
|
|
71
|
+
const held = liveTreeOperation(fresh, owner);
|
|
72
|
+
if (held)
|
|
73
|
+
throw new TreeBusyError(treeBusyMessage(held));
|
|
74
|
+
marks =
|
|
75
|
+
request.kind === 'commit' &&
|
|
76
|
+
fresh.steps.find((s) => s.id === request.stepId)?.commitStarted !== true;
|
|
77
|
+
return {
|
|
78
|
+
...(marks ? (0, state_machine_1.markCommitStarted)(fresh, request.stepId) : fresh),
|
|
79
|
+
treeOperation: {
|
|
80
|
+
kind: request.kind,
|
|
81
|
+
...(request.stepId !== undefined ? { stepId: request.stepId } : {}),
|
|
82
|
+
...(request.attempt !== undefined ? { attempt: request.attempt } : {}),
|
|
83
|
+
owner,
|
|
84
|
+
pid: process.pid,
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
const lease = {
|
|
89
|
+
owner,
|
|
90
|
+
...(marks ? { markedStepId: request.stepId } : {}),
|
|
91
|
+
release: () => releaseTreeOperation(dir, owner, lease.markedStepId),
|
|
92
|
+
};
|
|
93
|
+
return lease;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Owner-checked: a lease released late never drops a newer reservation, nor
|
|
97
|
+
* the mark it set.
|
|
98
|
+
*/
|
|
99
|
+
function releaseTreeOperation(dir, owner, markedStepId) {
|
|
100
|
+
(0, state_lock_1.updateRunState)(dir, (fresh) => {
|
|
101
|
+
if (fresh.treeOperation?.owner !== owner)
|
|
102
|
+
return null;
|
|
103
|
+
const released = { ...fresh, treeOperation: undefined };
|
|
104
|
+
return markedStepId ? (0, state_machine_1.clearCommitStarted)(released, markedStepId) : released;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/** The reservation a live process other than `owner` holds, if any. */
|
|
108
|
+
function liveTreeOperation(state, owner) {
|
|
109
|
+
const held = state.treeOperation;
|
|
110
|
+
if (!held || held.owner === owner || !(0, util_1.isPidAlive)(held.pid))
|
|
111
|
+
return undefined;
|
|
112
|
+
return held;
|
|
113
|
+
}
|
|
114
|
+
function treeBusyMessage(held) {
|
|
115
|
+
return `The working tree is held by process ${held.pid} for ${treeOperationLabel(held)}; run the reconcile again once it finishes.`;
|
|
116
|
+
}
|
|
117
|
+
function treeOperationLabel(held) {
|
|
118
|
+
return held.kind === 'checkpoint'
|
|
119
|
+
? 'the checkpoint commit'
|
|
120
|
+
: `the ${held.kind === 'commit' || held.kind === 'reset' ? held.kind : 'install'} of step '${held.stepId}'`;
|
|
121
|
+
}
|
|
122
|
+
function atSeam(state, request) {
|
|
123
|
+
if (request.kind === 'checkpoint') {
|
|
124
|
+
return (state.createCommits &&
|
|
125
|
+
state.checkpointFailed === true &&
|
|
126
|
+
state.steps.every((s) => s.status === 'pending'));
|
|
127
|
+
}
|
|
128
|
+
return (Object.hasOwn(SEAM_STATUSES, request.kind) &&
|
|
129
|
+
request.stepId !== undefined &&
|
|
130
|
+
request.attempt !== undefined &&
|
|
131
|
+
isAtSeam(state.steps.find((s) => s.id === request.stepId), request));
|
|
132
|
+
}
|
|
133
|
+
const SEAM_STATUSES = {
|
|
134
|
+
commit: new Set(['running', 'awaiting-prompt-outcome', 'died']),
|
|
135
|
+
install: new Set(['running']),
|
|
136
|
+
'fold-install': new Set(['awaiting-prompt-outcome']),
|
|
137
|
+
'action-install': new Set(['failed', 'died']),
|
|
138
|
+
reset: new Set(['failed', 'died']),
|
|
139
|
+
};
|
|
140
|
+
function isAtSeam(step, request) {
|
|
141
|
+
return (step !== undefined &&
|
|
142
|
+
step.attempt === request.attempt &&
|
|
143
|
+
SEAM_STATUSES[request.kind].has(step.status));
|
|
144
|
+
}
|
|
145
|
+
function brokerDir(runDirPath) {
|
|
146
|
+
return (0, path_1.join)(runDirPath, BROKER_DIR_NAME);
|
|
147
|
+
}
|
|
148
|
+
function lockPath(runDirPath, nonce) {
|
|
149
|
+
return (0, path_1.join)(brokerDir(runDirPath), `${nonce}.lock`);
|
|
150
|
+
}
|
|
151
|
+
function requestPath(runDirPath, id) {
|
|
152
|
+
return (0, path_1.join)(brokerDir(runDirPath), `${id}.request.json`);
|
|
153
|
+
}
|
|
154
|
+
function resultPath(runDirPath, id) {
|
|
155
|
+
return (0, path_1.join)(brokerDir(runDirPath), `${id}.result.json`);
|
|
156
|
+
}
|
|
157
|
+
// A request file lives in the agent-writable broker directory, so it could be
|
|
158
|
+
// a planted symlink or FIFO; read it without reading a symlink's target or
|
|
159
|
+
// blocking on a FIFO.
|
|
160
|
+
function readRequestFile(filePath) {
|
|
161
|
+
return (0, json_1.parseJson)((0, handoff_1.readAtomicallyPublishedFile)(filePath, `${filePath} is not a regular file.`));
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Runs the step's install and commit where they can land: in this process
|
|
165
|
+
* unless a parent session advertised its broker, in which case the request
|
|
166
|
+
* goes to the parent and the answer comes back with the output the parent
|
|
167
|
+
* collected, printed here. The absorbed step ids come from whichever side
|
|
168
|
+
* ran the commit, so the ledger entry names what its `git add -A` took.
|
|
169
|
+
*/
|
|
170
|
+
async function commitStepTree(dir, step, absorbedStepIds, commitInProcess, scope) {
|
|
171
|
+
const request = {
|
|
172
|
+
kind: 'commit',
|
|
173
|
+
stepId: step.id,
|
|
174
|
+
attempt: step.attempt,
|
|
175
|
+
};
|
|
176
|
+
const nonce = process.env[exports.BROKER_ENV_VAR];
|
|
177
|
+
if (!nonce) {
|
|
178
|
+
const lease = acquireTreeOperation(dir, request);
|
|
179
|
+
scope.lease = lease;
|
|
180
|
+
const result = await commitInProcess();
|
|
181
|
+
if (gitRan(result))
|
|
182
|
+
lease.markedStepId = undefined;
|
|
183
|
+
return { result, absorbedStepIds, recorded: false };
|
|
184
|
+
}
|
|
185
|
+
const answer = await ask(dir, nonce, request);
|
|
186
|
+
if (answer.kind !== 'commit') {
|
|
187
|
+
throw new Error(`Unexpected '${answer.kind}' answer to a commit request.`);
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
result: answer.result,
|
|
191
|
+
absorbedStepIds: answer.absorbedStepIds,
|
|
192
|
+
recorded: true,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
// Whether git may have written history for this result. A landed commit's
|
|
196
|
+
// mark is the ledger entry's to clear, and a failure reported once git ran
|
|
197
|
+
// (a hook's output overflowing the subprocess buffer after the commit) cannot
|
|
198
|
+
// vouch that nothing landed, so only the other results release the mark.
|
|
199
|
+
function gitRan(result) {
|
|
200
|
+
switch (result.status) {
|
|
201
|
+
case 'committed':
|
|
202
|
+
case 'failed':
|
|
203
|
+
return true;
|
|
204
|
+
case 'no-changes':
|
|
205
|
+
case 'disabled':
|
|
206
|
+
return false;
|
|
207
|
+
default: {
|
|
208
|
+
const exhaustive = result;
|
|
209
|
+
throw new Error(`Unhandled commit result: ${JSON.stringify(exhaustive)}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* The same for a step that owes only its install: no commit is due, or the
|
|
215
|
+
* commit waits for a fold.
|
|
216
|
+
*/
|
|
217
|
+
async function installStepTree(dir, step, seam, installInProcess, scope) {
|
|
218
|
+
const request = {
|
|
219
|
+
kind: seam,
|
|
220
|
+
stepId: step.id,
|
|
221
|
+
attempt: step.attempt,
|
|
222
|
+
};
|
|
223
|
+
const nonce = process.env[exports.BROKER_ENV_VAR];
|
|
224
|
+
if (!nonce) {
|
|
225
|
+
scope.lease = acquireTreeOperation(dir, request);
|
|
226
|
+
return installInProcess();
|
|
227
|
+
}
|
|
228
|
+
const answer = await ask(dir, nonce, request);
|
|
229
|
+
if (answer.kind !== 'installed') {
|
|
230
|
+
throw new Error(`Unexpected '${answer.kind}' answer to an install request.`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* The same for the reset a clean retry of a failed or died step needs. Runs
|
|
235
|
+
* `resetInProcess` under the reservation, or asks the parent, which resets
|
|
236
|
+
* against the state it reads then; a reset that could not run throws.
|
|
237
|
+
*/
|
|
238
|
+
async function resetStepTree(dir, step, resetInProcess, scope) {
|
|
239
|
+
const request = {
|
|
240
|
+
kind: 'reset',
|
|
241
|
+
stepId: step.id,
|
|
242
|
+
attempt: step.attempt,
|
|
243
|
+
invocation: (0, crypto_1.randomBytes)(4).toString('hex'),
|
|
244
|
+
};
|
|
245
|
+
const nonce = process.env[exports.BROKER_ENV_VAR];
|
|
246
|
+
if (!nonce) {
|
|
247
|
+
scope.lease = acquireTreeOperation(dir, request);
|
|
248
|
+
return resetInProcess();
|
|
249
|
+
}
|
|
250
|
+
const answer = await ask(dir, nonce, request);
|
|
251
|
+
if (answer.kind !== 'reset') {
|
|
252
|
+
throw new Error(`Unexpected '${answer.kind}' answer to a reset request.`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
async function ask(dir, nonce, request) {
|
|
256
|
+
const id = `${nonce}-${request.stepId}-${request.attempt}-${request.kind}${request.invocation ? `-${request.invocation}` : ''}`;
|
|
257
|
+
const path = resultPath(dir, id);
|
|
258
|
+
// A repeat reads the first answer, whatever became of the session since.
|
|
259
|
+
if ((0, fs_1.existsSync)(path)) {
|
|
260
|
+
return settle((0, fileutils_1.readJsonFile)(path));
|
|
261
|
+
}
|
|
262
|
+
// No deadline: an install or a commit over a large tree takes as long as it
|
|
263
|
+
// takes; the poll ends with an answer or a released lock. The probe is built
|
|
264
|
+
// first so a request is never left unwatched, and once: each instance holds
|
|
265
|
+
// a descriptor, and `wait()` would pin this process until the session ends.
|
|
266
|
+
let lock = null;
|
|
267
|
+
try {
|
|
268
|
+
lock = native_1.IS_WASM ? null : new native_1.FileLock(lockPath(dir, nonce));
|
|
269
|
+
}
|
|
270
|
+
catch (e) {
|
|
271
|
+
if ((0, fs_1.existsSync)(path)) {
|
|
272
|
+
return settle((0, fileutils_1.readJsonFile)(path));
|
|
273
|
+
}
|
|
274
|
+
throw notAccepting(e);
|
|
275
|
+
}
|
|
276
|
+
try {
|
|
277
|
+
(0, atomic_write_1.publishFileAtomically)(requestPath(dir, id), (tmpPath) => (0, fileutils_1.writeJsonFile)(tmpPath, request));
|
|
278
|
+
}
|
|
279
|
+
catch (e) {
|
|
280
|
+
throw notAccepting(e);
|
|
281
|
+
}
|
|
282
|
+
for (;;) {
|
|
283
|
+
if ((0, fs_1.existsSync)(path)) {
|
|
284
|
+
return settle((0, fileutils_1.readJsonFile)(path));
|
|
285
|
+
}
|
|
286
|
+
if (lock && lockIsFree(lock)) {
|
|
287
|
+
// Answered and closed between the two checks: the answer stays on disk.
|
|
288
|
+
if ((0, fs_1.existsSync)(path))
|
|
289
|
+
continue;
|
|
290
|
+
throw new BrokerUnavailableError(`The nx migrate session that started this step ended before its request was answered. The install or the commit may still have landed; check the working tree and git log.`);
|
|
291
|
+
}
|
|
292
|
+
await new Promise((resolve) => setTimeout(resolve, CHILD_POLL_INTERVAL_MS));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function notAccepting(e) {
|
|
296
|
+
return new BrokerUnavailableError(`The nx migrate session that started this step is not accepting its request (${e instanceof Error ? e.message : String(e)}).`);
|
|
297
|
+
}
|
|
298
|
+
// A probe that fails says nothing about the parent; keep waiting.
|
|
299
|
+
function lockIsFree(lock) {
|
|
300
|
+
try {
|
|
301
|
+
return !lock.check();
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function settle(result) {
|
|
308
|
+
switch (result.kind) {
|
|
309
|
+
case 'commit':
|
|
310
|
+
case 'installed':
|
|
311
|
+
(0, deferred_output_1.replayDeferredOutput)(result.output);
|
|
312
|
+
return result;
|
|
313
|
+
case 'install-failed':
|
|
314
|
+
(0, deferred_output_1.replayDeferredOutput)(result.output);
|
|
315
|
+
// The CLI catch returns 1 on the typed error instead of logging again.
|
|
316
|
+
throw result.peerDeps
|
|
317
|
+
? new execute_migration_1.NpmPeerDepsInstallError()
|
|
318
|
+
: new Error(result.message);
|
|
319
|
+
case 'reset':
|
|
320
|
+
if (result.error !== undefined)
|
|
321
|
+
throw new Error(result.error);
|
|
322
|
+
return result;
|
|
323
|
+
case 'stale':
|
|
324
|
+
throw new BrokerStaleRequestError(`The request for this step no longer matches its attempt; nothing was installed or committed.`);
|
|
325
|
+
default: {
|
|
326
|
+
const exhaustive = result;
|
|
327
|
+
throw new Error(`Unhandled broker result: ${JSON.stringify(exhaustive)}`);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* The parent side. Holds one exclusive lock for the session's lifetime so a
|
|
333
|
+
* waiting step can tell a slow parent from a dead one, answers each request
|
|
334
|
+
* once, and removes its own requests on close; its answers stay for the steps
|
|
335
|
+
* still reading them. Requests carrying another session's nonce belong to
|
|
336
|
+
* that session and are never touched. Whether to install or commit comes from
|
|
337
|
+
* the policy the session started with, never from run state, which the
|
|
338
|
+
* agent's sandbox can write.
|
|
339
|
+
*/
|
|
340
|
+
class MigrateCommitBroker {
|
|
341
|
+
constructor(root, dir, reconcileCommand, policy) {
|
|
342
|
+
this.root = root;
|
|
343
|
+
this.dir = dir;
|
|
344
|
+
this.reconcileCommand = reconcileCommand;
|
|
345
|
+
this.policy = policy;
|
|
346
|
+
this.nonce = (0, crypto_1.randomBytes)(4).toString('hex');
|
|
347
|
+
this.handled = new Set();
|
|
348
|
+
this.inFlight = null;
|
|
349
|
+
(0, handoff_1.ensureRunSubdir)(brokerDir(dir), () => this.notADirectory());
|
|
350
|
+
this.lock = native_1.IS_WASM ? null : new native_1.FileLock(lockPath(dir, this.nonce));
|
|
351
|
+
this.lock?.lock();
|
|
352
|
+
}
|
|
353
|
+
/** The request whose operation this process is running right now. */
|
|
354
|
+
get requestInFlight() {
|
|
355
|
+
return this.inFlight;
|
|
356
|
+
}
|
|
357
|
+
/** Answers this session's unanswered requests, one at a time. */
|
|
358
|
+
async service() {
|
|
359
|
+
// Refused rather than followed: a symlink swapped in would send the reads
|
|
360
|
+
// and the answers wherever it points, or leave requests unanswered.
|
|
361
|
+
if ((0, handoff_1.handoffsDirState)(brokerDir(this.dir)) !== 'directory') {
|
|
362
|
+
throw this.notADirectory();
|
|
363
|
+
}
|
|
364
|
+
const prefix = `${this.nonce}-`;
|
|
365
|
+
const suffix = '.request.json';
|
|
366
|
+
for (const name of (0, fs_1.readdirSync)(brokerDir(this.dir))) {
|
|
367
|
+
if (!name.startsWith(prefix) || !name.endsWith(suffix))
|
|
368
|
+
continue;
|
|
369
|
+
const id = name.slice(0, -suffix.length);
|
|
370
|
+
if (this.handled.has(id))
|
|
371
|
+
continue;
|
|
372
|
+
const request = readRequestFile(requestPath(this.dir, id));
|
|
373
|
+
// Reserved before anything runs, released after the record is written.
|
|
374
|
+
// A tree held by another live process is left for a later pass, not
|
|
375
|
+
// marked handled; a request no longer at its seam is answered stale.
|
|
376
|
+
let lease = null;
|
|
377
|
+
try {
|
|
378
|
+
lease = acquireTreeOperation(this.dir, request, this.nonce);
|
|
379
|
+
}
|
|
380
|
+
catch (e) {
|
|
381
|
+
if (e instanceof TreeBusyError)
|
|
382
|
+
continue;
|
|
383
|
+
if (!(e instanceof BrokerStaleRequestError))
|
|
384
|
+
throw e;
|
|
385
|
+
}
|
|
386
|
+
this.handled.add(id);
|
|
387
|
+
let result;
|
|
388
|
+
try {
|
|
389
|
+
if (lease)
|
|
390
|
+
this.inFlight = request;
|
|
391
|
+
result = lease ? await this.answer(request) : { kind: 'stale' };
|
|
392
|
+
// Recorded by the process that ran the commit, before the answer: the
|
|
393
|
+
// step reading it can die with the commit already in history. A failed
|
|
394
|
+
// record throws and ends the session rather than losing the entry.
|
|
395
|
+
if (result.kind === 'commit') {
|
|
396
|
+
if (gitRan(result.result))
|
|
397
|
+
lease.markedStepId = undefined;
|
|
398
|
+
this.record(request, result);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
finally {
|
|
402
|
+
this.inFlight = null;
|
|
403
|
+
lease?.release();
|
|
404
|
+
}
|
|
405
|
+
// Published after the release, so the step reading the answer never
|
|
406
|
+
// finds this request's reservation still standing over its own write.
|
|
407
|
+
(0, atomic_write_1.publishFileAtomically)(resultPath(this.dir, id), (tmpPath) => (0, fileutils_1.writeJsonFile)(tmpPath, result));
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
// Appends the entry and leaves the step a receipt for it, on the attempt the
|
|
411
|
+
// request named: a rearmed step owes nothing to the old attempt's commit.
|
|
412
|
+
record(request, result) {
|
|
413
|
+
const entry = (0, state_machine_1.commitResultToLedgerEntry)(result.result, request.stepId, result.absorbedStepIds);
|
|
414
|
+
if (!entry)
|
|
415
|
+
return;
|
|
416
|
+
(0, state_lock_1.updateRunState)(this.dir, (fresh) => {
|
|
417
|
+
const index = fresh.commits.length;
|
|
418
|
+
const next = (0, state_machine_1.appendCommit)(fresh, (0, issues_1.attachIssueIdsToCommitEntry)(fresh, entry));
|
|
419
|
+
return {
|
|
420
|
+
...next,
|
|
421
|
+
steps: next.steps.map((s) => s.id === request.stepId && s.attempt === request.attempt
|
|
422
|
+
? { ...s, commitLedgerIndex: index }
|
|
423
|
+
: s),
|
|
424
|
+
};
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
async answer(request) {
|
|
428
|
+
const state = (0, run_state_1.readRunState)(this.dir);
|
|
429
|
+
const step = state.steps.find((s) => s.id === request.stepId);
|
|
430
|
+
if (!Object.hasOwn(SEAM_STATUSES, request.kind) ||
|
|
431
|
+
!isAtSeam(step, request) ||
|
|
432
|
+
((request.kind === 'commit' || request.kind === 'reset') &&
|
|
433
|
+
!this.policy.createCommits)) {
|
|
434
|
+
return { kind: 'stale' };
|
|
435
|
+
}
|
|
436
|
+
if (request.kind === 'reset') {
|
|
437
|
+
try {
|
|
438
|
+
(0, clean_retry_1.resetForCleanRetry)(this.root, this.dir, step.id);
|
|
439
|
+
return { kind: 'reset' };
|
|
440
|
+
}
|
|
441
|
+
catch (e) {
|
|
442
|
+
return {
|
|
443
|
+
kind: 'reset',
|
|
444
|
+
error: e instanceof Error ? e.message : String(e),
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
const output = new deferred_output_1.DeferredOutputCollector();
|
|
449
|
+
const install = () => (0, util_1.installDepsChangedSinceDispense)(this.root, this.dir, step, this.policy.skipInstall, this.reconcileCommand, output);
|
|
450
|
+
try {
|
|
451
|
+
if (request.kind !== 'commit') {
|
|
452
|
+
await install();
|
|
453
|
+
return { kind: 'installed', output: output.render('drop') };
|
|
454
|
+
}
|
|
455
|
+
const absorbedStepIds = (0, state_machine_1.uncoveredFailedStepIds)(state).filter((id) => id !== step.id);
|
|
456
|
+
const result = await (0, migrate_commits_1.commitMigrationIfRequested)(this.root, { name: (0, state_machine_1.splitMigrationId)(step.migrationId).name }, true, state.commitPrefix, install, (0, state_machine_1.stepsToPendingMigrations)(state, absorbedStepIds), undefined, output);
|
|
457
|
+
return {
|
|
458
|
+
kind: 'commit',
|
|
459
|
+
result,
|
|
460
|
+
absorbedStepIds,
|
|
461
|
+
output: output.render('drop'),
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
catch (e) {
|
|
465
|
+
// The install is the only thing that throws: the commit reports through
|
|
466
|
+
// its result, and the install's own bookkeeping never throws. Marked
|
|
467
|
+
// here, where the install ran, on the attempt it ran for: a reconcile
|
|
468
|
+
// may have rearmed the step meanwhile, and that attempt owes nothing.
|
|
469
|
+
(0, state_lock_1.updateRunState)(this.dir, (fresh) => isAtSeam(fresh.steps.find((s) => s.id === step.id), request)
|
|
470
|
+
? (0, state_machine_1.markInstallFailed)(fresh, step.id)
|
|
471
|
+
: null);
|
|
472
|
+
return {
|
|
473
|
+
kind: 'install-failed',
|
|
474
|
+
message: e instanceof Error ? e.message : String(e),
|
|
475
|
+
peerDeps: e instanceof execute_migration_1.NpmPeerDepsInstallError,
|
|
476
|
+
// The package manager's own output: for pnpm, Yarn and Bun the error
|
|
477
|
+
// says only that the command failed.
|
|
478
|
+
output: output.render('keep'),
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
/** Releases the lock; call after the last `service` settled. */
|
|
483
|
+
close() {
|
|
484
|
+
this.lock?.unlock();
|
|
485
|
+
// A reservation this session still holds would only expire with its pid.
|
|
486
|
+
try {
|
|
487
|
+
releaseTreeOperation(this.dir, this.nonce);
|
|
488
|
+
}
|
|
489
|
+
catch { }
|
|
490
|
+
// Hygiene only; a file left behind is never read by another session.
|
|
491
|
+
try {
|
|
492
|
+
if ((0, handoff_1.handoffsDirState)(brokerDir(this.dir)) !== 'directory')
|
|
493
|
+
return;
|
|
494
|
+
for (const name of (0, fs_1.readdirSync)(brokerDir(this.dir))) {
|
|
495
|
+
if (name === `${this.nonce}.lock` ||
|
|
496
|
+
(name.startsWith(`${this.nonce}-`) && name.endsWith('.request.json'))) {
|
|
497
|
+
(0, fs_1.rmSync)((0, path_1.join)(brokerDir(this.dir), name), { force: true });
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
catch { }
|
|
502
|
+
}
|
|
503
|
+
notADirectory() {
|
|
504
|
+
return new Error(`The migrate run has something other than a directory at ${brokerDir(this.dir)}; remove it and try again.`);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
exports.MigrateCommitBroker = MigrateCommitBroker;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { MigrateRunState, MigrateStep } from './run-state';
|
|
2
|
+
export declare function canOfferCleanRetry(root: string, state: MigrateRunState, step: MigrateStep, head: string | null): boolean;
|
|
3
|
+
export declare function cleanRetryUnavailableReason(root: string, state: MigrateRunState, step: MigrateStep, head: string | null): string;
|
|
4
|
+
/**
|
|
5
|
+
* The reset a clean retry of `stepId` needs, run with the tree reserved. The
|
|
6
|
+
* retry is re-checked against the state read then, and the attempt's
|
|
7
|
+
* generator run and the fixes its resolutions claimed are forgotten in a
|
|
8
|
+
* write of their own before git runs, so a reset that fails midway leaves
|
|
9
|
+
* the plain retry gated. Throws the reason when the retry is no longer
|
|
10
|
+
* available, or what git said when the reset fails.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resetForCleanRetry(root: string, dir: string, stepId: string): void;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.canOfferCleanRetry = canOfferCleanRetry;
|
|
4
|
+
exports.cleanRetryUnavailableReason = cleanRetryUnavailableReason;
|
|
5
|
+
exports.resetForCleanRetry = resetForCleanRetry;
|
|
6
|
+
const git_utils_1 = require("../../../utils/git-utils");
|
|
7
|
+
const types_1 = require("../agentic/types");
|
|
8
|
+
const agent_output_1 = require("./agent-output");
|
|
9
|
+
const issues_1 = require("./issues");
|
|
10
|
+
const state_lock_1 = require("./state-lock");
|
|
11
|
+
const state_machine_1 = require("./state-machine");
|
|
12
|
+
const util_1 = require("./util");
|
|
13
|
+
// A clean retry resets the tree to the step's `gitRefBefore`, discarding
|
|
14
|
+
// everything the ref does not account for. It is offered only when it does
|
|
15
|
+
// account for the whole tree: every prior diff committed, the tree clean when
|
|
16
|
+
// the step was dispensed, and HEAD still at the ref. An absent or unreadable
|
|
17
|
+
// value is no restore point, never a clean one. The debt check is run-wide:
|
|
18
|
+
// the reset discards every step's uncommitted work, not only this one's.
|
|
19
|
+
function canOfferCleanRetry(root, state, step, head) {
|
|
20
|
+
return (state.createCommits &&
|
|
21
|
+
!state.checkpointFailed &&
|
|
22
|
+
!(0, state_machine_1.hasPendingCommitDebt)(state) &&
|
|
23
|
+
!!step.gitRefBefore &&
|
|
24
|
+
head === step.gitRefBefore &&
|
|
25
|
+
step.treeCleanAtDispense === true &&
|
|
26
|
+
!endangeredLandedEntry(root, state, step));
|
|
27
|
+
}
|
|
28
|
+
// The last landed entry covering the step whose commit a reset to the step's
|
|
29
|
+
// `gitRefBefore` would discard: one that is not a verified ancestor of it.
|
|
30
|
+
function endangeredLandedEntry(root, state, step) {
|
|
31
|
+
let endangered = null;
|
|
32
|
+
for (const entry of (0, state_machine_1.coveringLandedEntries)(state, step.id)) {
|
|
33
|
+
if (!entry.sha ||
|
|
34
|
+
!step.gitRefBefore ||
|
|
35
|
+
!(0, git_utils_1.isAncestorCommit)(entry.sha, step.gitRefBefore, root)) {
|
|
36
|
+
endangered = entry;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return endangered;
|
|
40
|
+
}
|
|
41
|
+
function cleanRetryUnavailableReason(root, state, step, head) {
|
|
42
|
+
const endangered = endangeredLandedEntry(root, state, step);
|
|
43
|
+
if (endangered) {
|
|
44
|
+
return endangered.sha
|
|
45
|
+
? `this migration's changes already landed in commit ${endangered.sha}, which a reset would discard.`
|
|
46
|
+
: `this migration's changes already landed in a commit, which a reset would discard.`;
|
|
47
|
+
}
|
|
48
|
+
if (step.gitRefBefore && head !== step.gitRefBefore) {
|
|
49
|
+
return `HEAD is at ${head ?? '(unreadable)'} rather than the ${step.gitRefBefore} this migration started from, so a reset would discard what was committed in between.`;
|
|
50
|
+
}
|
|
51
|
+
return `resetting the tree could discard uncommitted work that no restore point accounts for.`;
|
|
52
|
+
}
|
|
53
|
+
// Best-effort: run.json records the reverted dispositions and stays
|
|
54
|
+
// authoritative, so a failed append loses only the archive's trail record of
|
|
55
|
+
// the revert.
|
|
56
|
+
function archiveReopenedResolutions(dir, state, updates, migrationId) {
|
|
57
|
+
if (updates.length === 0)
|
|
58
|
+
return;
|
|
59
|
+
const reconstructedIds = [];
|
|
60
|
+
try {
|
|
61
|
+
(0, issues_1.archiveIssues)(dir, { state, newIssues: [], updates }, reconstructedIds);
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
(0, agent_output_1.warnToAgent)({
|
|
65
|
+
title: `The reverted issue resolutions for ${migrationId} could not be archived (${(0, util_1.summarizeError)(e)}).`,
|
|
66
|
+
bodyLines: [
|
|
67
|
+
`run.json stays authoritative for the dispositions; the archived files under the run's issues directory miss the revert records, so their last entries may still read resolved.`,
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
(0, issues_1.warnReconstructedArchives)(reconstructedIds);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The reset a clean retry of `stepId` needs, run with the tree reserved. The
|
|
75
|
+
* retry is re-checked against the state read then, and the attempt's
|
|
76
|
+
* generator run and the fixes its resolutions claimed are forgotten in a
|
|
77
|
+
* write of their own before git runs, so a reset that fails midway leaves
|
|
78
|
+
* the plain retry gated. Throws the reason when the retry is no longer
|
|
79
|
+
* available, or what git said when the reset fails.
|
|
80
|
+
*/
|
|
81
|
+
function resetForCleanRetry(root, dir, stepId) {
|
|
82
|
+
const head = (0, git_utils_1.getLatestCommitSha)(root);
|
|
83
|
+
let step;
|
|
84
|
+
let updates = [];
|
|
85
|
+
const prepared = (0, state_lock_1.updateRunState)(dir, (fresh) => {
|
|
86
|
+
step = fresh.steps.find((s) => s.id === stepId);
|
|
87
|
+
if (!step)
|
|
88
|
+
throw new Error(`step '${stepId}' is not in the run.`);
|
|
89
|
+
if (!canOfferCleanRetry(root, fresh, step, head)) {
|
|
90
|
+
throw new Error(cleanRetryUnavailableReason(root, fresh, step, head));
|
|
91
|
+
}
|
|
92
|
+
const reopened = (0, issues_1.reopenResolutionsForStep)((0, state_machine_1.discardGeneratorRun)(fresh, stepId), stepId);
|
|
93
|
+
updates = reopened.updates;
|
|
94
|
+
return reopened.state;
|
|
95
|
+
});
|
|
96
|
+
archiveReopenedResolutions(dir, prepared, updates, step.migrationId);
|
|
97
|
+
(0, git_utils_1.resetWorkingTree)(step.gitRefBefore, [types_1.MIGRATE_RUNS_RELATIVE_DIR], root);
|
|
98
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
export { CURRENT_RUN_STATE_FORMAT_VERSION, NewerRunStateFormatError, migrateRunsDir, runDir, readRunState, writeRunState, findActiveRun, createRun, } from './run-state';
|
|
2
|
-
export type { MigrateRunStatus, MigrateRunRound, MigrateStepStatus, PromptOutcomeStatus, MigrateStepAwaitingKind, MigrateStepOutcome, MigrateStepPromptOutcome, MigrateStep, MigrateCommitKind, MigrateCommitLedgerEntry, MigrateIssueDisposition, MigrateRunIssue, MigrateRunAnalytics, MigrateRunNoProgress, MigrateRunState, } from './run-state';
|
|
1
|
+
export { CURRENT_RUN_STATE_FORMAT_VERSION, NewerRunStateFormatError, migrateRunsDir, runDir, runHandoffsDir, readRunState, writeRunState, findActiveRun, createRun, } from './run-state';
|
|
2
|
+
export type { MigrateRunStatus, MigrateRunRound, MigrateStepStatus, PromptOutcomeStatus, MigrateStepAwaitingKind, MigrateStepOutcome, MigrateStepPromptOutcome, MigrateStep, MigrateCommitKind, MigrateCommitLedgerEntry, MigrateIssueDisposition, MigrateRunIssue, MigrateRunAnalytics, MigrateRunNoProgress, MigrateRunPolicy, MigrateRunState, } from './run-state';
|
|
3
3
|
export { applyStepEvent, hasPendingCommitDebt } from './state-machine';
|
|
4
4
|
export type { StepAction, StepEvent, ApplyStepEventResult, } from './state-machine';
|
|
5
5
|
export { createRunId, computePlanHash } from './run-id';
|
|
6
6
|
export { runSingleMigrationWorker } from './worker';
|
|
7
7
|
export type { RunSingleMigrationWorkerInput } from './worker';
|
|
8
|
-
export { runOrchestratorInit, runOrchestratorReconcile } from './orchestrator';
|
|
8
|
+
export { completionWarnings, runOrchestratorInit, runOrchestratorReconcile, } from './orchestrator';
|
|
9
9
|
export type { RunOrchestratorInitInput, RunOrchestratorReconcileInput, } from './orchestrator';
|
|
10
|
+
export { BROKER_ENV_VAR, MigrateCommitBroker, treeOperationLabel, } from './broker';
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.runOrchestratorReconcile = exports.runOrchestratorInit = exports.runSingleMigrationWorker = exports.computePlanHash = exports.createRunId = exports.hasPendingCommitDebt = exports.applyStepEvent = exports.createRun = exports.findActiveRun = exports.writeRunState = exports.readRunState = exports.runDir = exports.migrateRunsDir = exports.NewerRunStateFormatError = exports.CURRENT_RUN_STATE_FORMAT_VERSION = void 0;
|
|
3
|
+
exports.treeOperationLabel = exports.MigrateCommitBroker = exports.BROKER_ENV_VAR = exports.runOrchestratorReconcile = exports.runOrchestratorInit = exports.completionWarnings = exports.runSingleMigrationWorker = exports.computePlanHash = exports.createRunId = exports.hasPendingCommitDebt = exports.applyStepEvent = exports.createRun = exports.findActiveRun = exports.writeRunState = exports.readRunState = exports.runHandoffsDir = exports.runDir = exports.migrateRunsDir = exports.NewerRunStateFormatError = exports.CURRENT_RUN_STATE_FORMAT_VERSION = void 0;
|
|
4
4
|
var run_state_1 = require("./run-state");
|
|
5
5
|
Object.defineProperty(exports, "CURRENT_RUN_STATE_FORMAT_VERSION", { enumerable: true, get: function () { return run_state_1.CURRENT_RUN_STATE_FORMAT_VERSION; } });
|
|
6
6
|
Object.defineProperty(exports, "NewerRunStateFormatError", { enumerable: true, get: function () { return run_state_1.NewerRunStateFormatError; } });
|
|
7
7
|
Object.defineProperty(exports, "migrateRunsDir", { enumerable: true, get: function () { return run_state_1.migrateRunsDir; } });
|
|
8
8
|
Object.defineProperty(exports, "runDir", { enumerable: true, get: function () { return run_state_1.runDir; } });
|
|
9
|
+
Object.defineProperty(exports, "runHandoffsDir", { enumerable: true, get: function () { return run_state_1.runHandoffsDir; } });
|
|
9
10
|
Object.defineProperty(exports, "readRunState", { enumerable: true, get: function () { return run_state_1.readRunState; } });
|
|
10
11
|
Object.defineProperty(exports, "writeRunState", { enumerable: true, get: function () { return run_state_1.writeRunState; } });
|
|
11
12
|
Object.defineProperty(exports, "findActiveRun", { enumerable: true, get: function () { return run_state_1.findActiveRun; } });
|
|
@@ -19,5 +20,10 @@ Object.defineProperty(exports, "computePlanHash", { enumerable: true, get: funct
|
|
|
19
20
|
var worker_1 = require("./worker");
|
|
20
21
|
Object.defineProperty(exports, "runSingleMigrationWorker", { enumerable: true, get: function () { return worker_1.runSingleMigrationWorker; } });
|
|
21
22
|
var orchestrator_1 = require("./orchestrator");
|
|
23
|
+
Object.defineProperty(exports, "completionWarnings", { enumerable: true, get: function () { return orchestrator_1.completionWarnings; } });
|
|
22
24
|
Object.defineProperty(exports, "runOrchestratorInit", { enumerable: true, get: function () { return orchestrator_1.runOrchestratorInit; } });
|
|
23
25
|
Object.defineProperty(exports, "runOrchestratorReconcile", { enumerable: true, get: function () { return orchestrator_1.runOrchestratorReconcile; } });
|
|
26
|
+
var broker_1 = require("./broker");
|
|
27
|
+
Object.defineProperty(exports, "BROKER_ENV_VAR", { enumerable: true, get: function () { return broker_1.BROKER_ENV_VAR; } });
|
|
28
|
+
Object.defineProperty(exports, "MigrateCommitBroker", { enumerable: true, get: function () { return broker_1.MigrateCommitBroker; } });
|
|
29
|
+
Object.defineProperty(exports, "treeOperationLabel", { enumerable: true, get: function () { return broker_1.treeOperationLabel; } });
|