@prestyj/cli 5.20.0 → 5.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/app-sidecar.js +153 -8
- package/dist/app-sidecar.js.map +1 -1
- package/dist/cli.js +5 -10
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session.d.ts +6 -0
- package/dist/core/agent-session.js +11 -3
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autopilot-cycle.d.ts +3 -4
- package/dist/core/autopilot-cycle.js +18 -11
- package/dist/core/autopilot-cycle.js.map +1 -1
- package/dist/core/autopilot-gate.d.ts +1 -3
- package/dist/core/autopilot-gate.js +4 -16
- package/dist/core/autopilot-gate.js.map +1 -1
- package/dist/core/event-bus.d.ts +3 -0
- package/dist/core/event-bus.js +5 -0
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/ideal-review.js +7 -1
- package/dist/core/ideal-review.js.map +1 -1
- package/dist/core/nolan-context.d.ts +1 -2
- package/dist/core/nolan-context.js +81 -21
- package/dist/core/nolan-context.js.map +1 -1
- package/dist/core/nolan-prompt.js +52 -48
- package/dist/core/nolan-prompt.js.map +1 -1
- package/dist/core/prompt-command-expansion.d.ts +13 -0
- package/dist/core/prompt-command-expansion.js +48 -0
- package/dist/core/prompt-command-expansion.js.map +1 -0
- package/dist/core/run-status.d.ts +17 -0
- package/dist/core/run-status.js +28 -0
- package/dist/core/run-status.js.map +1 -0
- package/dist/core/session-history.js +5 -14
- package/dist/core/session-history.js.map +1 -1
- package/dist/core/verification-gate.d.ts +6 -1
- package/dist/core/verification-gate.js +26 -4
- package/dist/core/verification-gate.js.map +1 -1
- package/dist/core/worktree.d.ts +161 -0
- package/dist/core/worktree.js +574 -0
- package/dist/core/worktree.js.map +1 -0
- package/dist/tools/subagent.d.ts +1 -0
- package/dist/tools/subagent.js +66 -2
- package/dist/tools/subagent.js.map +1 -1
- package/dist/ui/prompt-routing.js +2 -1
- package/dist/ui/prompt-routing.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import { getGitDirtyFileCount } from "../utils/git.js";
|
|
7
|
+
const exec = promisify(execFile);
|
|
8
|
+
const GIT_TIMEOUT_MS = 10_000;
|
|
9
|
+
const MAX_COLLISION_ATTEMPTS = 20;
|
|
10
|
+
/**
|
|
11
|
+
* `readOnly` plumbing sets GIT_OPTIONAL_LOCKS=0 so a query never takes the
|
|
12
|
+
* index lock and fights a concurrent git. The env is read per call, not
|
|
13
|
+
* captured at module load, so a later process.env change is honoured.
|
|
14
|
+
*/
|
|
15
|
+
async function git(cwd, args, readOnly = true) {
|
|
16
|
+
const { stdout } = await exec("git", args, {
|
|
17
|
+
cwd,
|
|
18
|
+
timeout: GIT_TIMEOUT_MS,
|
|
19
|
+
maxBuffer: 8 * 1024 * 1024,
|
|
20
|
+
env: readOnly ? { ...process.env, GIT_OPTIONAL_LOCKS: "0" } : process.env,
|
|
21
|
+
});
|
|
22
|
+
return String(stdout);
|
|
23
|
+
}
|
|
24
|
+
/** Same as `git`, but a non-zero exit resolves to null instead of throwing. */
|
|
25
|
+
async function gitOrNull(cwd, args) {
|
|
26
|
+
try {
|
|
27
|
+
return await git(cwd, args);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function realpathOrSelf(p) {
|
|
34
|
+
try {
|
|
35
|
+
return await fs.realpath(p);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return p;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Walk up from `startDir` to the nearest `.git`. A `.git` directory means the
|
|
43
|
+
* main worktree; a `.git` *file* (`gitdir: <path>`) means an already-linked
|
|
44
|
+
* worktree. Returns null when no repository encloses `startDir`.
|
|
45
|
+
*/
|
|
46
|
+
export async function gitLayout(startDir) {
|
|
47
|
+
let dir = path.resolve(startDir);
|
|
48
|
+
for (;;) {
|
|
49
|
+
const dotGit = path.join(dir, ".git");
|
|
50
|
+
let stat;
|
|
51
|
+
try {
|
|
52
|
+
stat = await fs.stat(dotGit);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
stat = null;
|
|
56
|
+
}
|
|
57
|
+
if (stat?.isDirectory()) {
|
|
58
|
+
return { worktreeRoot: dir, gitDir: dotGit, isMain: true };
|
|
59
|
+
}
|
|
60
|
+
if (stat?.isFile()) {
|
|
61
|
+
const contents = await fs.readFile(dotGit, "utf-8");
|
|
62
|
+
const match = /^gitdir:\s*(.+)$/m.exec(contents);
|
|
63
|
+
const target = match?.[1]?.trim();
|
|
64
|
+
if (target) {
|
|
65
|
+
const resolved = path.isAbsolute(target) ? target : path.resolve(dir, target);
|
|
66
|
+
return { worktreeRoot: dir, gitDir: path.normalize(resolved), isMain: false };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const parent = path.dirname(dir);
|
|
70
|
+
if (parent === dir)
|
|
71
|
+
return null;
|
|
72
|
+
dir = parent;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** The enclosing repo's root, but only when `startDir` is inside the MAIN worktree. */
|
|
76
|
+
export async function findMainWorktreeRoot(startDir) {
|
|
77
|
+
const layout = await gitLayout(startDir);
|
|
78
|
+
return layout?.isMain ? layout.worktreeRoot : null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Parse `git worktree list --porcelain`. The first block is always the main
|
|
82
|
+
* worktree. Paths are canonicalised so callers can compare them by string
|
|
83
|
+
* equality (/var vs /private/var aliasing on macOS).
|
|
84
|
+
*/
|
|
85
|
+
export async function listWorktrees(repoDir) {
|
|
86
|
+
const stdout = await git(repoDir, ["worktree", "list", "--porcelain"]);
|
|
87
|
+
const entries = [];
|
|
88
|
+
let current = null;
|
|
89
|
+
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
90
|
+
const line = rawLine.trim();
|
|
91
|
+
if (!line) {
|
|
92
|
+
if (current)
|
|
93
|
+
entries.push(current);
|
|
94
|
+
current = null;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (line.startsWith("worktree ")) {
|
|
98
|
+
if (current)
|
|
99
|
+
entries.push(current);
|
|
100
|
+
current = {
|
|
101
|
+
path: line.slice("worktree ".length).trim(),
|
|
102
|
+
branch: null,
|
|
103
|
+
head: null,
|
|
104
|
+
isBare: false,
|
|
105
|
+
isMain: entries.length === 0,
|
|
106
|
+
};
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (!current)
|
|
110
|
+
continue;
|
|
111
|
+
if (line.startsWith("HEAD "))
|
|
112
|
+
current.head = line.slice("HEAD ".length).trim();
|
|
113
|
+
else if (line.startsWith("branch "))
|
|
114
|
+
current.branch = line
|
|
115
|
+
.slice("branch ".length)
|
|
116
|
+
.trim()
|
|
117
|
+
.replace(/^refs\/heads\//, "");
|
|
118
|
+
else if (line === "bare")
|
|
119
|
+
current.isBare = true;
|
|
120
|
+
}
|
|
121
|
+
if (current)
|
|
122
|
+
entries.push(current);
|
|
123
|
+
for (const entry of entries)
|
|
124
|
+
entry.path = await realpathOrSelf(entry.path);
|
|
125
|
+
return entries;
|
|
126
|
+
}
|
|
127
|
+
/** True when `git status --porcelain` reports anything (tracked or untracked). */
|
|
128
|
+
export async function isWorkingTreeDirty(dir) {
|
|
129
|
+
return (await getGitDirtyFileCount(dir)) > 0;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Normalise arbitrary text into a branch name git will accept. Returns "" when
|
|
133
|
+
* nothing usable survives, so callers can fall back to a generated name.
|
|
134
|
+
*/
|
|
135
|
+
export function slugifyBranch(input) {
|
|
136
|
+
const slug = input
|
|
137
|
+
.toLowerCase()
|
|
138
|
+
.replace(/[\s_]+/g, "-")
|
|
139
|
+
.replace(/[^a-z0-9._/-]+/g, "")
|
|
140
|
+
.replace(/-{2,}/g, "-")
|
|
141
|
+
.replace(/^[-./]+/, "")
|
|
142
|
+
.replace(/[-./]+$/, "");
|
|
143
|
+
if (!slug)
|
|
144
|
+
return "";
|
|
145
|
+
if (slug.includes(".."))
|
|
146
|
+
return "";
|
|
147
|
+
if (slug.endsWith(".lock") || slug.split("/").some((part) => part.endsWith(".lock")))
|
|
148
|
+
return "";
|
|
149
|
+
if (slug.startsWith("-"))
|
|
150
|
+
return "";
|
|
151
|
+
return slug;
|
|
152
|
+
}
|
|
153
|
+
/** Pure: `<home>/.ezcoder/worktrees/<basename(repoRoot)>`. */
|
|
154
|
+
export function worktreesRootFor(repoRoot, homeDir = os.homedir()) {
|
|
155
|
+
return path.join(homeDir, ".ezcoder", "worktrees", path.basename(path.resolve(repoRoot)));
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Name of the file, inside a linked worktree's own git dir, recording the ref it
|
|
159
|
+
* was forked from.
|
|
160
|
+
*
|
|
161
|
+
* Reclaim has to answer "does this branch hold commits nobody else has", and
|
|
162
|
+
* that question is only meaningful against the ref the worktree ACTUALLY forked
|
|
163
|
+
* from. Comparing against whatever `main` points at today gets it wrong in both
|
|
164
|
+
* directions: main moving ahead makes an untouched worktree look behind, and a
|
|
165
|
+
* worktree forked from a feature branch looks full of "new" commits that its
|
|
166
|
+
* base already contains. Git does not record the fork point anywhere durable
|
|
167
|
+
* (reflogs expire, and a rebased base breaks merge-base), so it is written at
|
|
168
|
+
* creation time and read back verbatim.
|
|
169
|
+
*/
|
|
170
|
+
const BASE_REF_FILE = "ezcoder-base";
|
|
171
|
+
async function pathExists(p) {
|
|
172
|
+
try {
|
|
173
|
+
await fs.lstat(p);
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async function branchExists(repoDir, branch) {
|
|
181
|
+
const sha = await gitOrNull(repoDir, [
|
|
182
|
+
"rev-parse",
|
|
183
|
+
"--verify",
|
|
184
|
+
"--quiet",
|
|
185
|
+
`refs/heads/${branch}`,
|
|
186
|
+
]);
|
|
187
|
+
return Boolean(sha?.trim());
|
|
188
|
+
}
|
|
189
|
+
/** Resolve the MAIN worktree root for any directory inside a repo (linked or not). */
|
|
190
|
+
async function resolveMainRoot(repoDir) {
|
|
191
|
+
const layout = await gitLayout(repoDir);
|
|
192
|
+
if (!layout)
|
|
193
|
+
throw new Error(`Not a git repository: ${repoDir}`);
|
|
194
|
+
if (layout.isMain)
|
|
195
|
+
return layout.worktreeRoot;
|
|
196
|
+
// Linked worktree: the common dir is the main checkout's .git, whose parent
|
|
197
|
+
// is the main worktree root.
|
|
198
|
+
const commonDir = (await gitOrNull(repoDir, ["rev-parse", "--git-common-dir"]))?.trim();
|
|
199
|
+
const resolved = commonDir
|
|
200
|
+
? path.resolve(repoDir, commonDir)
|
|
201
|
+
: // .git/worktrees/<name> → .git
|
|
202
|
+
path.dirname(path.dirname(layout.gitDir));
|
|
203
|
+
return path.dirname(resolved);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Create a linked worktree on a fresh branch under `worktreesRootFor(mainRoot)`.
|
|
207
|
+
* Refuses to run against a dirty main checkout unless `allowDirty` is set — a
|
|
208
|
+
* half-committed main tree is the fastest way to lose work across worktrees.
|
|
209
|
+
*/
|
|
210
|
+
export async function createWorktree(opts) {
|
|
211
|
+
const mainRoot = await resolveMainRoot(opts.repoDir);
|
|
212
|
+
let baseRef = opts.baseRef?.trim();
|
|
213
|
+
if (!baseRef) {
|
|
214
|
+
const head = (await gitOrNull(mainRoot, ["rev-parse", "--abbrev-ref", "HEAD"]))?.trim();
|
|
215
|
+
if (!head)
|
|
216
|
+
throw new Error(`Cannot determine HEAD of ${mainRoot} (no commits yet?)`);
|
|
217
|
+
baseRef =
|
|
218
|
+
head === "HEAD" ? ((await gitOrNull(mainRoot, ["rev-parse", "HEAD"]))?.trim() ?? head) : head;
|
|
219
|
+
}
|
|
220
|
+
if (!opts.allowDirty && (await isWorkingTreeDirty(mainRoot))) {
|
|
221
|
+
throw new Error(`The main checkout at ${mainRoot} has uncommitted changes; no worktree was created. ` +
|
|
222
|
+
`Commit or stash them first, or pass allowDirty to create the worktree anyway.`);
|
|
223
|
+
}
|
|
224
|
+
const requested = opts.branch ? slugifyBranch(opts.branch) : "";
|
|
225
|
+
const base = requested || `ez/${Date.now().toString(36)}`;
|
|
226
|
+
const worktreesRoot = worktreesRootFor(mainRoot);
|
|
227
|
+
await fs.mkdir(worktreesRoot, { recursive: true });
|
|
228
|
+
for (let attempt = 1; attempt <= MAX_COLLISION_ATTEMPTS; attempt++) {
|
|
229
|
+
const branch = attempt === 1 ? base : `${base}-${attempt}`;
|
|
230
|
+
const targetPath = path.join(worktreesRoot, branch.replace(/\//g, "-"));
|
|
231
|
+
if ((await branchExists(mainRoot, branch)) || (await pathExists(targetPath)))
|
|
232
|
+
continue;
|
|
233
|
+
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
234
|
+
await git(mainRoot, ["worktree", "add", "-b", branch, targetPath, baseRef], false);
|
|
235
|
+
await writeBaseRef(targetPath, baseRef);
|
|
236
|
+
return { path: await realpathOrSelf(targetPath), branch, baseRef, created: true };
|
|
237
|
+
}
|
|
238
|
+
throw new Error(`Could not find a free worktree branch name for "${base}" after ${MAX_COLLISION_ATTEMPTS} attempts.`);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Record the fork point inside the new worktree's own git dir (not its working
|
|
242
|
+
* tree): the working tree belongs to the user and an agent, and a stray file
|
|
243
|
+
* there would show up as an untracked change, which would in turn make the
|
|
244
|
+
* worktree permanently "dirty" and therefore never reclaimable.
|
|
245
|
+
*
|
|
246
|
+
* Best effort. A worktree with no base file still reclaims — `readBaseRef`
|
|
247
|
+
* falls back — so a write failure must not fail the creation that succeeded.
|
|
248
|
+
*/
|
|
249
|
+
async function writeBaseRef(worktreePath, baseRef) {
|
|
250
|
+
try {
|
|
251
|
+
const layout = await gitLayout(worktreePath);
|
|
252
|
+
if (!layout)
|
|
253
|
+
return;
|
|
254
|
+
await fs.writeFile(path.join(layout.gitDir, BASE_REF_FILE), `${baseRef}\n`, "utf-8");
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
// Non-fatal: see doc comment.
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* The ref this worktree forked from, or null when unrecorded (a worktree made
|
|
262
|
+
* before this file existed, or by hand with plain git).
|
|
263
|
+
*/
|
|
264
|
+
async function readBaseRef(worktreePath) {
|
|
265
|
+
try {
|
|
266
|
+
const layout = await gitLayout(worktreePath);
|
|
267
|
+
if (!layout)
|
|
268
|
+
return null;
|
|
269
|
+
const raw = await fs.readFile(path.join(layout.gitDir, BASE_REF_FILE), "utf-8");
|
|
270
|
+
return raw.trim() || null;
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Pure: is `candidate` inside `root`?
|
|
278
|
+
*
|
|
279
|
+
* `path.relative` rather than `startsWith`: the string form says yes to
|
|
280
|
+
* `/a/worktrees-evil` for root `/a/worktrees`, and on Windows says no to a
|
|
281
|
+
* correct path that differs only in separator or drive-letter case. An empty
|
|
282
|
+
* relative path (candidate IS root) is deliberately NOT contained — removing
|
|
283
|
+
* the container itself is never what a caller means.
|
|
284
|
+
*/
|
|
285
|
+
export function isInsideWorktreesRoot(root, candidate) {
|
|
286
|
+
const rel = path.relative(path.resolve(root), path.resolve(candidate));
|
|
287
|
+
if (!rel)
|
|
288
|
+
return false;
|
|
289
|
+
if (rel.startsWith(".."))
|
|
290
|
+
return false;
|
|
291
|
+
return !path.isAbsolute(rel);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* The first symlink at or above `dir` (stopping at the filesystem root), or
|
|
295
|
+
* null when the whole chain is real directories.
|
|
296
|
+
*
|
|
297
|
+
* A containment check alone cannot see this: `stat` dereferences every path
|
|
298
|
+
* component, so a symlink at `~/.ezcoder/worktrees` makes every path under it
|
|
299
|
+
* look like an ordinary contained directory while the removal lands in whatever
|
|
300
|
+
* checkout it points at — the user's real repo, most likely. `lstat` sees the
|
|
301
|
+
* link itself. Every destructive path routes through here.
|
|
302
|
+
*/
|
|
303
|
+
export async function redirectedAncestor(dir) {
|
|
304
|
+
let current = path.resolve(dir);
|
|
305
|
+
for (;;) {
|
|
306
|
+
try {
|
|
307
|
+
if ((await fs.lstat(current)).isSymbolicLink())
|
|
308
|
+
return current;
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
// Missing components cannot redirect anything.
|
|
312
|
+
}
|
|
313
|
+
const parent = path.dirname(current);
|
|
314
|
+
if (parent === current)
|
|
315
|
+
return null;
|
|
316
|
+
current = parent;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/** Count commits on `branch` absent from `baseRef`; null when git cannot say. */
|
|
320
|
+
async function commitsAhead(dir, baseRef, branch) {
|
|
321
|
+
// `--` guards a ref whose name could otherwise be read as a path.
|
|
322
|
+
const out = await gitOrNull(dir, ["rev-list", "--count", `${baseRef}..${branch}`, "--"]);
|
|
323
|
+
if (out === null)
|
|
324
|
+
return null;
|
|
325
|
+
const n = Number.parseInt(out.trim(), 10);
|
|
326
|
+
return Number.isFinite(n) ? n : null;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Describe one worktree well enough to decide its fate, from the worktree's own
|
|
330
|
+
* directory so a stale main-checkout view cannot mislead.
|
|
331
|
+
*
|
|
332
|
+
* Unknowns always count AGAINST reclaiming: a git call that fails leaves the
|
|
333
|
+
* entry blocked rather than deleted. The cost of a wrong "keep" is a stale
|
|
334
|
+
* folder; the cost of a wrong "delete" is lost work.
|
|
335
|
+
*/
|
|
336
|
+
export async function worktreeStatus(mainRoot, entry, busyPaths = []) {
|
|
337
|
+
const blockedBy = [];
|
|
338
|
+
const busySet = new Set(await Promise.all(busyPaths.map((p) => realpathOrSelf(p))));
|
|
339
|
+
const busy = busySet.has(await realpathOrSelf(entry.path));
|
|
340
|
+
if (busy)
|
|
341
|
+
blockedBy.push("it is open in another window");
|
|
342
|
+
// -1 marks "could not read", which blocks just as a dirty tree does: an
|
|
343
|
+
// unreadable status is never evidence that a copy is empty.
|
|
344
|
+
const dirtyFiles = await getGitDirtyFileCount(entry.path).catch(() => -1);
|
|
345
|
+
if (dirtyFiles > 0)
|
|
346
|
+
blockedBy.push(`it has ${dirtyFiles} uncommitted file(s)`);
|
|
347
|
+
else if (dirtyFiles < 0)
|
|
348
|
+
blockedBy.push("its status could not be read");
|
|
349
|
+
const baseRef = (await readBaseRef(entry.path)) ?? (await defaultBaseRef(mainRoot));
|
|
350
|
+
let ahead = null;
|
|
351
|
+
if (baseRef && entry.branch) {
|
|
352
|
+
ahead = await commitsAhead(entry.path, baseRef, entry.branch);
|
|
353
|
+
if (ahead === null)
|
|
354
|
+
blockedBy.push("its commits could not be compared to the base branch");
|
|
355
|
+
else if (ahead > 0)
|
|
356
|
+
blockedBy.push(`it has ${ahead} unmerged commit(s)`);
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
blockedBy.push("its base branch is unknown");
|
|
360
|
+
}
|
|
361
|
+
if (!isInsideWorktreesRoot(worktreesRootFor(mainRoot), entry.path)) {
|
|
362
|
+
blockedBy.push("it lives outside the managed copies folder");
|
|
363
|
+
}
|
|
364
|
+
if (entry.isMain)
|
|
365
|
+
blockedBy.push("it is the main checkout");
|
|
366
|
+
return {
|
|
367
|
+
path: entry.path,
|
|
368
|
+
branch: entry.branch,
|
|
369
|
+
baseRef,
|
|
370
|
+
dirtyFiles: Math.max(dirtyFiles, 0),
|
|
371
|
+
commitsAhead: ahead ?? 0,
|
|
372
|
+
merged: ahead === 0,
|
|
373
|
+
busy,
|
|
374
|
+
reclaimable: blockedBy.length === 0,
|
|
375
|
+
blockedBy,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
/** The main checkout's current branch, used when no fork point was recorded. */
|
|
379
|
+
async function defaultBaseRef(mainRoot) {
|
|
380
|
+
const head = (await gitOrNull(mainRoot, ["rev-parse", "--abbrev-ref", "HEAD"]))?.trim();
|
|
381
|
+
return head && head !== "HEAD" ? head : null;
|
|
382
|
+
}
|
|
383
|
+
/** Status for every linked worktree of `repoDir`'s repo, main checkout excluded. */
|
|
384
|
+
export async function worktreeStatuses(repoDir, busyPaths = []) {
|
|
385
|
+
const mainRoot = await resolveMainRoot(repoDir);
|
|
386
|
+
const entries = await listWorktrees(mainRoot);
|
|
387
|
+
return await Promise.all(entries.filter((e) => !e.isMain).map((e) => worktreeStatus(mainRoot, e, busyPaths)));
|
|
388
|
+
}
|
|
389
|
+
/** Worktrees that can be removed right now with nothing lost. */
|
|
390
|
+
export async function reclaimableWorktrees(repoDir, busyPaths = []) {
|
|
391
|
+
return (await worktreeStatuses(repoDir, busyPaths)).filter((s) => s.reclaimable);
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Free a worktree's path AND its branch. Never throws: cleanup runs on window
|
|
395
|
+
* close and on daemon startup, where an exception would surface as a crash in
|
|
396
|
+
* an unrelated flow. Everything it could not do comes back in the result.
|
|
397
|
+
*
|
|
398
|
+
* The order below is load-bearing and `prune` is not optional. `worktree
|
|
399
|
+
* remove` needs the directory to be there; a user reclaiming disk with
|
|
400
|
+
* `rm -rf ~/.ezcoder/worktrees` leaves the tree REGISTERED BUT MISSING, and git
|
|
401
|
+
* then refuses both of the things the next run needs:
|
|
402
|
+
*
|
|
403
|
+
* $ git worktree add <path> <branch>
|
|
404
|
+
* fatal: '<path>' is a missing but already registered worktree;
|
|
405
|
+
* use 'add -f' to override, or 'prune' or 'remove' to clear
|
|
406
|
+
*
|
|
407
|
+
* and `git branch -d <branch>`, because the branch counts as checked out in
|
|
408
|
+
* that phantom. `git worktree prune` is the only thing that clears the
|
|
409
|
+
* registration, and it is a no-op when nothing is stale — so it runs
|
|
410
|
+
* unconditionally, and BEFORE the branch delete that depends on it.
|
|
411
|
+
*/
|
|
412
|
+
export async function removeWorktree(opts) {
|
|
413
|
+
let mainRoot;
|
|
414
|
+
try {
|
|
415
|
+
mainRoot = await resolveMainRoot(opts.repoDir);
|
|
416
|
+
}
|
|
417
|
+
catch (err) {
|
|
418
|
+
return { existed: false, freed: false, branchDeleted: false, reason: messageOf(err) };
|
|
419
|
+
}
|
|
420
|
+
const target = path.resolve(opts.worktreePath);
|
|
421
|
+
const root = worktreesRootFor(mainRoot);
|
|
422
|
+
// Containment BEFORE anything destructive. The path arrives over HTTP from
|
|
423
|
+
// the app; a request naming a path is not authorization to delete it.
|
|
424
|
+
if (!isInsideWorktreesRoot(root, target)) {
|
|
425
|
+
return {
|
|
426
|
+
existed: true,
|
|
427
|
+
freed: false,
|
|
428
|
+
branchDeleted: false,
|
|
429
|
+
reason: `refusing to remove ${target}: it is outside ${root}`,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
// A symlink ANYWHERE above the target redirects both the git remove and the
|
|
433
|
+
// rm fallback into whatever it points at, while the containment check above
|
|
434
|
+
// still reads as contained. `dirname`, because a link AT the target is
|
|
435
|
+
// unlinked below rather than followed.
|
|
436
|
+
try {
|
|
437
|
+
const redirected = await redirectedAncestor(path.dirname(target));
|
|
438
|
+
if (redirected !== null) {
|
|
439
|
+
return {
|
|
440
|
+
existed: true,
|
|
441
|
+
freed: false,
|
|
442
|
+
branchDeleted: false,
|
|
443
|
+
reason: `refusing to remove through a symlink: ${redirected} is a link, so the removal would land wherever it points`,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
catch (err) {
|
|
448
|
+
return { existed: true, freed: false, branchDeleted: false, reason: messageOf(err) };
|
|
449
|
+
}
|
|
450
|
+
const existed = await pathExists(target);
|
|
451
|
+
// Read the branch BEFORE the removal: afterwards the registration is gone and
|
|
452
|
+
// there is nothing left to ask.
|
|
453
|
+
const registeredBranch = await branchAtPath(mainRoot, target);
|
|
454
|
+
const branch = opts.deleteBranch === false ? null : registeredBranch;
|
|
455
|
+
const isRegistered = registeredBranch !== null;
|
|
456
|
+
let removeError;
|
|
457
|
+
if (existed) {
|
|
458
|
+
// `--force` only when the caller actually asked for it. Without it git
|
|
459
|
+
// refuses to remove a worktree holding uncommitted work, which is a second
|
|
460
|
+
// safety net under the `reclaimable` check the sweep already did.
|
|
461
|
+
const args = opts.force
|
|
462
|
+
? ["worktree", "remove", "--force", target]
|
|
463
|
+
: ["worktree", "remove", target];
|
|
464
|
+
try {
|
|
465
|
+
await git(mainRoot, args, false);
|
|
466
|
+
}
|
|
467
|
+
catch (err) {
|
|
468
|
+
removeError = err;
|
|
469
|
+
// Fall back to a direct delete ONLY when nothing would be lost by it:
|
|
470
|
+
// either the caller forced, or the path is not a registered worktree at
|
|
471
|
+
// all (a leftover directory git has already forgotten). A non-forced
|
|
472
|
+
// refusal over a REGISTERED tree is git protecting real work, and
|
|
473
|
+
// deleting it here would turn that protection into data loss.
|
|
474
|
+
if (opts.force || !isRegistered) {
|
|
475
|
+
try {
|
|
476
|
+
await fs.rm(target, { recursive: true, force: true });
|
|
477
|
+
removeError = undefined;
|
|
478
|
+
}
|
|
479
|
+
catch (rmErr) {
|
|
480
|
+
removeError = rmErr;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
// Always, even when nothing existed: this is what clears a registration whose
|
|
486
|
+
// directory someone deleted by hand, and it must precede the branch delete.
|
|
487
|
+
const pruned = (await gitOrNull(mainRoot, ["worktree", "prune"])) !== null;
|
|
488
|
+
const stillThere = await pathExists(target);
|
|
489
|
+
if (existed && stillThere) {
|
|
490
|
+
return {
|
|
491
|
+
existed,
|
|
492
|
+
freed: false,
|
|
493
|
+
branchDeleted: false,
|
|
494
|
+
reason: removeError
|
|
495
|
+
? messageOf(removeError)
|
|
496
|
+
: "the path is still there after `git worktree remove --force` and a direct delete",
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
if (!pruned) {
|
|
500
|
+
return {
|
|
501
|
+
existed,
|
|
502
|
+
freed: false,
|
|
503
|
+
branchDeleted: false,
|
|
504
|
+
reason: "`git worktree prune` could not run, so the registration and the branch survive; " +
|
|
505
|
+
"the next copy over this path would fail with \u201cmissing but already registered\u201d",
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
let branchDeleted = false;
|
|
509
|
+
if (branch) {
|
|
510
|
+
// -D rather than -d when forcing: an unmerged branch whose removal the user
|
|
511
|
+
// confirmed must not survive as a dangling ref.
|
|
512
|
+
const flag = opts.force ? "-D" : "-d";
|
|
513
|
+
branchDeleted = (await gitOrNull(mainRoot, ["branch", flag, "--", branch])) !== null;
|
|
514
|
+
}
|
|
515
|
+
return { existed, freed: true, branchDeleted };
|
|
516
|
+
}
|
|
517
|
+
function messageOf(err) {
|
|
518
|
+
return err instanceof Error ? err.message : String(err);
|
|
519
|
+
}
|
|
520
|
+
/** The branch checked out at `target`, read from the worktree itself. */
|
|
521
|
+
async function branchAtPath(mainRoot, target) {
|
|
522
|
+
const entries = await listWorktrees(mainRoot).catch(() => []);
|
|
523
|
+
for (const entry of entries) {
|
|
524
|
+
if ((await realpathOrSelf(entry.path)) === (await realpathOrSelf(target)))
|
|
525
|
+
return entry.branch;
|
|
526
|
+
}
|
|
527
|
+
return null;
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Remove every worktree of `repoDir`'s repo that is provably free of work.
|
|
531
|
+
*
|
|
532
|
+
* The automatic entry point: window close and daemon startup. It never forces,
|
|
533
|
+
* so anything holding uncommitted or unmerged work is reported as kept, with
|
|
534
|
+
* the reason, and waits for a human. Failures are collected rather than thrown
|
|
535
|
+
* — one wedged worktree must not stop the rest of the sweep.
|
|
536
|
+
*/
|
|
537
|
+
export async function sweepWorktrees(repoDir, busyPaths = []) {
|
|
538
|
+
const result = { removed: [], kept: [] };
|
|
539
|
+
let statuses;
|
|
540
|
+
try {
|
|
541
|
+
statuses = await worktreeStatuses(repoDir, busyPaths);
|
|
542
|
+
}
|
|
543
|
+
catch {
|
|
544
|
+
return result;
|
|
545
|
+
}
|
|
546
|
+
for (const status of statuses) {
|
|
547
|
+
if (!status.reclaimable) {
|
|
548
|
+
result.kept.push({ status, reason: status.blockedBy.join("; ") });
|
|
549
|
+
continue;
|
|
550
|
+
}
|
|
551
|
+
const release = await removeWorktree({
|
|
552
|
+
repoDir,
|
|
553
|
+
worktreePath: status.path,
|
|
554
|
+
force: false,
|
|
555
|
+
deleteBranch: true,
|
|
556
|
+
});
|
|
557
|
+
if (release.freed)
|
|
558
|
+
result.removed.push(status);
|
|
559
|
+
else
|
|
560
|
+
result.kept.push({ status, reason: release.reason ?? "it could not be removed" });
|
|
561
|
+
}
|
|
562
|
+
return result;
|
|
563
|
+
}
|
|
564
|
+
/** True when the repo already has at least one linked worktree registered. */
|
|
565
|
+
export async function repoHasLinkedWorktrees(mainRoot) {
|
|
566
|
+
try {
|
|
567
|
+
const entries = await fs.readdir(path.join(mainRoot, ".git", "worktrees"));
|
|
568
|
+
return entries.some((name) => !name.startsWith("."));
|
|
569
|
+
}
|
|
570
|
+
catch {
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
//# sourceMappingURL=worktree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/core/worktree.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/subagent.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare function isModelUnavailableError(stderr: string): boolean;
|
|
|
8
8
|
declare const SubAgentParams: z.ZodObject<{
|
|
9
9
|
task: z.ZodString;
|
|
10
10
|
agent: z.ZodOptional<z.ZodString>;
|
|
11
|
+
isolate: z.ZodOptional<z.ZodBoolean>;
|
|
11
12
|
}, z.core.$strip>;
|
|
12
13
|
export interface SubAgentUpdate {
|
|
13
14
|
toolUseCount: number;
|