@staff0rd/assist 0.481.0 → 0.482.1
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/commands/sessions/web/bundle.js +365 -365
- package/dist/index.js +296 -131
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.482.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -6665,10 +6665,10 @@ async function prepareRun(id, resumeSessionId) {
|
|
|
6665
6665
|
import chalk39 from "chalk";
|
|
6666
6666
|
function reportDuplicateRun(itemId2, holder) {
|
|
6667
6667
|
const since = holder.timestamp ? `, started ${holder.timestamp}` : "";
|
|
6668
|
-
const
|
|
6668
|
+
const reason4 = `another session is already running it (pid ${holder.pid}${since}); close that session before running it again`;
|
|
6669
6669
|
console.log(chalk39.yellow(`Already running: ${formatItemId(itemId2)}`));
|
|
6670
|
-
console.log(chalk39.dim(`Refusing to start a second run \u2014 ${
|
|
6671
|
-
appendDaemonLog(`backlog run ${itemId2}: refused \u2014 ${
|
|
6670
|
+
console.log(chalk39.dim(`Refusing to start a second run \u2014 ${reason4}.`));
|
|
6671
|
+
appendDaemonLog(`backlog run ${itemId2}: refused \u2014 ${reason4}`);
|
|
6672
6672
|
}
|
|
6673
6673
|
|
|
6674
6674
|
// src/commands/backlog/consumePause.ts
|
|
@@ -8332,11 +8332,11 @@ import {
|
|
|
8332
8332
|
var SPAWN_TIMEOUT_MS = 1e4;
|
|
8333
8333
|
var RETRY_DELAY_MS2 = 200;
|
|
8334
8334
|
var STALE_LOCK_MS = SPAWN_TIMEOUT_MS + 5e3;
|
|
8335
|
-
async function ensureDaemonRunning(
|
|
8335
|
+
async function ensureDaemonRunning(reason4 = "unspecified") {
|
|
8336
8336
|
if (await isDaemonRunning()) return;
|
|
8337
8337
|
mkdirSync10(daemonPaths.dir, { recursive: true });
|
|
8338
8338
|
const holdsLock = acquireSpawnLock();
|
|
8339
|
-
if (holdsLock) spawnDaemon(
|
|
8339
|
+
if (holdsLock) spawnDaemon(reason4);
|
|
8340
8340
|
try {
|
|
8341
8341
|
await waitForDaemon();
|
|
8342
8342
|
} finally {
|
|
@@ -8385,12 +8385,12 @@ function releaseSpawnLock() {
|
|
|
8385
8385
|
} catch {
|
|
8386
8386
|
}
|
|
8387
8387
|
}
|
|
8388
|
-
function spawnDaemon(
|
|
8388
|
+
function spawnDaemon(reason4) {
|
|
8389
8389
|
const log = openSync2(daemonPaths.log, "a");
|
|
8390
8390
|
const child = spawn4(process.execPath, [process.argv[1], "daemon", "run"], {
|
|
8391
8391
|
detached: true,
|
|
8392
8392
|
stdio: ["ignore", log, log],
|
|
8393
|
-
env: { ...process.env, ASSIST_DAEMON_SPAWN_REASON:
|
|
8393
|
+
env: { ...process.env, ASSIST_DAEMON_SPAWN_REASON: reason4 }
|
|
8394
8394
|
});
|
|
8395
8395
|
child.unref();
|
|
8396
8396
|
}
|
|
@@ -8971,7 +8971,7 @@ async function patchSubtaskStatus(req, res, id, idx) {
|
|
|
8971
8971
|
}
|
|
8972
8972
|
|
|
8973
8973
|
// src/commands/backlog/rewindItemToPhase.ts
|
|
8974
|
-
async function rewindItemToPhase(orm, item, phaseNumber,
|
|
8974
|
+
async function rewindItemToPhase(orm, item, phaseNumber, reason4) {
|
|
8975
8975
|
const plan2 = resolveRewindPlan(item);
|
|
8976
8976
|
if (phaseNumber < 1 || phaseNumber > plan2.length) {
|
|
8977
8977
|
return {
|
|
@@ -8990,7 +8990,7 @@ async function rewindItemToPhase(orm, item, phaseNumber, reason2) {
|
|
|
8990
8990
|
await appendComment(
|
|
8991
8991
|
orm,
|
|
8992
8992
|
item.id,
|
|
8993
|
-
`Rewound to phase ${phaseNumber} (${phaseName}): ${
|
|
8993
|
+
`Rewound to phase ${phaseNumber} (${phaseName}): ${reason4}`,
|
|
8994
8994
|
{ phase: phaseNumber }
|
|
8995
8995
|
);
|
|
8996
8996
|
await updateCurrentPhase(orm, item.id, phaseNumber);
|
|
@@ -9001,11 +9001,11 @@ async function rewindItemToPhase(orm, item, phaseNumber, reason2) {
|
|
|
9001
9001
|
|
|
9002
9002
|
// src/commands/backlog/web/rewindItemPhase.ts
|
|
9003
9003
|
async function rewindItemPhase(req, res, id) {
|
|
9004
|
-
const { phase, reason:
|
|
9004
|
+
const { phase, reason: reason4 } = await parseRewindBody(req);
|
|
9005
9005
|
const result = await findItemOr404(res, id);
|
|
9006
9006
|
if (!result) return;
|
|
9007
9007
|
const { orm, item } = result;
|
|
9008
|
-
const outcome = await rewindItemToPhase(orm, item, phase,
|
|
9008
|
+
const outcome = await rewindItemToPhase(orm, item, phase, reason4);
|
|
9009
9009
|
if (!outcome.ok) {
|
|
9010
9010
|
respondJson(res, 400, { error: outcome.error });
|
|
9011
9011
|
return;
|
|
@@ -11750,8 +11750,8 @@ function countCopyRows(data) {
|
|
|
11750
11750
|
|
|
11751
11751
|
// src/commands/backlog/dump/parseDump.ts
|
|
11752
11752
|
var NEWLINE = 10;
|
|
11753
|
-
function invalid(
|
|
11754
|
-
throw new Error(`Invalid dump: ${
|
|
11753
|
+
function invalid(reason4) {
|
|
11754
|
+
throw new Error(`Invalid dump: ${reason4}`);
|
|
11755
11755
|
}
|
|
11756
11756
|
function readLine(dump, start3) {
|
|
11757
11757
|
const eol = dump.indexOf(NEWLINE, start3);
|
|
@@ -13123,14 +13123,14 @@ async function unstar(id) {
|
|
|
13123
13123
|
|
|
13124
13124
|
// src/commands/backlog/wontdo/index.ts
|
|
13125
13125
|
import chalk98 from "chalk";
|
|
13126
|
-
async function wontdo(id,
|
|
13126
|
+
async function wontdo(id, reason4) {
|
|
13127
13127
|
const found = await findOneItem(id);
|
|
13128
13128
|
if (!found) return;
|
|
13129
13129
|
const { orm, item } = found;
|
|
13130
13130
|
await updateStatus(orm, item.id, "wontdo");
|
|
13131
|
-
if (
|
|
13131
|
+
if (reason4) {
|
|
13132
13132
|
const phase = item.currentPhase ?? 1;
|
|
13133
|
-
await appendComment(orm, item.id,
|
|
13133
|
+
await appendComment(orm, item.id, reason4, { phase, type: "summary" });
|
|
13134
13134
|
}
|
|
13135
13135
|
console.log(
|
|
13136
13136
|
chalk98.red(`Won't do item ${formatItemId(item.id)}: ${item.name}`)
|
|
@@ -14697,9 +14697,9 @@ function resolvePermission(toolName, parts) {
|
|
|
14697
14697
|
if (denied) return denied;
|
|
14698
14698
|
const reasons = [];
|
|
14699
14699
|
for (const part of parts) {
|
|
14700
|
-
const
|
|
14701
|
-
if (!
|
|
14702
|
-
reasons.push(
|
|
14700
|
+
const reason4 = isApprovedRead(part, toolName);
|
|
14701
|
+
if (!reason4) return void 0;
|
|
14702
|
+
reasons.push(reason4);
|
|
14703
14703
|
}
|
|
14704
14704
|
return {
|
|
14705
14705
|
permissionDecision: "allow",
|
|
@@ -14823,13 +14823,13 @@ function cliHookCheck(command, toolName = "Bash") {
|
|
|
14823
14823
|
if (reportDeny(toolName, parts)) return;
|
|
14824
14824
|
const reasons = [];
|
|
14825
14825
|
for (const part of parts) {
|
|
14826
|
-
const
|
|
14827
|
-
if (!
|
|
14826
|
+
const reason4 = isApprovedRead(part, toolName);
|
|
14827
|
+
if (!reason4) {
|
|
14828
14828
|
console.log(`not approved (unrecognised: ${part})`);
|
|
14829
14829
|
process.exitCode = 1;
|
|
14830
14830
|
return;
|
|
14831
14831
|
}
|
|
14832
|
-
reasons.push(` ${part} -> ${
|
|
14832
|
+
reasons.push(` ${part} -> ${reason4}`);
|
|
14833
14833
|
}
|
|
14834
14834
|
console.log(`approved
|
|
14835
14835
|
${reasons.join("\n")}`);
|
|
@@ -17888,14 +17888,14 @@ async function editHook() {
|
|
|
17888
17888
|
const input = tryParseInput2(await readStdin());
|
|
17889
17889
|
if (!input) return;
|
|
17890
17890
|
const existing = input.tool_name === "Write" ? readExisting(input.tool_input.file_path) : void 0;
|
|
17891
|
-
const
|
|
17892
|
-
if (!
|
|
17891
|
+
const reason4 = decideOverrideGuard(input, existing) ?? decideCommentGuard(input, existing) ?? decideMigrationGuard(input, existing);
|
|
17892
|
+
if (!reason4) return;
|
|
17893
17893
|
console.log(
|
|
17894
17894
|
JSON.stringify({
|
|
17895
17895
|
hookSpecificOutput: {
|
|
17896
17896
|
hookEventName: "PreToolUse",
|
|
17897
17897
|
permissionDecision: "deny",
|
|
17898
|
-
permissionDecisionReason:
|
|
17898
|
+
permissionDecisionReason: reason4
|
|
17899
17899
|
}
|
|
17900
17900
|
})
|
|
17901
17901
|
);
|
|
@@ -18841,10 +18841,12 @@ function persistedTreeRoots() {
|
|
|
18841
18841
|
}
|
|
18842
18842
|
|
|
18843
18843
|
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
18844
|
-
import { execFile as execFile8 } from "child_process";
|
|
18845
18844
|
import { copyFileSync, existsSync as existsSync46, mkdirSync as mkdirSync16 } from "fs";
|
|
18846
18845
|
import { dirname as dirname24, join as join48 } from "path";
|
|
18847
18846
|
|
|
18847
|
+
// src/commands/sessions/daemon/worktree/runInstall.ts
|
|
18848
|
+
import { spawn as spawn5 } from "child_process";
|
|
18849
|
+
|
|
18848
18850
|
// src/commands/sessions/daemon/worktree/resolveInstallCommand.ts
|
|
18849
18851
|
import { existsSync as existsSync45 } from "fs";
|
|
18850
18852
|
import { join as join47 } from "path";
|
|
@@ -18861,6 +18863,90 @@ function resolveInstallCommand(repoRoot, install) {
|
|
|
18861
18863
|
return detectInstallCommand(repoRoot);
|
|
18862
18864
|
}
|
|
18863
18865
|
|
|
18866
|
+
// src/commands/sessions/daemon/worktree/stopInstall.ts
|
|
18867
|
+
import { execFile as execFile8 } from "child_process";
|
|
18868
|
+
var running2 = /* @__PURE__ */ new Map();
|
|
18869
|
+
function trackInstall(worktreePath, child) {
|
|
18870
|
+
running2.set(worktreePath, child);
|
|
18871
|
+
}
|
|
18872
|
+
function untrackInstall(worktreePath, child) {
|
|
18873
|
+
if (running2.get(worktreePath) === child) running2.delete(worktreePath);
|
|
18874
|
+
}
|
|
18875
|
+
function stopInstall(worktreePath) {
|
|
18876
|
+
const child = running2.get(worktreePath);
|
|
18877
|
+
running2.delete(worktreePath);
|
|
18878
|
+
if (!child?.pid) return;
|
|
18879
|
+
daemonLog(
|
|
18880
|
+
`worktree ${worktreePath} install still running at teardown; killing pid ${child.pid} so removal is not racing it`
|
|
18881
|
+
);
|
|
18882
|
+
killTree(child.pid);
|
|
18883
|
+
}
|
|
18884
|
+
function killTree(pid) {
|
|
18885
|
+
if (process.platform === "win32") {
|
|
18886
|
+
execFile8("taskkill", ["/T", "/F", "/PID", String(pid)], () => {
|
|
18887
|
+
});
|
|
18888
|
+
return;
|
|
18889
|
+
}
|
|
18890
|
+
try {
|
|
18891
|
+
process.kill(-pid, "SIGKILL");
|
|
18892
|
+
} catch {
|
|
18893
|
+
try {
|
|
18894
|
+
process.kill(pid, "SIGKILL");
|
|
18895
|
+
} catch {
|
|
18896
|
+
}
|
|
18897
|
+
}
|
|
18898
|
+
}
|
|
18899
|
+
|
|
18900
|
+
// src/commands/sessions/daemon/worktree/installInvocation.ts
|
|
18901
|
+
function installInvocation(worktreePath, command) {
|
|
18902
|
+
const windows = /^[A-Za-z]:[\\/]/.test(worktreePath);
|
|
18903
|
+
const shell = windows ? "cmd.exe" : process.env.SHELL ?? "bash";
|
|
18904
|
+
const args = windows ? ["/c", `cd /d ${quoteForCmd(worktreePath)} && ${command}`] : ["-l", "-c", `cd ${quoteForPosixShell(worktreePath)} && ${command}`];
|
|
18905
|
+
return [
|
|
18906
|
+
shell,
|
|
18907
|
+
args,
|
|
18908
|
+
{ cwd: worktreePath, detached: true, stdio: ["ignore", "ignore", "pipe"] }
|
|
18909
|
+
];
|
|
18910
|
+
}
|
|
18911
|
+
function quoteForCmd(value) {
|
|
18912
|
+
return `"${value.replaceAll('"', "")}"`;
|
|
18913
|
+
}
|
|
18914
|
+
function quoteForPosixShell(value) {
|
|
18915
|
+
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
18916
|
+
}
|
|
18917
|
+
|
|
18918
|
+
// src/commands/sessions/daemon/worktree/runInstall.ts
|
|
18919
|
+
var STDERR_TAIL = 2e3;
|
|
18920
|
+
function runInstall(worktreePath, clone, install, onSeeded) {
|
|
18921
|
+
const command = resolveInstallCommand(clone, install);
|
|
18922
|
+
if (!command) {
|
|
18923
|
+
onSeeded();
|
|
18924
|
+
return;
|
|
18925
|
+
}
|
|
18926
|
+
daemonLog(`worktree ${worktreePath} installing deps: ${command}`);
|
|
18927
|
+
const child = spawn5(...installInvocation(worktreePath, command));
|
|
18928
|
+
trackInstall(worktreePath, child);
|
|
18929
|
+
let stderr = "";
|
|
18930
|
+
child.stderr?.on("data", (chunk) => {
|
|
18931
|
+
stderr = (stderr + chunk.toString()).slice(-STDERR_TAIL);
|
|
18932
|
+
});
|
|
18933
|
+
let settled = false;
|
|
18934
|
+
const settle = (outcome) => {
|
|
18935
|
+
if (settled) return;
|
|
18936
|
+
settled = true;
|
|
18937
|
+
untrackInstall(worktreePath, child);
|
|
18938
|
+
daemonLog(`worktree ${worktreePath} install ${outcome}`);
|
|
18939
|
+
onSeeded();
|
|
18940
|
+
};
|
|
18941
|
+
child.on("error", (error) => settle(`failed to start: ${error.message}`));
|
|
18942
|
+
child.on(
|
|
18943
|
+
"close",
|
|
18944
|
+
(code, signal) => settle(
|
|
18945
|
+
code === 0 ? "complete" : `failed (${signal ? `signal ${signal}` : `exit ${code}`}): ${stderr.trim() || "no output"}`
|
|
18946
|
+
)
|
|
18947
|
+
);
|
|
18948
|
+
}
|
|
18949
|
+
|
|
18864
18950
|
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
18865
18951
|
function seedWorktree(worktreePath, clone, onSeeded = () => {
|
|
18866
18952
|
}) {
|
|
@@ -18884,29 +18970,6 @@ function copyConfigFiles(worktreePath, clone, copy) {
|
|
|
18884
18970
|
}
|
|
18885
18971
|
}
|
|
18886
18972
|
}
|
|
18887
|
-
function runInstall(worktreePath, clone, install, onSeeded) {
|
|
18888
|
-
const command = resolveInstallCommand(clone, install);
|
|
18889
|
-
if (!command) {
|
|
18890
|
-
onSeeded();
|
|
18891
|
-
return;
|
|
18892
|
-
}
|
|
18893
|
-
const windows = /^[A-Za-z]:[\\/]/.test(worktreePath);
|
|
18894
|
-
const shell = windows ? "cmd.exe" : process.env.SHELL ?? "bash";
|
|
18895
|
-
const shellArgs = windows ? ["/c", `cd /d ${quoteForCmd(worktreePath)} && ${command}`] : ["-l", "-c", `cd ${quoteForPosixShell(worktreePath)} && ${command}`];
|
|
18896
|
-
daemonLog(`worktree ${worktreePath} installing deps: ${command}`);
|
|
18897
|
-
execFile8(shell, shellArgs, { cwd: worktreePath }, (error) => {
|
|
18898
|
-
daemonLog(
|
|
18899
|
-
error ? `worktree ${worktreePath} install failed: ${error.message}` : `worktree ${worktreePath} install complete`
|
|
18900
|
-
);
|
|
18901
|
-
onSeeded();
|
|
18902
|
-
});
|
|
18903
|
-
}
|
|
18904
|
-
function quoteForPosixShell(value) {
|
|
18905
|
-
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
18906
|
-
}
|
|
18907
|
-
function quoteForCmd(value) {
|
|
18908
|
-
return `"${value.replaceAll('"', "")}"`;
|
|
18909
|
-
}
|
|
18910
18973
|
function message(error) {
|
|
18911
18974
|
return error instanceof Error ? error.message : String(error);
|
|
18912
18975
|
}
|
|
@@ -20881,16 +20944,16 @@ function reply(commentId, body) {
|
|
|
20881
20944
|
|
|
20882
20945
|
// src/commands/prs/wontfix.ts
|
|
20883
20946
|
import { execSync as execSync50 } from "child_process";
|
|
20884
|
-
function validateReason(
|
|
20885
|
-
const lowerReason =
|
|
20947
|
+
function validateReason(reason4) {
|
|
20948
|
+
const lowerReason = reason4.toLowerCase();
|
|
20886
20949
|
if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
|
|
20887
20950
|
console.error('Error: Reason must not contain "claude" or "opus"');
|
|
20888
20951
|
process.exit(1);
|
|
20889
20952
|
}
|
|
20890
20953
|
}
|
|
20891
|
-
function validateShaReferences(
|
|
20954
|
+
function validateShaReferences(reason4) {
|
|
20892
20955
|
const commitLinkPattern = /\[[0-9a-f]{7}\]\(https:\/\/github\.com\/[^/]+\/[^/]+\/commit\/([0-9a-f]{40})\)/gi;
|
|
20893
|
-
const shas = Array.from(
|
|
20956
|
+
const shas = Array.from(reason4.matchAll(commitLinkPattern), (m) => m[1]);
|
|
20894
20957
|
if (shas.length === 0) {
|
|
20895
20958
|
return;
|
|
20896
20959
|
}
|
|
@@ -20909,11 +20972,11 @@ function validateShaReferences(reason2) {
|
|
|
20909
20972
|
process.exit(1);
|
|
20910
20973
|
}
|
|
20911
20974
|
}
|
|
20912
|
-
function wontfix(commentId,
|
|
20913
|
-
validateReason(
|
|
20914
|
-
validateShaReferences(
|
|
20975
|
+
function wontfix(commentId, reason4) {
|
|
20976
|
+
validateReason(reason4);
|
|
20977
|
+
validateShaReferences(reason4);
|
|
20915
20978
|
try {
|
|
20916
|
-
resolveCommentWithReply(commentId,
|
|
20979
|
+
resolveCommentWithReply(commentId, reason4);
|
|
20917
20980
|
} catch (error) {
|
|
20918
20981
|
if (isGhNotInstalled(error)) {
|
|
20919
20982
|
console.error("Error: GitHub CLI (gh) is not installed.");
|
|
@@ -21092,8 +21155,8 @@ function registerPrs(program2) {
|
|
|
21092
21155
|
prsCommand.command("fixed <comment-id> <sha>").description("Reply with commit link and resolve thread").action((commentId, sha) => {
|
|
21093
21156
|
fixed(Number.parseInt(commentId, 10), sha);
|
|
21094
21157
|
});
|
|
21095
|
-
prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId,
|
|
21096
|
-
wontfix(Number.parseInt(commentId, 10),
|
|
21158
|
+
prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason4) => {
|
|
21159
|
+
wontfix(Number.parseInt(commentId, 10), reason4);
|
|
21097
21160
|
});
|
|
21098
21161
|
prsCommand.command("reply <comment-id> <body>").description("Reply to a comment thread without resolving it").action((commentId, body) => {
|
|
21099
21162
|
reply(Number.parseInt(commentId, 10), body);
|
|
@@ -21542,7 +21605,7 @@ function registerRavendb(program2) {
|
|
|
21542
21605
|
}
|
|
21543
21606
|
|
|
21544
21607
|
// src/commands/refactor/check/index.ts
|
|
21545
|
-
import { spawn as
|
|
21608
|
+
import { spawn as spawn6 } from "child_process";
|
|
21546
21609
|
import * as path36 from "path";
|
|
21547
21610
|
|
|
21548
21611
|
// src/commands/refactor/logViolations.ts
|
|
@@ -21690,7 +21753,7 @@ function getViolations(pattern2, options2 = {}, maxLines = DEFAULT_MAX_LINES) {
|
|
|
21690
21753
|
// src/commands/refactor/check/index.ts
|
|
21691
21754
|
function runScript(script, cwd) {
|
|
21692
21755
|
return new Promise((resolve20) => {
|
|
21693
|
-
const child =
|
|
21756
|
+
const child = spawn6("npm", ["run", script], {
|
|
21694
21757
|
stdio: "pipe",
|
|
21695
21758
|
shell: true,
|
|
21696
21759
|
cwd
|
|
@@ -23074,10 +23137,10 @@ function listFilesRecursive(dir) {
|
|
|
23074
23137
|
}
|
|
23075
23138
|
return results;
|
|
23076
23139
|
}
|
|
23077
|
-
function addDirectoryFileMoves(moves, childDir, newLocation,
|
|
23140
|
+
function addDirectoryFileMoves(moves, childDir, newLocation, reason4) {
|
|
23078
23141
|
for (const file of listFilesRecursive(childDir)) {
|
|
23079
23142
|
const rel = path55.relative(childDir, file);
|
|
23080
|
-
moves.push({ from: file, to: path55.join(newLocation, rel), reason:
|
|
23143
|
+
moves.push({ from: file, to: path55.join(newLocation, rel), reason: reason4 });
|
|
23081
23144
|
}
|
|
23082
23145
|
}
|
|
23083
23146
|
function resolveChildDest(parentDir, childDir) {
|
|
@@ -23088,8 +23151,8 @@ function childMoveReason(parentDir) {
|
|
|
23088
23151
|
}
|
|
23089
23152
|
function registerDirectoryMove(result, childDir, dest, parentDir) {
|
|
23090
23153
|
result.directories.push(dest);
|
|
23091
|
-
const
|
|
23092
|
-
addDirectoryFileMoves(result.moves, childDir, dest,
|
|
23154
|
+
const reason4 = childMoveReason(parentDir);
|
|
23155
|
+
addDirectoryFileMoves(result.moves, childDir, dest, reason4);
|
|
23093
23156
|
}
|
|
23094
23157
|
function planChildDirectoryMove(result, parentDir, childDir) {
|
|
23095
23158
|
const dest = resolveChildDest(parentDir, childDir);
|
|
@@ -24384,7 +24447,7 @@ function reportReviewerToolUse(name, use, spinner) {
|
|
|
24384
24447
|
}
|
|
24385
24448
|
|
|
24386
24449
|
// src/commands/review/runStreamingChild.ts
|
|
24387
|
-
import { spawn as
|
|
24450
|
+
import { spawn as spawn7 } from "child_process";
|
|
24388
24451
|
|
|
24389
24452
|
// src/commands/review/attachLineParser.ts
|
|
24390
24453
|
function flushBuffer(buffer, onLine) {
|
|
@@ -24535,7 +24598,7 @@ function writeStdinSafely(child, payload) {
|
|
|
24535
24598
|
}
|
|
24536
24599
|
}
|
|
24537
24600
|
function startChild(spec) {
|
|
24538
|
-
const child =
|
|
24601
|
+
const child = spawn7(spec.command, spec.args, {
|
|
24539
24602
|
stdio: ["pipe", "pipe", "pipe"],
|
|
24540
24603
|
shell: process.platform === "win32"
|
|
24541
24604
|
});
|
|
@@ -26192,7 +26255,7 @@ function setup() {
|
|
|
26192
26255
|
}
|
|
26193
26256
|
|
|
26194
26257
|
// src/commands/voice/start.ts
|
|
26195
|
-
import { spawn as
|
|
26258
|
+
import { spawn as spawn8 } from "child_process";
|
|
26196
26259
|
import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync40 } from "fs";
|
|
26197
26260
|
import { join as join65 } from "path";
|
|
26198
26261
|
|
|
@@ -26207,11 +26270,11 @@ function buildDaemonEnv(options2) {
|
|
|
26207
26270
|
// src/commands/voice/start.ts
|
|
26208
26271
|
function spawnForeground(python, script, env) {
|
|
26209
26272
|
console.log("Starting voice daemon in foreground...");
|
|
26210
|
-
const child =
|
|
26273
|
+
const child = spawn8(python, [script], { stdio: "inherit", env });
|
|
26211
26274
|
child.on("exit", (code) => process.exit(code ?? 0));
|
|
26212
26275
|
}
|
|
26213
26276
|
function spawnBackground(python, script, env) {
|
|
26214
|
-
const child =
|
|
26277
|
+
const child = spawn8(python, [script], {
|
|
26215
26278
|
detached: true,
|
|
26216
26279
|
stdio: "ignore",
|
|
26217
26280
|
env
|
|
@@ -27012,7 +27075,7 @@ function runPreCommands(pre, cwd) {
|
|
|
27012
27075
|
}
|
|
27013
27076
|
|
|
27014
27077
|
// src/commands/run/spawnRunCommand.ts
|
|
27015
|
-
import { execFileSync as execFileSync12, spawn as
|
|
27078
|
+
import { execFileSync as execFileSync12, spawn as spawn9 } from "child_process";
|
|
27016
27079
|
import { existsSync as existsSync58 } from "fs";
|
|
27017
27080
|
import { dirname as dirname29, join as join67, resolve as resolve15 } from "path";
|
|
27018
27081
|
function resolveCommand2(command) {
|
|
@@ -27028,7 +27091,7 @@ function resolveCommand2(command) {
|
|
|
27028
27091
|
}
|
|
27029
27092
|
function spawnRunCommand(command, args, env, cwd, quiet) {
|
|
27030
27093
|
const start3 = Date.now();
|
|
27031
|
-
const child =
|
|
27094
|
+
const child = spawn9(resolveCommand2(command), args, {
|
|
27032
27095
|
stdio: quiet ? "pipe" : "inherit",
|
|
27033
27096
|
env: env ? { ...process.env, ...expandEnv(env) } : void 0,
|
|
27034
27097
|
cwd
|
|
@@ -28104,9 +28167,89 @@ function otherTreeHolders(sessions, session) {
|
|
|
28104
28167
|
}
|
|
28105
28168
|
|
|
28106
28169
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
28107
|
-
import { existsSync as
|
|
28170
|
+
import { existsSync as existsSync63 } from "fs";
|
|
28108
28171
|
import { basename as basename16 } from "path";
|
|
28109
28172
|
|
|
28173
|
+
// src/commands/sessions/daemon/worktree/deleteStrandedTree.ts
|
|
28174
|
+
import { existsSync as existsSync62 } from "fs";
|
|
28175
|
+
import { join as join73 } from "path";
|
|
28176
|
+
|
|
28177
|
+
// src/commands/sessions/daemon/worktree/deleteTreeDirectly.ts
|
|
28178
|
+
import { statSync as statSync11 } from "fs";
|
|
28179
|
+
import { rm as rm2 } from "fs/promises";
|
|
28180
|
+
import { join as join72 } from "path";
|
|
28181
|
+
async function deleteTreeDirectly(clone, worktreePath, why) {
|
|
28182
|
+
if (holdsAGitDirectoryRatherThanALink(worktreePath)) {
|
|
28183
|
+
daemonLog(
|
|
28184
|
+
`worktree ${worktreePath} not deleted directly (${why}): it is a clone of its own, not a linked worktree`
|
|
28185
|
+
);
|
|
28186
|
+
return false;
|
|
28187
|
+
}
|
|
28188
|
+
daemonLog(`worktree ${worktreePath} deleting its directory directly: ${why}`);
|
|
28189
|
+
try {
|
|
28190
|
+
await rm2(worktreePath, {
|
|
28191
|
+
recursive: true,
|
|
28192
|
+
force: true,
|
|
28193
|
+
maxRetries: 3,
|
|
28194
|
+
retryDelay: 200
|
|
28195
|
+
});
|
|
28196
|
+
} catch (error) {
|
|
28197
|
+
daemonLog(
|
|
28198
|
+
`worktree ${worktreePath} directory delete failed, left in place for the next reconcile: ${reason(error)}`
|
|
28199
|
+
);
|
|
28200
|
+
return false;
|
|
28201
|
+
}
|
|
28202
|
+
daemonLog(`worktree ${worktreePath} directory deleted directly`);
|
|
28203
|
+
await pruneBookkeeping(clone, worktreePath);
|
|
28204
|
+
return true;
|
|
28205
|
+
}
|
|
28206
|
+
function holdsAGitDirectoryRatherThanALink(worktreePath) {
|
|
28207
|
+
return statSync11(join72(worktreePath, ".git"), {
|
|
28208
|
+
throwIfNoEntry: false
|
|
28209
|
+
})?.isDirectory() === true;
|
|
28210
|
+
}
|
|
28211
|
+
async function pruneBookkeeping(clone, worktreePath) {
|
|
28212
|
+
try {
|
|
28213
|
+
await git2(clone, ["worktree", "prune"]);
|
|
28214
|
+
daemonLog(
|
|
28215
|
+
`worktree bookkeeping pruned in clone ${clone} after deleting ${worktreePath} directly`
|
|
28216
|
+
);
|
|
28217
|
+
} catch (error) {
|
|
28218
|
+
daemonLog(
|
|
28219
|
+
`worktree bookkeeping prune failed in clone ${clone} after deleting ${worktreePath}: ${reason(error)}`
|
|
28220
|
+
);
|
|
28221
|
+
}
|
|
28222
|
+
}
|
|
28223
|
+
function reason(error) {
|
|
28224
|
+
return error instanceof Error ? error.message : String(error);
|
|
28225
|
+
}
|
|
28226
|
+
|
|
28227
|
+
// src/commands/sessions/daemon/worktree/deleteStrandedTree.ts
|
|
28228
|
+
async function deleteStrandedTree(clone, worktreePath, cause) {
|
|
28229
|
+
const stranded = strandedReason(worktreePath, cause);
|
|
28230
|
+
if (!stranded) {
|
|
28231
|
+
daemonLog(
|
|
28232
|
+
`worktree ${worktreePath} left in place for the next reconcile: ${reason2(cause)}`
|
|
28233
|
+
);
|
|
28234
|
+
return false;
|
|
28235
|
+
}
|
|
28236
|
+
return await deleteTreeDirectly(
|
|
28237
|
+
clone,
|
|
28238
|
+
worktreePath,
|
|
28239
|
+
`git can no longer remove it, ${stranded}`
|
|
28240
|
+
);
|
|
28241
|
+
}
|
|
28242
|
+
function strandedReason(worktreePath, cause) {
|
|
28243
|
+
if (!existsSync62(join73(worktreePath, ".git")))
|
|
28244
|
+
return "its .git link is already gone";
|
|
28245
|
+
if (/not a working tree|not a git repository/i.test(reason2(cause)))
|
|
28246
|
+
return "git no longer recognises it as a working tree";
|
|
28247
|
+
return null;
|
|
28248
|
+
}
|
|
28249
|
+
function reason2(error) {
|
|
28250
|
+
return error instanceof Error ? error.message : String(error);
|
|
28251
|
+
}
|
|
28252
|
+
|
|
28110
28253
|
// src/commands/sessions/daemon/worktree/removeTree.ts
|
|
28111
28254
|
async function removeTree(clone, worktreePath, force) {
|
|
28112
28255
|
const remove2 = (forced) => git2(clone, [
|
|
@@ -28119,12 +28262,17 @@ async function removeTree(clone, worktreePath, force) {
|
|
|
28119
28262
|
await remove2(force);
|
|
28120
28263
|
return true;
|
|
28121
28264
|
} catch (error) {
|
|
28122
|
-
daemonLog(`worktree ${worktreePath} removal failed: ${
|
|
28265
|
+
daemonLog(`worktree ${worktreePath} removal failed: ${reason3(error)}`);
|
|
28266
|
+
if (force)
|
|
28267
|
+
return await deleteTreeDirectly(
|
|
28268
|
+
clone,
|
|
28269
|
+
worktreePath,
|
|
28270
|
+
`its work was discarded and git could not remove it: ${reason3(error)}`
|
|
28271
|
+
);
|
|
28123
28272
|
}
|
|
28124
|
-
|
|
28125
|
-
return await removeIgnoringLeftovers(remove2, worktreePath);
|
|
28273
|
+
return await removeIgnoringLeftovers(clone, remove2, worktreePath);
|
|
28126
28274
|
}
|
|
28127
|
-
async function removeIgnoringLeftovers(remove2, worktreePath) {
|
|
28275
|
+
async function removeIgnoringLeftovers(clone, remove2, worktreePath) {
|
|
28128
28276
|
try {
|
|
28129
28277
|
await remove2(true);
|
|
28130
28278
|
daemonLog(
|
|
@@ -28133,18 +28281,18 @@ async function removeIgnoringLeftovers(remove2, worktreePath) {
|
|
|
28133
28281
|
return true;
|
|
28134
28282
|
} catch (error) {
|
|
28135
28283
|
daemonLog(
|
|
28136
|
-
`worktree ${worktreePath}
|
|
28284
|
+
`worktree ${worktreePath} forced removal failed: ${reason3(error)}`
|
|
28137
28285
|
);
|
|
28138
|
-
return
|
|
28286
|
+
return await deleteStrandedTree(clone, worktreePath, error);
|
|
28139
28287
|
}
|
|
28140
28288
|
}
|
|
28141
|
-
function
|
|
28289
|
+
function reason3(error) {
|
|
28142
28290
|
return error instanceof Error ? error.message : String(error);
|
|
28143
28291
|
}
|
|
28144
28292
|
|
|
28145
28293
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
28146
28294
|
async function reapWorktree(worktreePath, force = false) {
|
|
28147
|
-
if (!
|
|
28295
|
+
if (!existsSync63(worktreePath)) {
|
|
28148
28296
|
daemonLog(`worktree ${worktreePath} already gone; skipping reap`);
|
|
28149
28297
|
return false;
|
|
28150
28298
|
}
|
|
@@ -28155,13 +28303,24 @@ async function reapWorktree(worktreePath, force = false) {
|
|
|
28155
28303
|
return false;
|
|
28156
28304
|
}
|
|
28157
28305
|
}
|
|
28158
|
-
|
|
28306
|
+
stopInstall(worktreePath);
|
|
28307
|
+
const clone = owningClone(worktreePath);
|
|
28159
28308
|
if (!await removeTree(clone, worktreePath, force)) return false;
|
|
28160
28309
|
await deleteWorktreeBranch(clone, basename16(worktreePath));
|
|
28161
28310
|
forgetWorktree(worktreePath);
|
|
28162
28311
|
daemonLog(`worktree ${worktreePath} reaped${force ? " (forced)" : ""}`);
|
|
28163
28312
|
return true;
|
|
28164
28313
|
}
|
|
28314
|
+
function owningClone(worktreePath) {
|
|
28315
|
+
const recorded = worktreeAttributionIncludingReaped(worktreePath)?.clone;
|
|
28316
|
+
if (recorded && existsSync63(recorded)) return recorded;
|
|
28317
|
+
const detected = mainWorktree(worktreePath);
|
|
28318
|
+
if (detected) return detected;
|
|
28319
|
+
daemonLog(
|
|
28320
|
+
`worktree ${worktreePath} has no resolvable clone; tearing it down on its own`
|
|
28321
|
+
);
|
|
28322
|
+
return worktreePath;
|
|
28323
|
+
}
|
|
28165
28324
|
async function deleteWorktreeBranch(clone, branch2) {
|
|
28166
28325
|
if (!listLocalBranches(clone).includes(branch2)) return;
|
|
28167
28326
|
const current = await gitOrNull2(clone, ["symbolic-ref", "--short", "HEAD"]);
|
|
@@ -28241,12 +28400,12 @@ function setStatus2(session, newStatus) {
|
|
|
28241
28400
|
}
|
|
28242
28401
|
|
|
28243
28402
|
// src/commands/sessions/daemon/worktree/watchGitState.ts
|
|
28244
|
-
import { existsSync as
|
|
28403
|
+
import { existsSync as existsSync64, watch } from "fs";
|
|
28245
28404
|
var DEBOUNCE_MS = 500;
|
|
28246
28405
|
var POLL_MS = 3e4;
|
|
28247
28406
|
function watchGitState(cwd, onChange) {
|
|
28248
28407
|
const common = gitCommonDir(cwd);
|
|
28249
|
-
if (!common || !
|
|
28408
|
+
if (!common || !existsSync64(common)) return void 0;
|
|
28250
28409
|
const watchers = [
|
|
28251
28410
|
watchGitDir(common, onChange),
|
|
28252
28411
|
pollGitState(cwd, onChange)
|
|
@@ -28300,12 +28459,12 @@ async function resolveCloseDurability(session, finalize, notify2) {
|
|
|
28300
28459
|
session.gitWatcher = void 0;
|
|
28301
28460
|
finalize();
|
|
28302
28461
|
}
|
|
28303
|
-
function holdStopped(session, tree,
|
|
28304
|
-
if (session.undurable?.reason !==
|
|
28462
|
+
function holdStopped(session, tree, reason4, finalize, notify2) {
|
|
28463
|
+
if (session.undurable?.reason !== reason4)
|
|
28305
28464
|
daemonLog(
|
|
28306
|
-
`session ${session.id} stopped; ${tree.removable ? "reap" : "close"} blocked in ${tree.path}: ${
|
|
28465
|
+
`session ${session.id} stopped; ${tree.removable ? "reap" : "close"} blocked in ${tree.path}: ${reason4}`
|
|
28307
28466
|
);
|
|
28308
|
-
session.undurable = { reason:
|
|
28467
|
+
session.undurable = { reason: reason4, removesTree: tree.removable };
|
|
28309
28468
|
session.closing = void 0;
|
|
28310
28469
|
setStatus2(session, "stopped");
|
|
28311
28470
|
if (!session.gitWatcher) {
|
|
@@ -28650,10 +28809,10 @@ function emitSessionOutput(session, clients, data) {
|
|
|
28650
28809
|
}
|
|
28651
28810
|
|
|
28652
28811
|
// src/commands/sessions/daemon/exitReason.ts
|
|
28653
|
-
import { existsSync as
|
|
28812
|
+
import { existsSync as existsSync65 } from "fs";
|
|
28654
28813
|
function exitReason(session, exitCode) {
|
|
28655
28814
|
const base = `process exited with code ${exitCode}`;
|
|
28656
|
-
if (session.cwd && !
|
|
28815
|
+
if (session.cwd && !existsSync65(session.cwd))
|
|
28657
28816
|
return `${base}: working directory ${session.cwd} no longer exists`;
|
|
28658
28817
|
return base;
|
|
28659
28818
|
}
|
|
@@ -28671,7 +28830,7 @@ function handleFailedResume(session, exitCode, onStatusChange) {
|
|
|
28671
28830
|
}
|
|
28672
28831
|
|
|
28673
28832
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
28674
|
-
import { existsSync as
|
|
28833
|
+
import { existsSync as existsSync66, mkdirSync as mkdirSync26, watch as watch2 } from "fs";
|
|
28675
28834
|
import { dirname as dirname31 } from "path";
|
|
28676
28835
|
|
|
28677
28836
|
// src/commands/sessions/daemon/applyReviewPause.ts
|
|
@@ -28752,7 +28911,7 @@ function watchActivity(session, notify2, onClaudeSessionId) {
|
|
|
28752
28911
|
if (timer) clearTimeout(timer);
|
|
28753
28912
|
timer = setTimeout(read, DEBOUNCE_MS2);
|
|
28754
28913
|
});
|
|
28755
|
-
if (
|
|
28914
|
+
if (existsSync66(path71)) read();
|
|
28756
28915
|
}
|
|
28757
28916
|
function refreshActivity(session) {
|
|
28758
28917
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -29767,14 +29926,14 @@ function restoreSession(id, persisted) {
|
|
|
29767
29926
|
}
|
|
29768
29927
|
|
|
29769
29928
|
// src/commands/sessions/daemon/restoreOne.ts
|
|
29770
|
-
function restoreOne(persisted,
|
|
29929
|
+
function restoreOne(persisted, spawn13, sessions) {
|
|
29771
29930
|
try {
|
|
29772
|
-
const id =
|
|
29931
|
+
const id = spawn13((sid) => restoreSession(sid, persisted));
|
|
29773
29932
|
logUnresumable(persisted.name, id, sessions.get(id));
|
|
29774
29933
|
} catch (error) {
|
|
29775
|
-
const
|
|
29934
|
+
const reason4 = logRestoreError(persisted.name, error);
|
|
29776
29935
|
try {
|
|
29777
|
-
|
|
29936
|
+
spawn13((id) => errorSession(id, persisted, reason4));
|
|
29778
29937
|
} catch {
|
|
29779
29938
|
}
|
|
29780
29939
|
}
|
|
@@ -29786,9 +29945,9 @@ function logUnresumable(name, id, session) {
|
|
|
29786
29945
|
);
|
|
29787
29946
|
}
|
|
29788
29947
|
function logRestoreError(name, error) {
|
|
29789
|
-
const
|
|
29790
|
-
daemonLog(`failed to restore session "${name}": ${
|
|
29791
|
-
return
|
|
29948
|
+
const reason4 = error instanceof Error ? error.message : String(error);
|
|
29949
|
+
daemonLog(`failed to restore session "${name}": ${reason4}`);
|
|
29950
|
+
return reason4;
|
|
29792
29951
|
}
|
|
29793
29952
|
|
|
29794
29953
|
// src/commands/sessions/daemon/sessionLimits.ts
|
|
@@ -29809,7 +29968,7 @@ var sessionLimits = {
|
|
|
29809
29968
|
};
|
|
29810
29969
|
|
|
29811
29970
|
// src/commands/sessions/daemon/restoreAll.ts
|
|
29812
|
-
function restoreAll(
|
|
29971
|
+
function restoreAll(spawn13, sessions) {
|
|
29813
29972
|
const persisted = loadPersistedSessions();
|
|
29814
29973
|
const toRestore = persisted.slice(0, sessionLimits.maxRestore);
|
|
29815
29974
|
const skipped = persisted.length - toRestore.length;
|
|
@@ -29818,7 +29977,7 @@ function restoreAll(spawn12, sessions) {
|
|
|
29818
29977
|
`restore capped at ${sessionLimits.maxRestore}; skipping ${skipped} persisted session(s)`
|
|
29819
29978
|
);
|
|
29820
29979
|
return toRestore.map((persisted2) => {
|
|
29821
|
-
restoreOne(persisted2,
|
|
29980
|
+
restoreOne(persisted2, spawn13, sessions);
|
|
29822
29981
|
return persisted2.name;
|
|
29823
29982
|
});
|
|
29824
29983
|
}
|
|
@@ -29841,7 +30000,7 @@ function rearmStoppedSessions(sessions, notify2) {
|
|
|
29841
30000
|
}
|
|
29842
30001
|
|
|
29843
30002
|
// src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
|
|
29844
|
-
import { existsSync as
|
|
30003
|
+
import { existsSync as existsSync69 } from "fs";
|
|
29845
30004
|
import { basename as basename18 } from "path";
|
|
29846
30005
|
|
|
29847
30006
|
// src/commands/sessions/daemon/worktree/accountedTrees.ts
|
|
@@ -29897,10 +30056,10 @@ function bindResumedWorktree(session, cwd, notify2) {
|
|
|
29897
30056
|
|
|
29898
30057
|
// src/commands/sessions/daemon/worktree/describeHeldWork.ts
|
|
29899
30058
|
var MAX_ITEMS = 20;
|
|
29900
|
-
async function describeHeldWork(path71,
|
|
29901
|
-
if (
|
|
29902
|
-
if (
|
|
29903
|
-
return { summary:
|
|
30059
|
+
async function describeHeldWork(path71, reason4) {
|
|
30060
|
+
if (reason4.startsWith("uncommitted")) return await changedFiles(path71);
|
|
30061
|
+
if (reason4.startsWith("unpushed")) return await unpushedCommits(path71, reason4);
|
|
30062
|
+
return { summary: reason4, items: [] };
|
|
29904
30063
|
}
|
|
29905
30064
|
async function changedFiles(path71) {
|
|
29906
30065
|
const status3 = await gitResult(path71, ["status", "--porcelain"]);
|
|
@@ -29910,9 +30069,9 @@ async function changedFiles(path71) {
|
|
|
29910
30069
|
items: capped(lines)
|
|
29911
30070
|
};
|
|
29912
30071
|
}
|
|
29913
|
-
async function unpushedCommits(path71,
|
|
30072
|
+
async function unpushedCommits(path71, reason4) {
|
|
29914
30073
|
const log = await gitResult(path71, ["log", "--oneline", "@{upstream}..HEAD"]);
|
|
29915
|
-
if (!log.ok) return { summary:
|
|
30074
|
+
if (!log.ok) return { summary: reason4, items: [] };
|
|
29916
30075
|
const lines = nonEmptyLines(log.out);
|
|
29917
30076
|
return {
|
|
29918
30077
|
summary: `${lines.length} unpushed ${lines.length === 1 ? "commit" : "commits"}`,
|
|
@@ -29931,20 +30090,20 @@ function capped(lines) {
|
|
|
29931
30090
|
}
|
|
29932
30091
|
|
|
29933
30092
|
// src/commands/sessions/daemon/worktree/reclaimVanishedWorktrees.ts
|
|
29934
|
-
import { existsSync as
|
|
30093
|
+
import { existsSync as existsSync68 } from "fs";
|
|
29935
30094
|
async function reclaimVanishedWorktrees(clone, paths) {
|
|
29936
|
-
if (!
|
|
30095
|
+
if (!existsSync68(clone)) {
|
|
29937
30096
|
for (const { path: path71 } of paths) forgetWorktree(path71);
|
|
29938
30097
|
daemonLog(
|
|
29939
30098
|
`clone ${clone} is gone; forgot ${paths.length} worktree record(s) it owned`
|
|
29940
30099
|
);
|
|
29941
30100
|
return;
|
|
29942
30101
|
}
|
|
29943
|
-
await
|
|
30102
|
+
await pruneBookkeeping2(clone);
|
|
29944
30103
|
for (const { path: path71, branch: branch2 } of paths)
|
|
29945
30104
|
if (await reclaimBranch(clone, branch2)) forgetWorktree(path71);
|
|
29946
30105
|
}
|
|
29947
|
-
async function
|
|
30106
|
+
async function pruneBookkeeping2(clone) {
|
|
29948
30107
|
try {
|
|
29949
30108
|
await git2(clone, ["worktree", "prune"]);
|
|
29950
30109
|
daemonLog(`worktree bookkeeping pruned for clone ${clone}`);
|
|
@@ -29971,7 +30130,7 @@ async function reclaimBranch(clone, branch2) {
|
|
|
29971
30130
|
// src/commands/sessions/daemon/worktree/resurfaceOrphanedWorktree.ts
|
|
29972
30131
|
import { basename as basename17 } from "path";
|
|
29973
30132
|
function resurfaceOrphanedWorktree(sessions, spawnWith, recovered, notify2) {
|
|
29974
|
-
const { orphan, reason:
|
|
30133
|
+
const { orphan, reason: reason4, held } = recovered;
|
|
29975
30134
|
let id;
|
|
29976
30135
|
try {
|
|
29977
30136
|
id = spawnWith((sid) => orphanedSession(sid, recovered));
|
|
@@ -29982,14 +30141,14 @@ function resurfaceOrphanedWorktree(sessions, spawnWith, recovered, notify2) {
|
|
|
29982
30141
|
return;
|
|
29983
30142
|
}
|
|
29984
30143
|
daemonLog(
|
|
29985
|
-
`orphaned worktree ${orphan.path} resurfaced as stopped session ${id}: ${
|
|
30144
|
+
`orphaned worktree ${orphan.path} resurfaced as stopped session ${id}: ${reason4} (${held.summary})`
|
|
29986
30145
|
);
|
|
29987
30146
|
const session = sessions.get(id);
|
|
29988
30147
|
if (session) armStoppedSession(sessions, session, notify2);
|
|
29989
30148
|
notify2();
|
|
29990
30149
|
}
|
|
29991
30150
|
function orphanedSession(id, recovered) {
|
|
29992
|
-
const { orphan, reason:
|
|
30151
|
+
const { orphan, reason: reason4, held } = recovered;
|
|
29993
30152
|
return {
|
|
29994
30153
|
...sessionBase(id, "stopped"),
|
|
29995
30154
|
name: `recovered ${basename17(orphan.path)}`,
|
|
@@ -29998,7 +30157,7 @@ function orphanedSession(id, recovered) {
|
|
|
29998
30157
|
pty: null,
|
|
29999
30158
|
cwd: orphan.path,
|
|
30000
30159
|
worktree: { path: orphan.path, clone: orphan.clone },
|
|
30001
|
-
undurable: { reason:
|
|
30160
|
+
undurable: { reason: reason4, removesTree: true },
|
|
30002
30161
|
scrollback: recoveryNotice(recovered)
|
|
30003
30162
|
};
|
|
30004
30163
|
}
|
|
@@ -30026,7 +30185,7 @@ async function recoverOrphanedWorktrees(sessions, spawnWith, notify2) {
|
|
|
30026
30185
|
const vanished = /* @__PURE__ */ new Map();
|
|
30027
30186
|
for (const { path: path71, clone } of readWorktreeRegistry()) {
|
|
30028
30187
|
if (accounted.has(path71)) continue;
|
|
30029
|
-
if (!
|
|
30188
|
+
if (!existsSync69(path71)) {
|
|
30030
30189
|
vanished.set(clone, [
|
|
30031
30190
|
...vanished.get(clone) ?? [],
|
|
30032
30191
|
{ path: path71, branch: basename18(path71) }
|
|
@@ -30239,6 +30398,12 @@ function startHeldSession(session, sessions, clients, onStatusChange, notify2) {
|
|
|
30239
30398
|
);
|
|
30240
30399
|
return;
|
|
30241
30400
|
}
|
|
30401
|
+
if (session.closing) {
|
|
30402
|
+
daemonLog(
|
|
30403
|
+
`session ${session.id} not started after seeding: card is closing (${session.worktree?.path ?? "no worktree"})`
|
|
30404
|
+
);
|
|
30405
|
+
return;
|
|
30406
|
+
}
|
|
30242
30407
|
session.startedAt = Date.now();
|
|
30243
30408
|
if (session.status === "running") session.runningSince = session.startedAt;
|
|
30244
30409
|
session.pty = start3();
|
|
@@ -30315,7 +30480,7 @@ async function isWindowsDaemonRunning() {
|
|
|
30315
30480
|
}
|
|
30316
30481
|
|
|
30317
30482
|
// src/commands/sessions/daemon/ensureWindowsDaemonRunning.ts
|
|
30318
|
-
import { spawn as
|
|
30483
|
+
import { spawn as spawn11 } from "child_process";
|
|
30319
30484
|
|
|
30320
30485
|
// src/commands/sessions/daemon/logChildStream.ts
|
|
30321
30486
|
import { createInterface as createInterface7 } from "readline";
|
|
@@ -30340,7 +30505,7 @@ async function ensureWindowsDaemonRunning() {
|
|
|
30340
30505
|
await waitForWindowsDaemon();
|
|
30341
30506
|
}
|
|
30342
30507
|
function launchWindowsDaemon() {
|
|
30343
|
-
const child =
|
|
30508
|
+
const child = spawn11("pwsh.exe", ["-Command", "assist daemon run"], {
|
|
30344
30509
|
detached: true,
|
|
30345
30510
|
stdio: ["ignore", "pipe", "pipe"]
|
|
30346
30511
|
});
|
|
@@ -30388,13 +30553,13 @@ async function defaultConnect() {
|
|
|
30388
30553
|
}
|
|
30389
30554
|
|
|
30390
30555
|
// src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
|
|
30391
|
-
import { existsSync as
|
|
30556
|
+
import { existsSync as existsSync70, readFileSync as readFileSync50 } from "fs";
|
|
30392
30557
|
import { posix } from "path";
|
|
30393
30558
|
function hasPersistedWindowsSessions() {
|
|
30394
30559
|
const sessionsFile = windowsSessionsFileFromWsl();
|
|
30395
30560
|
if (!sessionsFile) return false;
|
|
30396
30561
|
try {
|
|
30397
|
-
if (!
|
|
30562
|
+
if (!existsSync70(sessionsFile)) return false;
|
|
30398
30563
|
const data = JSON.parse(readFileSync50(sessionsFile, "utf8"));
|
|
30399
30564
|
return Array.isArray(data) && data.length > 0;
|
|
30400
30565
|
} catch (error) {
|
|
@@ -30643,7 +30808,7 @@ function handleWindowsClose(state) {
|
|
|
30643
30808
|
}
|
|
30644
30809
|
|
|
30645
30810
|
// src/commands/sessions/daemon/healWindowsDaemon.ts
|
|
30646
|
-
import { spawn as
|
|
30811
|
+
import { spawn as spawn12 } from "child_process";
|
|
30647
30812
|
var UPDATE_TIMEOUT_MS = 5 * 6e4;
|
|
30648
30813
|
var STOP_TIMEOUT_MS2 = 3e4;
|
|
30649
30814
|
async function healWindowsDaemon() {
|
|
@@ -30663,7 +30828,7 @@ async function healWindowsDaemon() {
|
|
|
30663
30828
|
}
|
|
30664
30829
|
function runOnWindowsHost(command, timeoutMs) {
|
|
30665
30830
|
return new Promise((resolve20, reject) => {
|
|
30666
|
-
const child =
|
|
30831
|
+
const child = spawn12("pwsh.exe", ["-Command", command], {
|
|
30667
30832
|
stdio: ["ignore", "pipe", "pipe"]
|
|
30668
30833
|
});
|
|
30669
30834
|
logChildStream(child.stdout, `windows ${command}`);
|
|
@@ -31285,10 +31450,10 @@ import * as net3 from "net";
|
|
|
31285
31450
|
import { createInterface as createInterface9 } from "readline";
|
|
31286
31451
|
|
|
31287
31452
|
// src/commands/sessions/daemon/creator.ts
|
|
31288
|
-
function creator(isNew,
|
|
31453
|
+
function creator(isNew, spawn13) {
|
|
31289
31454
|
return (client, m, d) => {
|
|
31290
31455
|
if (m.windowsProxy.route(client, d)) return;
|
|
31291
|
-
sendTo(client, { type: "created", sessionId:
|
|
31456
|
+
sendTo(client, { type: "created", sessionId: spawn13(m, d), isNew });
|
|
31292
31457
|
};
|
|
31293
31458
|
}
|
|
31294
31459
|
|
|
@@ -32018,13 +32183,13 @@ function buildLimitsSegment(rateLimits) {
|
|
|
32018
32183
|
}
|
|
32019
32184
|
|
|
32020
32185
|
// src/commands/readGitBranch.ts
|
|
32021
|
-
import { readFileSync as readFileSync53, statSync as
|
|
32022
|
-
import { isAbsolute as isAbsolute3, join as
|
|
32186
|
+
import { readFileSync as readFileSync53, statSync as statSync13 } from "fs";
|
|
32187
|
+
import { isAbsolute as isAbsolute3, join as join75, resolve as resolve18 } from "path";
|
|
32023
32188
|
function resolveGitDir(cwd) {
|
|
32024
|
-
const dotGit =
|
|
32189
|
+
const dotGit = join75(cwd, ".git");
|
|
32025
32190
|
let stat3;
|
|
32026
32191
|
try {
|
|
32027
|
-
stat3 =
|
|
32192
|
+
stat3 = statSync13(dotGit);
|
|
32028
32193
|
} catch {
|
|
32029
32194
|
return null;
|
|
32030
32195
|
}
|
|
@@ -32051,7 +32216,7 @@ function readGitBranch(cwd) {
|
|
|
32051
32216
|
}
|
|
32052
32217
|
let head;
|
|
32053
32218
|
try {
|
|
32054
|
-
head = readFileSync53(
|
|
32219
|
+
head = readFileSync53(join75(gitDir, "HEAD"), "utf8");
|
|
32055
32220
|
} catch {
|
|
32056
32221
|
return null;
|
|
32057
32222
|
}
|