@staff0rd/assist 0.444.1 → 0.446.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 +10 -3
- package/dist/commands/sessions/web/bundle.js +2 -2
- package/dist/index.js +963 -773
- 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.446.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -121,7 +121,7 @@ var package_default = {
|
|
|
121
121
|
};
|
|
122
122
|
|
|
123
123
|
// src/commands/commit.ts
|
|
124
|
-
import { execSync as
|
|
124
|
+
import { execSync as execSync7 } from "child_process";
|
|
125
125
|
|
|
126
126
|
// src/shared/resolveSessionItemId.ts
|
|
127
127
|
var ITEM_ID_ENV = "ASSIST_BACKLOG_ITEM_ID";
|
|
@@ -435,6 +435,7 @@ var assistConfigSchema = z2.strictObject({
|
|
|
435
435
|
repos: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional(),
|
|
436
436
|
worktree: z2.strictObject({
|
|
437
437
|
enabled: z2.boolean().default(false),
|
|
438
|
+
trunk: z2.boolean().default(false),
|
|
438
439
|
root: z2.string().optional(),
|
|
439
440
|
install: z2.union([z2.boolean(), z2.string()]).default(true),
|
|
440
441
|
commitBeforeManualChecks: z2.boolean().default(false),
|
|
@@ -502,7 +503,8 @@ var assistConfigSchema = z2.strictObject({
|
|
|
502
503
|
windowsDaemonHost: z2.string().optional(),
|
|
503
504
|
// why: TCP port the native Windows daemon listens on for the WSL bridge; defaults to 51764
|
|
504
505
|
windowsDaemonPort: z2.number().optional(),
|
|
505
|
-
windowsVersionCheck: z2.enum(["block", "warn", "off"]).default("block")
|
|
506
|
+
windowsVersionCheck: z2.enum(["block", "warn", "off"]).default("block"),
|
|
507
|
+
includeCommittedChanges: z2.boolean().default(false)
|
|
506
508
|
}).optional(),
|
|
507
509
|
database: z2.strictObject({
|
|
508
510
|
url: z2.string().optional()
|
|
@@ -1782,17 +1784,49 @@ function git(args) {
|
|
|
1782
1784
|
}
|
|
1783
1785
|
}
|
|
1784
1786
|
|
|
1785
|
-
// src/commands/commit/
|
|
1787
|
+
// src/commands/commit/pushCommit.ts
|
|
1786
1788
|
import { execSync as execSync5 } from "child_process";
|
|
1789
|
+
var HEADS_PREFIX = "refs/heads/";
|
|
1790
|
+
function pushCommit() {
|
|
1791
|
+
const target = renamedUpstream();
|
|
1792
|
+
const command = target ? `git push ${shellQuote(target.remote)} HEAD:${shellQuote(target.branch)}` : "git push";
|
|
1793
|
+
execSync5(command, { stdio: "inherit" });
|
|
1794
|
+
}
|
|
1795
|
+
function renamedUpstream() {
|
|
1796
|
+
const branch2 = gitOrNull("git symbolic-ref --short HEAD");
|
|
1797
|
+
if (!branch2) return null;
|
|
1798
|
+
const remote = gitOrNull(
|
|
1799
|
+
`git config --get branch.${shellQuote(branch2)}.remote`
|
|
1800
|
+
);
|
|
1801
|
+
const merge = gitOrNull(
|
|
1802
|
+
`git config --get branch.${shellQuote(branch2)}.merge`
|
|
1803
|
+
);
|
|
1804
|
+
if (!remote || !merge) return null;
|
|
1805
|
+
const upstream = merge.startsWith(HEADS_PREFIX) ? merge.slice(HEADS_PREFIX.length) : merge;
|
|
1806
|
+
return upstream === branch2 ? null : { remote, branch: upstream };
|
|
1807
|
+
}
|
|
1808
|
+
function gitOrNull(command) {
|
|
1809
|
+
try {
|
|
1810
|
+
return execSync5(command, {
|
|
1811
|
+
encoding: "utf8",
|
|
1812
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1813
|
+
}).trim() || null;
|
|
1814
|
+
} catch {
|
|
1815
|
+
return null;
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
// src/commands/commit/stageAndCommit.ts
|
|
1820
|
+
import { execSync as execSync6 } from "child_process";
|
|
1787
1821
|
function commitStaged(message2) {
|
|
1788
|
-
|
|
1789
|
-
return
|
|
1822
|
+
execSync6(`git commit -m ${shellQuote(message2)}`, { stdio: "inherit" });
|
|
1823
|
+
return execSync6("git rev-parse --short=7 HEAD", {
|
|
1790
1824
|
encoding: "utf8"
|
|
1791
1825
|
}).trim();
|
|
1792
1826
|
}
|
|
1793
1827
|
function stageAndCommit(files, message2) {
|
|
1794
1828
|
const escaped = files.map(shellQuote).join(" ");
|
|
1795
|
-
|
|
1829
|
+
execSync6(`git add ${escaped}`, { stdio: "inherit" });
|
|
1796
1830
|
return commitStaged(message2);
|
|
1797
1831
|
}
|
|
1798
1832
|
|
|
@@ -1920,13 +1954,13 @@ async function execCommit(files, message2, config) {
|
|
|
1920
1954
|
warnIfUnexpectedBranch(config);
|
|
1921
1955
|
const pulled = Boolean(config.commit?.pull);
|
|
1922
1956
|
if (pulled) {
|
|
1923
|
-
|
|
1957
|
+
execSync7("git pull --autostash", { stdio: "inherit" });
|
|
1924
1958
|
}
|
|
1925
1959
|
abortOnConflicts(files, pulled);
|
|
1926
1960
|
const sha = files.length > 0 ? stageAndCommit(files, message2) : commitStaged(message2);
|
|
1927
1961
|
console.log(`Committed: ${sha}`);
|
|
1928
1962
|
if (config.commit?.push) {
|
|
1929
|
-
|
|
1963
|
+
pushCommit();
|
|
1930
1964
|
console.log("Pushed to remote");
|
|
1931
1965
|
}
|
|
1932
1966
|
await recordCommitActivity(message2);
|
|
@@ -1941,7 +1975,7 @@ async function recordCommitActivity(message2) {
|
|
|
1941
1975
|
}
|
|
1942
1976
|
async function commit(args) {
|
|
1943
1977
|
if (args[0] === "status") {
|
|
1944
|
-
|
|
1978
|
+
execSync7("git status && echo '---DIFF---' && git diff", {
|
|
1945
1979
|
stdio: "inherit"
|
|
1946
1980
|
});
|
|
1947
1981
|
return;
|
|
@@ -1958,9 +1992,9 @@ async function commit(args) {
|
|
|
1958
1992
|
}
|
|
1959
1993
|
|
|
1960
1994
|
// src/commands/coverage.ts
|
|
1961
|
-
import { execSync as
|
|
1995
|
+
import { execSync as execSync8 } from "child_process";
|
|
1962
1996
|
function coverage() {
|
|
1963
|
-
const output =
|
|
1997
|
+
const output = execSync8(
|
|
1964
1998
|
"npx vitest run --coverage --coverage.include='src/**/*.ts' --coverage.all --coverage.reporter=text 2>&1",
|
|
1965
1999
|
{ encoding: "utf8", timeout: 12e4 }
|
|
1966
2000
|
);
|
|
@@ -2060,7 +2094,7 @@ function findPackageJsonWithVerifyScripts(startDir) {
|
|
|
2060
2094
|
}
|
|
2061
2095
|
|
|
2062
2096
|
// src/commands/verify/installPackage.ts
|
|
2063
|
-
import { execSync as
|
|
2097
|
+
import { execSync as execSync9 } from "child_process";
|
|
2064
2098
|
import { writeFileSync as writeFileSync2 } from "fs";
|
|
2065
2099
|
import chalk6 from "chalk";
|
|
2066
2100
|
function writePackageJson(filePath, pkg) {
|
|
@@ -2079,7 +2113,7 @@ function addScript(pkg, name, command) {
|
|
|
2079
2113
|
function installPackage(name, cwd) {
|
|
2080
2114
|
console.log(chalk6.dim(`Installing ${name}...`));
|
|
2081
2115
|
try {
|
|
2082
|
-
|
|
2116
|
+
execSync9(`npm install -D ${name}`, { stdio: "inherit", cwd });
|
|
2083
2117
|
return true;
|
|
2084
2118
|
} catch {
|
|
2085
2119
|
console.error(chalk6.red(`Failed to install ${name}`));
|
|
@@ -2323,7 +2357,7 @@ import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync
|
|
|
2323
2357
|
import chalk14 from "chalk";
|
|
2324
2358
|
|
|
2325
2359
|
// src/shared/removeEslint/index.ts
|
|
2326
|
-
import { execSync as
|
|
2360
|
+
import { execSync as execSync10 } from "child_process";
|
|
2327
2361
|
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
2328
2362
|
|
|
2329
2363
|
// src/shared/removeEslint/removeEslintConfigFiles.ts
|
|
@@ -2358,7 +2392,7 @@ function removeEslint(options2 = {}) {
|
|
|
2358
2392
|
const removedConfigFiles = removeEslintConfigFiles();
|
|
2359
2393
|
if (removedFromPackageJson || removedConfigFiles) {
|
|
2360
2394
|
console.log("Running npm install...");
|
|
2361
|
-
|
|
2395
|
+
execSync10("npm install", { stdio: "inherit" });
|
|
2362
2396
|
return true;
|
|
2363
2397
|
}
|
|
2364
2398
|
return false;
|
|
@@ -3206,11 +3240,11 @@ function lint(options2 = {}) {
|
|
|
3206
3240
|
}
|
|
3207
3241
|
|
|
3208
3242
|
// src/commands/new/registerNew/newCli/index.ts
|
|
3209
|
-
import { execSync as
|
|
3243
|
+
import { execSync as execSync19 } from "child_process";
|
|
3210
3244
|
import { basename as basename2, resolve as resolve5 } from "path";
|
|
3211
3245
|
|
|
3212
3246
|
// src/commands/verify/blockCodeComments/findComments.ts
|
|
3213
|
-
import { execSync as
|
|
3247
|
+
import { execSync as execSync11 } from "child_process";
|
|
3214
3248
|
import fs15 from "fs";
|
|
3215
3249
|
import { minimatch } from "minimatch";
|
|
3216
3250
|
import { Project as Project2 } from "ts-morph";
|
|
@@ -3470,7 +3504,7 @@ function shouldScan(file, ignoreGlobs) {
|
|
|
3470
3504
|
return fs15.existsSync(file);
|
|
3471
3505
|
}
|
|
3472
3506
|
function findComments(options2) {
|
|
3473
|
-
const diff3 =
|
|
3507
|
+
const diff3 = execSync11("git diff HEAD", {
|
|
3474
3508
|
encoding: "utf8",
|
|
3475
3509
|
maxBuffer: 64 * 1024 * 1024
|
|
3476
3510
|
});
|
|
@@ -3716,13 +3750,13 @@ Total: ${violations.length} forbidden string(s).`);
|
|
|
3716
3750
|
}
|
|
3717
3751
|
|
|
3718
3752
|
// src/commands/verify/hardcodedColors.ts
|
|
3719
|
-
import { execSync as
|
|
3753
|
+
import { execSync as execSync12 } from "child_process";
|
|
3720
3754
|
import { minimatch as minimatch3 } from "minimatch";
|
|
3721
3755
|
var pattern = "0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}";
|
|
3722
3756
|
function hardcodedColors() {
|
|
3723
3757
|
const ignoreGlobs = loadConfig().hardcodedColors?.ignore ?? [];
|
|
3724
3758
|
try {
|
|
3725
|
-
const output =
|
|
3759
|
+
const output = execSync12(`grep -rEnH '${pattern}' src/`, {
|
|
3726
3760
|
encoding: "utf8"
|
|
3727
3761
|
});
|
|
3728
3762
|
const lines = output.trim().split("\n").filter((line) => {
|
|
@@ -3983,14 +4017,14 @@ function listMigrationFiles(dir) {
|
|
|
3983
4017
|
}
|
|
3984
4018
|
|
|
3985
4019
|
// src/commands/verify/migrations/readBaselineMigrations.ts
|
|
3986
|
-
import { execSync as
|
|
4020
|
+
import { execSync as execSync13 } from "child_process";
|
|
3987
4021
|
import { basename } from "path";
|
|
3988
4022
|
var MIGRATION_FILE3 = /^migration\d+[A-Za-z0-9]*\.ts$/;
|
|
3989
4023
|
function readBaselineMigrations(repoRelativeDir, ref) {
|
|
3990
4024
|
const baseline = /* @__PURE__ */ new Map();
|
|
3991
4025
|
let listing;
|
|
3992
4026
|
try {
|
|
3993
|
-
listing =
|
|
4027
|
+
listing = execSync13(
|
|
3994
4028
|
`git ls-tree -r --name-only "${ref}" -- "${repoRelativeDir}"`,
|
|
3995
4029
|
{ encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }
|
|
3996
4030
|
);
|
|
@@ -4000,7 +4034,7 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
4000
4034
|
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path71) => MIGRATION_FILE3.test(basename(path71)));
|
|
4001
4035
|
for (const path71 of paths) {
|
|
4002
4036
|
try {
|
|
4003
|
-
const content =
|
|
4037
|
+
const content = execSync13(`git show "${ref}:${path71}"`, {
|
|
4004
4038
|
encoding: "utf8",
|
|
4005
4039
|
maxBuffer: 16 * 1024 * 1024,
|
|
4006
4040
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4013,10 +4047,10 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
4013
4047
|
}
|
|
4014
4048
|
|
|
4015
4049
|
// src/commands/verify/migrations/resolveBaselineRef.ts
|
|
4016
|
-
import { execSync as
|
|
4050
|
+
import { execSync as execSync14 } from "child_process";
|
|
4017
4051
|
function refExists(ref) {
|
|
4018
4052
|
try {
|
|
4019
|
-
|
|
4053
|
+
execSync14(`git rev-parse --verify --quiet "${ref}"`, {
|
|
4020
4054
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4021
4055
|
});
|
|
4022
4056
|
return true;
|
|
@@ -4088,10 +4122,10 @@ Total: ${problems.length} violation(s).`);
|
|
|
4088
4122
|
}
|
|
4089
4123
|
|
|
4090
4124
|
// src/commands/verify/noVenv.ts
|
|
4091
|
-
import { execSync as
|
|
4125
|
+
import { execSync as execSync15 } from "child_process";
|
|
4092
4126
|
function noVenv() {
|
|
4093
4127
|
try {
|
|
4094
|
-
const output =
|
|
4128
|
+
const output = execSync15(
|
|
4095
4129
|
"find . -type d -name venv -not -path '*/node_modules/*'",
|
|
4096
4130
|
{
|
|
4097
4131
|
encoding: "utf8"
|
|
@@ -4123,9 +4157,9 @@ Total: ${folders.length} venv folder(s)`);
|
|
|
4123
4157
|
import { minimatch as minimatch4 } from "minimatch";
|
|
4124
4158
|
|
|
4125
4159
|
// src/commands/verify/run/getChangedFiles.ts
|
|
4126
|
-
import { execSync as
|
|
4160
|
+
import { execSync as execSync16 } from "child_process";
|
|
4127
4161
|
function getChangedFiles() {
|
|
4128
|
-
const output =
|
|
4162
|
+
const output = execSync16("git diff --name-only HEAD", {
|
|
4129
4163
|
encoding: "utf8"
|
|
4130
4164
|
}).trim();
|
|
4131
4165
|
if (output === "") return [];
|
|
@@ -4297,25 +4331,25 @@ async function run(options2 = {}) {
|
|
|
4297
4331
|
}
|
|
4298
4332
|
|
|
4299
4333
|
// src/commands/new/registerNew/initGit.ts
|
|
4300
|
-
import { execSync as
|
|
4334
|
+
import { execSync as execSync17 } from "child_process";
|
|
4301
4335
|
import { writeFileSync as writeFileSync10 } from "fs";
|
|
4302
4336
|
function initGit() {
|
|
4303
4337
|
console.log("Initializing git repository...");
|
|
4304
|
-
|
|
4338
|
+
execSync17("git init", { stdio: "inherit" });
|
|
4305
4339
|
writeFileSync10(".gitignore", "dist\nnode_modules\n");
|
|
4306
4340
|
}
|
|
4307
4341
|
|
|
4308
4342
|
// src/commands/new/registerNew/newCli/initPackageJson.ts
|
|
4309
|
-
import { execSync as
|
|
4343
|
+
import { execSync as execSync18 } from "child_process";
|
|
4310
4344
|
function initPackageJson(name) {
|
|
4311
4345
|
console.log("Initializing package.json...");
|
|
4312
|
-
|
|
4346
|
+
execSync18("npm init -y", { stdio: "inherit" });
|
|
4313
4347
|
console.log("Configuring package.json...");
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4348
|
+
execSync18("npm pkg delete main", { stdio: "inherit" });
|
|
4349
|
+
execSync18("npm pkg set type=module", { stdio: "inherit" });
|
|
4350
|
+
execSync18(`npm pkg set bin.${name}=./dist/index.js`, { stdio: "inherit" });
|
|
4351
|
+
execSync18("npm pkg set scripts.build=tsup", { stdio: "inherit" });
|
|
4352
|
+
execSync18('npm pkg set scripts.start="node dist/index.js"', {
|
|
4319
4353
|
stdio: "inherit"
|
|
4320
4354
|
});
|
|
4321
4355
|
}
|
|
@@ -4380,8 +4414,8 @@ async function newCli() {
|
|
|
4380
4414
|
initGit();
|
|
4381
4415
|
initPackageJson(name);
|
|
4382
4416
|
console.log("Installing dependencies...");
|
|
4383
|
-
|
|
4384
|
-
|
|
4417
|
+
execSync19("npm install commander", { stdio: "inherit" });
|
|
4418
|
+
execSync19("npm install -D tsup typescript @types/node", {
|
|
4385
4419
|
stdio: "inherit"
|
|
4386
4420
|
});
|
|
4387
4421
|
writeCliTemplate(name);
|
|
@@ -4390,11 +4424,11 @@ async function newCli() {
|
|
|
4390
4424
|
}
|
|
4391
4425
|
|
|
4392
4426
|
// src/commands/new/registerNew/newProject.ts
|
|
4393
|
-
import { execSync as
|
|
4427
|
+
import { execSync as execSync21 } from "child_process";
|
|
4394
4428
|
import { existsSync as existsSync15, readFileSync as readFileSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
4395
4429
|
|
|
4396
4430
|
// src/commands/deploy/init/index.ts
|
|
4397
|
-
import { execSync as
|
|
4431
|
+
import { execSync as execSync20 } from "child_process";
|
|
4398
4432
|
import chalk28 from "chalk";
|
|
4399
4433
|
import enquirer3 from "enquirer";
|
|
4400
4434
|
|
|
@@ -4447,7 +4481,7 @@ Created ${WORKFLOW_PATH}`));
|
|
|
4447
4481
|
// src/commands/deploy/init/index.ts
|
|
4448
4482
|
async function ensureNetlifyCli() {
|
|
4449
4483
|
try {
|
|
4450
|
-
|
|
4484
|
+
execSync20("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
4451
4485
|
} catch (error) {
|
|
4452
4486
|
if (!(error instanceof Error) || !error.message.includes("command not found"))
|
|
4453
4487
|
throw error;
|
|
@@ -4462,9 +4496,9 @@ async function ensureNetlifyCli() {
|
|
|
4462
4496
|
process.exit(1);
|
|
4463
4497
|
}
|
|
4464
4498
|
console.log(chalk28.dim("\nInstalling netlify-cli...\n"));
|
|
4465
|
-
|
|
4499
|
+
execSync20("npm install -g netlify-cli", { stdio: "inherit" });
|
|
4466
4500
|
console.log();
|
|
4467
|
-
|
|
4501
|
+
execSync20("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
4468
4502
|
}
|
|
4469
4503
|
}
|
|
4470
4504
|
function printSetupInstructions() {
|
|
@@ -4507,7 +4541,7 @@ async function init6() {
|
|
|
4507
4541
|
// src/commands/new/registerNew/newProject.ts
|
|
4508
4542
|
async function newProject() {
|
|
4509
4543
|
console.log("Initializing Vite with react-ts template...");
|
|
4510
|
-
|
|
4544
|
+
execSync21("npm create vite@latest . -- --template react-ts", {
|
|
4511
4545
|
stdio: "inherit"
|
|
4512
4546
|
});
|
|
4513
4547
|
initGit();
|
|
@@ -4698,11 +4732,11 @@ function activityChart(data, range) {
|
|
|
4698
4732
|
}
|
|
4699
4733
|
|
|
4700
4734
|
// src/commands/activity/fetchCommitsPerDay.ts
|
|
4701
|
-
import { execSync as
|
|
4735
|
+
import { execSync as execSync22 } from "child_process";
|
|
4702
4736
|
function fetchContributions(from, to) {
|
|
4703
4737
|
const query = `{ viewer { contributionsCollection(from: "${from}T00:00:00Z", to: "${to}T23:59:59Z") { contributionCalendar { weeks { contributionDays { date contributionCount } } } } } }`;
|
|
4704
4738
|
const jq = ".data.viewer.contributionsCollection.contributionCalendar.weeks[].contributionDays[]";
|
|
4705
|
-
const raw =
|
|
4739
|
+
const raw = execSync22(`gh api graphql -f query='${query}' --jq '${jq}'`, {
|
|
4706
4740
|
encoding: "utf8"
|
|
4707
4741
|
}).trim();
|
|
4708
4742
|
if (!raw) return [];
|
|
@@ -4789,10 +4823,10 @@ import { join as join10 } from "path";
|
|
|
4789
4823
|
import chalk29 from "chalk";
|
|
4790
4824
|
|
|
4791
4825
|
// src/commands/backup/readCrontab.ts
|
|
4792
|
-
import { execSync as
|
|
4826
|
+
import { execSync as execSync23 } from "child_process";
|
|
4793
4827
|
function readCrontab() {
|
|
4794
4828
|
try {
|
|
4795
|
-
return
|
|
4829
|
+
return execSync23("crontab -l", {
|
|
4796
4830
|
encoding: "utf8",
|
|
4797
4831
|
stdio: ["ignore", "pipe", "ignore"]
|
|
4798
4832
|
});
|
|
@@ -4802,7 +4836,7 @@ function readCrontab() {
|
|
|
4802
4836
|
}
|
|
4803
4837
|
function writeCrontab(content) {
|
|
4804
4838
|
try {
|
|
4805
|
-
|
|
4839
|
+
execSync23("crontab -", {
|
|
4806
4840
|
input: content,
|
|
4807
4841
|
stdio: ["pipe", "ignore", "pipe"]
|
|
4808
4842
|
});
|
|
@@ -5143,7 +5177,7 @@ import chalk46 from "chalk";
|
|
|
5143
5177
|
import enquirer5 from "enquirer";
|
|
5144
5178
|
|
|
5145
5179
|
// src/shared/pullIfConfigured.ts
|
|
5146
|
-
import { execSync as
|
|
5180
|
+
import { execSync as execSync24 } from "child_process";
|
|
5147
5181
|
import chalk32 from "chalk";
|
|
5148
5182
|
function pullIfConfigured() {
|
|
5149
5183
|
const config = loadConfig();
|
|
@@ -5157,7 +5191,7 @@ function pullIfConfigured() {
|
|
|
5157
5191
|
return;
|
|
5158
5192
|
}
|
|
5159
5193
|
try {
|
|
5160
|
-
|
|
5194
|
+
execSync24("git pull --ff-only", { stdio: "inherit" });
|
|
5161
5195
|
} catch {
|
|
5162
5196
|
console.error(chalk32.red("git pull --ff-only failed; aborting."));
|
|
5163
5197
|
process.exit(1);
|
|
@@ -5165,7 +5199,7 @@ function pullIfConfigured() {
|
|
|
5165
5199
|
}
|
|
5166
5200
|
function hasLocalChanges() {
|
|
5167
5201
|
try {
|
|
5168
|
-
const status3 =
|
|
5202
|
+
const status3 = execSync24("git status --porcelain", {
|
|
5169
5203
|
encoding: "utf8"
|
|
5170
5204
|
});
|
|
5171
5205
|
return status3.trim().length > 0;
|
|
@@ -5432,7 +5466,7 @@ function buildArgs(prompt, options2) {
|
|
|
5432
5466
|
}
|
|
5433
5467
|
|
|
5434
5468
|
// src/commands/branch/createBranch.ts
|
|
5435
|
-
import { execSync as
|
|
5469
|
+
import { execSync as execSync26 } from "child_process";
|
|
5436
5470
|
|
|
5437
5471
|
// src/commands/branch/buildBranchName.ts
|
|
5438
5472
|
function buildBranchName({
|
|
@@ -5448,12 +5482,12 @@ function buildBranchName({
|
|
|
5448
5482
|
}
|
|
5449
5483
|
|
|
5450
5484
|
// src/commands/branch/resolveDefaultBranch.ts
|
|
5451
|
-
import { execSync as
|
|
5485
|
+
import { execSync as execSync25 } from "child_process";
|
|
5452
5486
|
var REMOTE_HEAD_REGEX = /^ref:\s+refs\/heads\/(\S+)\s+HEAD$/m;
|
|
5453
5487
|
function resolveDefaultBranch(override, cwd) {
|
|
5454
5488
|
if (override) return override;
|
|
5455
5489
|
try {
|
|
5456
|
-
const output =
|
|
5490
|
+
const output = execSync25("git ls-remote --symref origin HEAD", {
|
|
5457
5491
|
encoding: "utf8",
|
|
5458
5492
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5459
5493
|
cwd
|
|
@@ -5477,11 +5511,11 @@ async function createBranch({
|
|
|
5477
5511
|
jira,
|
|
5478
5512
|
slug
|
|
5479
5513
|
});
|
|
5480
|
-
|
|
5514
|
+
execSync26("git fetch", { stdio: "inherit" });
|
|
5481
5515
|
let baseRef;
|
|
5482
5516
|
if (from) {
|
|
5483
5517
|
try {
|
|
5484
|
-
|
|
5518
|
+
execSync26(`git rev-parse --verify ${shellQuote(from)}`, {
|
|
5485
5519
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5486
5520
|
});
|
|
5487
5521
|
} catch {
|
|
@@ -5491,7 +5525,7 @@ async function createBranch({
|
|
|
5491
5525
|
} else {
|
|
5492
5526
|
baseRef = `origin/${resolveDefaultBranch(config.branch?.defaultBranch)}`;
|
|
5493
5527
|
}
|
|
5494
|
-
|
|
5528
|
+
execSync26(`git switch -c ${shellQuote(branchName)} ${shellQuote(baseRef)}`, {
|
|
5495
5529
|
stdio: "inherit"
|
|
5496
5530
|
});
|
|
5497
5531
|
await recordBranchActivity(branchName);
|
|
@@ -5631,11 +5665,11 @@ function backupLocalBacklogFiles(dir) {
|
|
|
5631
5665
|
}
|
|
5632
5666
|
|
|
5633
5667
|
// src/commands/backlog/gitPullBacklog.ts
|
|
5634
|
-
import { execSync as
|
|
5668
|
+
import { execSync as execSync27 } from "child_process";
|
|
5635
5669
|
import chalk35 from "chalk";
|
|
5636
5670
|
function gitPullBacklog(dir) {
|
|
5637
5671
|
try {
|
|
5638
|
-
|
|
5672
|
+
execSync27("git pull --ff-only", {
|
|
5639
5673
|
cwd: dir,
|
|
5640
5674
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5641
5675
|
});
|
|
@@ -7925,7 +7959,7 @@ import chalk61 from "chalk";
|
|
|
7925
7959
|
import { WebSocketServer } from "ws";
|
|
7926
7960
|
|
|
7927
7961
|
// src/shared/getInstallDir.ts
|
|
7928
|
-
import { execSync as
|
|
7962
|
+
import { execSync as execSync28 } from "child_process";
|
|
7929
7963
|
import { dirname as dirname18, resolve as resolve7 } from "path";
|
|
7930
7964
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
7931
7965
|
var __filename2 = fileURLToPath3(import.meta.url);
|
|
@@ -7935,7 +7969,7 @@ function getInstallDir() {
|
|
|
7935
7969
|
}
|
|
7936
7970
|
function isGitRepo(dir) {
|
|
7937
7971
|
try {
|
|
7938
|
-
const result =
|
|
7972
|
+
const result = execSync28("git rev-parse --show-toplevel", {
|
|
7939
7973
|
cwd: dir,
|
|
7940
7974
|
stdio: "pipe"
|
|
7941
7975
|
}).toString().trim();
|
|
@@ -7952,11 +7986,11 @@ import {
|
|
|
7952
7986
|
import chalk57 from "chalk";
|
|
7953
7987
|
|
|
7954
7988
|
// src/lib/openBrowser.ts
|
|
7955
|
-
import { execSync as
|
|
7989
|
+
import { execSync as execSync29 } from "child_process";
|
|
7956
7990
|
function tryExec(commands) {
|
|
7957
7991
|
for (const cmd of commands) {
|
|
7958
7992
|
try {
|
|
7959
|
-
|
|
7993
|
+
execSync29(cmd, { stdio: "ignore" });
|
|
7960
7994
|
return true;
|
|
7961
7995
|
} catch {
|
|
7962
7996
|
}
|
|
@@ -8188,7 +8222,7 @@ function git2(cwd, args) {
|
|
|
8188
8222
|
});
|
|
8189
8223
|
});
|
|
8190
8224
|
}
|
|
8191
|
-
async function
|
|
8225
|
+
async function gitOrNull2(cwd, args) {
|
|
8192
8226
|
try {
|
|
8193
8227
|
return (await git2(cwd, args)).trim() || null;
|
|
8194
8228
|
} catch {
|
|
@@ -8847,6 +8881,61 @@ function getCwdParam(req, res) {
|
|
|
8847
8881
|
return cwd;
|
|
8848
8882
|
}
|
|
8849
8883
|
|
|
8884
|
+
// src/commands/sessions/web/windowsCwdToWslPath.ts
|
|
8885
|
+
function windowsCwdToWslPath(cwd) {
|
|
8886
|
+
const match = /^([A-Za-z]):[\\/](.*)$/.exec(cwd);
|
|
8887
|
+
if (!match) return cwd;
|
|
8888
|
+
const drive = match[1].toLowerCase();
|
|
8889
|
+
const rest = match[2].replace(/\\/g, "/");
|
|
8890
|
+
return `/mnt/${drive}/${rest}`;
|
|
8891
|
+
}
|
|
8892
|
+
|
|
8893
|
+
// src/commands/sessions/web/toGitCwd.ts
|
|
8894
|
+
function toGitCwd(cwd) {
|
|
8895
|
+
return detectPlatform() === "wsl" ? windowsCwdToWslPath(cwd) : cwd;
|
|
8896
|
+
}
|
|
8897
|
+
|
|
8898
|
+
// src/commands/sessions/web/resolveDiffBase.ts
|
|
8899
|
+
function baseCandidates(defaultBranch) {
|
|
8900
|
+
return [
|
|
8901
|
+
defaultBranch && `origin/${defaultBranch}`,
|
|
8902
|
+
defaultBranch,
|
|
8903
|
+
"origin/main",
|
|
8904
|
+
"origin/master",
|
|
8905
|
+
"main",
|
|
8906
|
+
"master"
|
|
8907
|
+
].filter((candidate) => Boolean(candidate));
|
|
8908
|
+
}
|
|
8909
|
+
async function refExists2(cwd, ref) {
|
|
8910
|
+
try {
|
|
8911
|
+
await execGit(cwd, ["rev-parse", "--verify", "--quiet", `${ref}^{commit}`]);
|
|
8912
|
+
return true;
|
|
8913
|
+
} catch {
|
|
8914
|
+
return false;
|
|
8915
|
+
}
|
|
8916
|
+
}
|
|
8917
|
+
async function resolveDiffBase(cwd) {
|
|
8918
|
+
let defaultBranch;
|
|
8919
|
+
try {
|
|
8920
|
+
const config = loadConfigFrom(toGitCwd(cwd));
|
|
8921
|
+
if (!config.sessions?.includeCommittedChanges) return "HEAD";
|
|
8922
|
+
defaultBranch = config.branch?.defaultBranch;
|
|
8923
|
+
} catch {
|
|
8924
|
+
return "HEAD";
|
|
8925
|
+
}
|
|
8926
|
+
for (const candidate of baseCandidates(defaultBranch)) {
|
|
8927
|
+
if (!await refExists2(cwd, candidate)) continue;
|
|
8928
|
+
try {
|
|
8929
|
+
const base = await execGit(cwd, ["merge-base", "HEAD", candidate]);
|
|
8930
|
+
const sha = base.trim();
|
|
8931
|
+
if (sha) return sha;
|
|
8932
|
+
} catch {
|
|
8933
|
+
}
|
|
8934
|
+
return "HEAD";
|
|
8935
|
+
}
|
|
8936
|
+
return "HEAD";
|
|
8937
|
+
}
|
|
8938
|
+
|
|
8850
8939
|
// src/commands/sessions/web/diff.ts
|
|
8851
8940
|
var MAX_DIFF_BYTES = 50 * 1024 * 1024;
|
|
8852
8941
|
async function untrackedFileDiff(cwd, path71) {
|
|
@@ -8871,7 +8960,8 @@ async function diff2(req, res) {
|
|
|
8871
8960
|
const cwd = getCwdParam(req, res);
|
|
8872
8961
|
if (!cwd) return;
|
|
8873
8962
|
try {
|
|
8874
|
-
const
|
|
8963
|
+
const base = await resolveDiffBase(cwd);
|
|
8964
|
+
const tracked = await execGit(cwd, ["diff", base], {
|
|
8875
8965
|
maxBuffer: MAX_DIFF_BYTES
|
|
8876
8966
|
});
|
|
8877
8967
|
const untracked = await untrackedDiff(cwd);
|
|
@@ -8886,22 +8976,6 @@ async function diff2(req, res) {
|
|
|
8886
8976
|
// src/commands/sessions/web/fileContent.ts
|
|
8887
8977
|
import { readFile, stat as stat2 } from "fs/promises";
|
|
8888
8978
|
import { isAbsolute, relative as relative2, resolve as resolve9 } from "path";
|
|
8889
|
-
|
|
8890
|
-
// src/commands/sessions/web/windowsCwdToWslPath.ts
|
|
8891
|
-
function windowsCwdToWslPath(cwd) {
|
|
8892
|
-
const match = /^([A-Za-z]):[\\/](.*)$/.exec(cwd);
|
|
8893
|
-
if (!match) return cwd;
|
|
8894
|
-
const drive = match[1].toLowerCase();
|
|
8895
|
-
const rest = match[2].replace(/\\/g, "/");
|
|
8896
|
-
return `/mnt/${drive}/${rest}`;
|
|
8897
|
-
}
|
|
8898
|
-
|
|
8899
|
-
// src/commands/sessions/web/toGitCwd.ts
|
|
8900
|
-
function toGitCwd(cwd) {
|
|
8901
|
-
return detectPlatform() === "wsl" ? windowsCwdToWslPath(cwd) : cwd;
|
|
8902
|
-
}
|
|
8903
|
-
|
|
8904
|
-
// src/commands/sessions/web/fileContent.ts
|
|
8905
8979
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
8906
8980
|
function resolveWithinCwd(cwd, path71) {
|
|
8907
8981
|
const root = resolve9(toGitCwd(cwd));
|
|
@@ -9098,13 +9172,44 @@ function githubUrl(req, res) {
|
|
|
9098
9172
|
});
|
|
9099
9173
|
}
|
|
9100
9174
|
|
|
9175
|
+
// src/commands/sessions/web/parseDiffNameStatus.ts
|
|
9176
|
+
function categorize(code) {
|
|
9177
|
+
switch (code) {
|
|
9178
|
+
case "A":
|
|
9179
|
+
case "C":
|
|
9180
|
+
return "new";
|
|
9181
|
+
case "D":
|
|
9182
|
+
return "deleted";
|
|
9183
|
+
case "M":
|
|
9184
|
+
case "R":
|
|
9185
|
+
case "T":
|
|
9186
|
+
case "U":
|
|
9187
|
+
return "modified";
|
|
9188
|
+
default:
|
|
9189
|
+
return null;
|
|
9190
|
+
}
|
|
9191
|
+
}
|
|
9192
|
+
function parseDiffNameStatus(output) {
|
|
9193
|
+
const result = { new: [], modified: [], deleted: [] };
|
|
9194
|
+
for (const line of output.split("\n")) {
|
|
9195
|
+
const fields = line.split(" ");
|
|
9196
|
+
const status3 = fields[0];
|
|
9197
|
+
if (!status3 || fields.length < 2) continue;
|
|
9198
|
+
const category = categorize(status3[0]);
|
|
9199
|
+
if (!category) continue;
|
|
9200
|
+
const path71 = fields[fields.length - 1];
|
|
9201
|
+
if (path71) result[category].push(path71);
|
|
9202
|
+
}
|
|
9203
|
+
return result;
|
|
9204
|
+
}
|
|
9205
|
+
|
|
9101
9206
|
// src/commands/sessions/web/parseGitStatus.ts
|
|
9102
9207
|
function extractPath(rest) {
|
|
9103
9208
|
const arrow = rest.indexOf(" -> ");
|
|
9104
9209
|
return arrow === -1 ? rest : rest.slice(arrow + 4);
|
|
9105
9210
|
}
|
|
9106
9211
|
var UNMERGED_STATES = /* @__PURE__ */ new Set(["DD", "AU", "UD", "UA", "DU", "AA", "UU"]);
|
|
9107
|
-
function
|
|
9212
|
+
function categorize2(xy) {
|
|
9108
9213
|
if (xy === "??") return "new";
|
|
9109
9214
|
if (UNMERGED_STATES.has(xy)) return "modified";
|
|
9110
9215
|
const codes = xy.replace(/ /g, "");
|
|
@@ -9119,23 +9224,45 @@ function parseGitStatus(output) {
|
|
|
9119
9224
|
const result = { new: [], modified: [], deleted: [] };
|
|
9120
9225
|
for (const line of output.split("\n")) {
|
|
9121
9226
|
if (line.length < 4) continue;
|
|
9122
|
-
const category =
|
|
9227
|
+
const category = categorize2(line.slice(0, 2));
|
|
9123
9228
|
if (category) result[category].push(extractPath(line.slice(3)));
|
|
9124
9229
|
}
|
|
9125
9230
|
return result;
|
|
9126
9231
|
}
|
|
9127
9232
|
|
|
9128
9233
|
// src/commands/sessions/web/gitStatus.ts
|
|
9234
|
+
async function untrackedPaths(cwd) {
|
|
9235
|
+
const list5 = await execGit(cwd, [
|
|
9236
|
+
"ls-files",
|
|
9237
|
+
"--others",
|
|
9238
|
+
"--exclude-standard"
|
|
9239
|
+
]);
|
|
9240
|
+
return list5.split("\n").filter(Boolean);
|
|
9241
|
+
}
|
|
9242
|
+
async function branchCounts(cwd, base) {
|
|
9243
|
+
const output = await execGit(cwd, ["diff", "--name-status", base]);
|
|
9244
|
+
const counts = parseDiffNameStatus(output);
|
|
9245
|
+
counts.new.push(...await untrackedPaths(cwd));
|
|
9246
|
+
return counts;
|
|
9247
|
+
}
|
|
9248
|
+
async function workingTreeCounts(cwd) {
|
|
9249
|
+
const output = await execGit(cwd, [
|
|
9250
|
+
"status",
|
|
9251
|
+
"--porcelain",
|
|
9252
|
+
"--untracked-files=all"
|
|
9253
|
+
]);
|
|
9254
|
+
return parseGitStatus(output);
|
|
9255
|
+
}
|
|
9129
9256
|
async function gitStatus(req, res) {
|
|
9130
9257
|
const cwd = getCwdParam(req, res);
|
|
9131
9258
|
if (!cwd) return;
|
|
9132
9259
|
try {
|
|
9133
|
-
const
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
|
|
9137
|
-
|
|
9138
|
-
|
|
9260
|
+
const base = await resolveDiffBase(cwd);
|
|
9261
|
+
respondJson(
|
|
9262
|
+
res,
|
|
9263
|
+
200,
|
|
9264
|
+
base === "HEAD" ? await workingTreeCounts(cwd) : await branchCounts(cwd, base)
|
|
9265
|
+
);
|
|
9139
9266
|
} catch {
|
|
9140
9267
|
respondJson(res, 200, { new: [], modified: [], deleted: [] });
|
|
9141
9268
|
}
|
|
@@ -9146,7 +9273,7 @@ import * as os3 from "os";
|
|
|
9146
9273
|
import * as path25 from "path";
|
|
9147
9274
|
|
|
9148
9275
|
// src/shared/checkCliAvailable.ts
|
|
9149
|
-
import { execSync as
|
|
9276
|
+
import { execSync as execSync30 } from "child_process";
|
|
9150
9277
|
function checkCliAvailable(cli) {
|
|
9151
9278
|
const binary = cli.split(/\s+/)[0];
|
|
9152
9279
|
const opts = {
|
|
@@ -9154,11 +9281,11 @@ function checkCliAvailable(cli) {
|
|
|
9154
9281
|
stdio: ["ignore", "pipe", "pipe"]
|
|
9155
9282
|
};
|
|
9156
9283
|
try {
|
|
9157
|
-
|
|
9284
|
+
execSync30(`command -v ${binary}`, opts);
|
|
9158
9285
|
return true;
|
|
9159
9286
|
} catch {
|
|
9160
9287
|
try {
|
|
9161
|
-
|
|
9288
|
+
execSync30(`where ${binary}`, opts);
|
|
9162
9289
|
return true;
|
|
9163
9290
|
} catch {
|
|
9164
9291
|
return false;
|
|
@@ -9249,8 +9376,8 @@ function subsequenceScore(text17, query) {
|
|
|
9249
9376
|
function scoreFilePath(path71, query) {
|
|
9250
9377
|
const needle = query.trim().toLowerCase();
|
|
9251
9378
|
if (!needle) return 0;
|
|
9252
|
-
const
|
|
9253
|
-
const inBasename = subsequenceScore(
|
|
9379
|
+
const basename19 = path71.slice(path71.lastIndexOf("/") + 1);
|
|
9380
|
+
const inBasename = subsequenceScore(basename19, needle);
|
|
9254
9381
|
if (inBasename !== null) return BASENAME_WEIGHT + inBasename;
|
|
9255
9382
|
return subsequenceScore(path71, needle);
|
|
9256
9383
|
}
|
|
@@ -10561,13 +10688,13 @@ async function beginAssociation(id, options2, clearPatch, label2) {
|
|
|
10561
10688
|
}
|
|
10562
10689
|
|
|
10563
10690
|
// src/commands/backlog/associate-github/fetchGithubIssueTitle.ts
|
|
10564
|
-
import { execSync as
|
|
10691
|
+
import { execSync as execSync31 } from "child_process";
|
|
10565
10692
|
function fetchGithubIssueTitle(issue) {
|
|
10566
10693
|
const match = /^([^/]+)\/([^#]+)#(\d+)$/.exec(issue);
|
|
10567
10694
|
if (!match) return void 0;
|
|
10568
10695
|
const [, owner, repo, number] = match;
|
|
10569
10696
|
try {
|
|
10570
|
-
const result =
|
|
10697
|
+
const result = execSync31(
|
|
10571
10698
|
`gh issue view ${number} -R ${owner}/${repo} --json title`,
|
|
10572
10699
|
{ encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }
|
|
10573
10700
|
);
|
|
@@ -10634,12 +10761,12 @@ import chalk66 from "chalk";
|
|
|
10634
10761
|
import { eq as eq19 } from "drizzle-orm";
|
|
10635
10762
|
|
|
10636
10763
|
// src/commands/jira/fetchIssue.ts
|
|
10637
|
-
import { execSync as
|
|
10764
|
+
import { execSync as execSync32 } from "child_process";
|
|
10638
10765
|
import chalk65 from "chalk";
|
|
10639
10766
|
function fetchIssue(issueKey, fields) {
|
|
10640
10767
|
let result;
|
|
10641
10768
|
try {
|
|
10642
|
-
result =
|
|
10769
|
+
result = execSync32(
|
|
10643
10770
|
`acli jira workitem view ${issueKey} -f ${fields} --json`,
|
|
10644
10771
|
{ encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }
|
|
10645
10772
|
);
|
|
@@ -14721,10 +14848,10 @@ function formatResultLine(entry, failing) {
|
|
|
14721
14848
|
}
|
|
14722
14849
|
|
|
14723
14850
|
// src/commands/complexity/maintainability/getMaintainabilityGitState.ts
|
|
14724
|
-
import { execSync as
|
|
14851
|
+
import { execSync as execSync33 } from "child_process";
|
|
14725
14852
|
import path28 from "path";
|
|
14726
14853
|
function git3(command) {
|
|
14727
|
-
return
|
|
14854
|
+
return execSync33(command, { encoding: "utf8" });
|
|
14728
14855
|
}
|
|
14729
14856
|
function toAbsolute(root, repoRelative) {
|
|
14730
14857
|
return path28.resolve(root, repoRelative);
|
|
@@ -15298,7 +15425,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
15298
15425
|
}
|
|
15299
15426
|
|
|
15300
15427
|
// src/commands/devlog/shared.ts
|
|
15301
|
-
import { execSync as
|
|
15428
|
+
import { execSync as execSync34 } from "child_process";
|
|
15302
15429
|
import chalk134 from "chalk";
|
|
15303
15430
|
|
|
15304
15431
|
// src/shared/getRepoName.ts
|
|
@@ -15390,7 +15517,7 @@ function loadAllDevlogLatestDates() {
|
|
|
15390
15517
|
// src/commands/devlog/shared.ts
|
|
15391
15518
|
function getCommitFiles(hash) {
|
|
15392
15519
|
try {
|
|
15393
|
-
const output =
|
|
15520
|
+
const output = execSync34(`git show --name-only --format="" ${hash}`, {
|
|
15394
15521
|
encoding: "utf8"
|
|
15395
15522
|
});
|
|
15396
15523
|
return output.trim().split("\n").filter(Boolean);
|
|
@@ -15486,11 +15613,11 @@ function list3(options2) {
|
|
|
15486
15613
|
}
|
|
15487
15614
|
|
|
15488
15615
|
// src/commands/devlog/getLastVersionInfo.ts
|
|
15489
|
-
import { execFileSync as execFileSync4, execSync as
|
|
15616
|
+
import { execFileSync as execFileSync4, execSync as execSync35 } from "child_process";
|
|
15490
15617
|
import semver from "semver";
|
|
15491
15618
|
function getVersionAtCommit(hash) {
|
|
15492
15619
|
try {
|
|
15493
|
-
const content =
|
|
15620
|
+
const content = execSync35(`git show ${hash}:package.json`, {
|
|
15494
15621
|
encoding: "utf8"
|
|
15495
15622
|
});
|
|
15496
15623
|
const pkg = JSON.parse(content);
|
|
@@ -15663,7 +15790,7 @@ function next2(options2) {
|
|
|
15663
15790
|
}
|
|
15664
15791
|
|
|
15665
15792
|
// src/commands/devlog/repos/index.ts
|
|
15666
|
-
import { execSync as
|
|
15793
|
+
import { execSync as execSync36 } from "child_process";
|
|
15667
15794
|
|
|
15668
15795
|
// src/commands/devlog/repos/printReposTable.ts
|
|
15669
15796
|
import chalk138 from "chalk";
|
|
@@ -15698,7 +15825,7 @@ function getStatus(lastPush, lastDevlog) {
|
|
|
15698
15825
|
return lastDevlog < lastPush ? "outdated" : "ok";
|
|
15699
15826
|
}
|
|
15700
15827
|
function fetchRepos(days, all) {
|
|
15701
|
-
const json =
|
|
15828
|
+
const json = execSync36(
|
|
15702
15829
|
"gh repo list staff0rd --json name,pushedAt,isArchived --limit 200",
|
|
15703
15830
|
{ encoding: "utf8" }
|
|
15704
15831
|
);
|
|
@@ -16078,7 +16205,7 @@ async function deps(csprojPath, options2) {
|
|
|
16078
16205
|
}
|
|
16079
16206
|
|
|
16080
16207
|
// src/commands/dotnet/getChangedCsFiles.ts
|
|
16081
|
-
import { execSync as
|
|
16208
|
+
import { execSync as execSync37 } from "child_process";
|
|
16082
16209
|
var SCOPE_ALL = "all";
|
|
16083
16210
|
var SCOPE_BASE = "base:";
|
|
16084
16211
|
var SCOPE_COMMIT = "commit:";
|
|
@@ -16102,7 +16229,7 @@ function getChangedCsFiles(scope) {
|
|
|
16102
16229
|
} else {
|
|
16103
16230
|
cmd = "git diff --name-only HEAD";
|
|
16104
16231
|
}
|
|
16105
|
-
const output =
|
|
16232
|
+
const output = execSync37(cmd, { encoding: "utf8" }).trim();
|
|
16106
16233
|
if (output === "") return [];
|
|
16107
16234
|
return output.split("\n").filter((f) => f.toLowerCase().endsWith(".cs"));
|
|
16108
16235
|
}
|
|
@@ -16300,14 +16427,14 @@ function parseInspectReport(json) {
|
|
|
16300
16427
|
}
|
|
16301
16428
|
|
|
16302
16429
|
// src/commands/dotnet/runInspectCode.ts
|
|
16303
|
-
import { execSync as
|
|
16430
|
+
import { execSync as execSync38 } from "child_process";
|
|
16304
16431
|
import { existsSync as existsSync40, readFileSync as readFileSync35, unlinkSync as unlinkSync10 } from "fs";
|
|
16305
16432
|
import { tmpdir as tmpdir4 } from "os";
|
|
16306
16433
|
import path35 from "path";
|
|
16307
16434
|
import chalk148 from "chalk";
|
|
16308
16435
|
function assertJbInstalled() {
|
|
16309
16436
|
try {
|
|
16310
|
-
|
|
16437
|
+
execSync38("jb inspectcode --version", { stdio: "pipe" });
|
|
16311
16438
|
} catch {
|
|
16312
16439
|
console.error(chalk148.red("jb is not installed. Install with:"));
|
|
16313
16440
|
console.error(
|
|
@@ -16321,7 +16448,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
16321
16448
|
const includeFlag = include ? ` --include="${include}"` : "";
|
|
16322
16449
|
const sweaFlag = swea ? " --swea" : "";
|
|
16323
16450
|
try {
|
|
16324
|
-
|
|
16451
|
+
execSync38(
|
|
16325
16452
|
`jb inspectcode "${slnPath}" -o="${reportPath}"${includeFlag}${sweaFlag} --verbosity=OFF`,
|
|
16326
16453
|
{ stdio: "pipe" }
|
|
16327
16454
|
);
|
|
@@ -16342,7 +16469,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
16342
16469
|
}
|
|
16343
16470
|
|
|
16344
16471
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
16345
|
-
import { execSync as
|
|
16472
|
+
import { execSync as execSync39 } from "child_process";
|
|
16346
16473
|
import chalk149 from "chalk";
|
|
16347
16474
|
function resolveMsbuildPath() {
|
|
16348
16475
|
const { run: run4 } = loadConfig();
|
|
@@ -16353,7 +16480,7 @@ function resolveMsbuildPath() {
|
|
|
16353
16480
|
function assertMsbuildInstalled() {
|
|
16354
16481
|
const msbuild = resolveMsbuildPath();
|
|
16355
16482
|
try {
|
|
16356
|
-
|
|
16483
|
+
execSync39(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
16357
16484
|
} catch {
|
|
16358
16485
|
console.error(chalk149.red(`msbuild not found at: ${msbuild}`));
|
|
16359
16486
|
console.error(
|
|
@@ -16379,7 +16506,7 @@ function runRoslynInspect(slnPath) {
|
|
|
16379
16506
|
const msbuild = resolveMsbuildPath();
|
|
16380
16507
|
let output;
|
|
16381
16508
|
try {
|
|
16382
|
-
output =
|
|
16509
|
+
output = execSync39(
|
|
16383
16510
|
`"${msbuild}" "${slnPath}" -t:Build -v:minimal -maxcpucount -p:EnforceCodeStyleInBuild=true -p:RunAnalyzersDuringBuild=true 2>&1`,
|
|
16384
16511
|
{ encoding: "utf8", stdio: "pipe", maxBuffer: 50 * 1024 * 1024 }
|
|
16385
16512
|
);
|
|
@@ -17226,7 +17353,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
17226
17353
|
}
|
|
17227
17354
|
|
|
17228
17355
|
// src/commands/jira/jiraAuth.ts
|
|
17229
|
-
import { execSync as
|
|
17356
|
+
import { execSync as execSync40 } from "child_process";
|
|
17230
17357
|
|
|
17231
17358
|
// src/shared/promptInput.ts
|
|
17232
17359
|
import Enquirer from "enquirer";
|
|
@@ -17261,7 +17388,7 @@ async function jiraAuth() {
|
|
|
17261
17388
|
console.error("All fields are required.");
|
|
17262
17389
|
process.exit(1);
|
|
17263
17390
|
}
|
|
17264
|
-
|
|
17391
|
+
execSync40(`acli jira auth login --site ${site} --email "${email}" --token`, {
|
|
17265
17392
|
encoding: "utf8",
|
|
17266
17393
|
input: token,
|
|
17267
17394
|
stdio: ["pipe", "inherit", "inherit"]
|
|
@@ -17352,71 +17479,434 @@ function registerRefineLaunch(program2, resumeFlag) {
|
|
|
17352
17479
|
}
|
|
17353
17480
|
|
|
17354
17481
|
// src/commands/reviewPrComments.ts
|
|
17355
|
-
import { execFileSync as execFileSync6 } from "child_process";
|
|
17356
17482
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
17483
|
+
|
|
17484
|
+
// src/commands/review/checkoutPr.ts
|
|
17485
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
17357
17486
|
import chalk155 from "chalk";
|
|
17358
|
-
|
|
17359
|
-
|
|
17360
|
-
|
|
17361
|
-
|
|
17362
|
-
|
|
17363
|
-
|
|
17364
|
-
|
|
17365
|
-
|
|
17487
|
+
|
|
17488
|
+
// src/commands/sessions/daemon/daemonLog.ts
|
|
17489
|
+
var RING_CAPACITY = 1e3;
|
|
17490
|
+
var ring = [];
|
|
17491
|
+
var sink;
|
|
17492
|
+
function daemonLog(message2) {
|
|
17493
|
+
emit3(`${(/* @__PURE__ */ new Date()).toISOString()} [${process.pid}] ${message2}`);
|
|
17494
|
+
}
|
|
17495
|
+
function relayDaemonLog(line) {
|
|
17496
|
+
emit3(`[windows] ${line}`);
|
|
17497
|
+
}
|
|
17498
|
+
function emit3(line) {
|
|
17499
|
+
console.log(line);
|
|
17500
|
+
ring.push(line);
|
|
17501
|
+
if (ring.length > RING_CAPACITY) ring.shift();
|
|
17502
|
+
sink?.(line);
|
|
17503
|
+
}
|
|
17504
|
+
function setDaemonLogSink(next3) {
|
|
17505
|
+
sink = next3;
|
|
17506
|
+
}
|
|
17507
|
+
function recentDaemonLogLines() {
|
|
17508
|
+
return [...ring];
|
|
17509
|
+
}
|
|
17510
|
+
|
|
17511
|
+
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
17512
|
+
import { existsSync as existsSync43 } from "fs";
|
|
17513
|
+
import { basename as basename12, dirname as dirname23 } from "path";
|
|
17514
|
+
|
|
17515
|
+
// src/commands/sessions/daemon/worktree/planAllocation.ts
|
|
17516
|
+
import { basename as basename11, join as join46 } from "path";
|
|
17517
|
+
function planAllocation(clone, boundTreeRoots2) {
|
|
17518
|
+
return boundTreeRoots2.has(clone) ? "spill" : "primary";
|
|
17519
|
+
}
|
|
17520
|
+
function nextWorktreePath(clone, base, isTaken) {
|
|
17521
|
+
const name = basename11(clone);
|
|
17522
|
+
for (let n = 2; n < 1e3; n++) {
|
|
17523
|
+
const candidate = join46(base, `${name}-${n}`);
|
|
17524
|
+
if (!isTaken(candidate)) return candidate;
|
|
17366
17525
|
}
|
|
17367
|
-
|
|
17368
|
-
emitActivity({
|
|
17369
|
-
kind: "command",
|
|
17370
|
-
name: "review-pr-comments",
|
|
17371
|
-
claudeSessionId
|
|
17372
|
-
});
|
|
17373
|
-
const { done: done2 } = spawnClaude("/review-pr-comments", {
|
|
17374
|
-
permissionMode: "acceptEdits",
|
|
17375
|
-
sessionId: claudeSessionId
|
|
17376
|
-
});
|
|
17377
|
-
await done2;
|
|
17526
|
+
throw new Error(`no free worktree suffix for ${clone}`);
|
|
17378
17527
|
}
|
|
17379
17528
|
|
|
17380
|
-
// src/commands/
|
|
17381
|
-
|
|
17382
|
-
|
|
17383
|
-
|
|
17384
|
-
|
|
17385
|
-
|
|
17529
|
+
// src/commands/sessions/daemon/worktree/worktreeStartPoint.ts
|
|
17530
|
+
function worktreeStartPoint(clone, trunk) {
|
|
17531
|
+
const branch2 = trunk ? cloneTrunkBranch(clone) : remoteDefaultBranch(clone);
|
|
17532
|
+
const ref = `origin/${branch2}`;
|
|
17533
|
+
if (gitSyncOrNull(clone, ["rev-parse", "--verify", "--quiet", ref]))
|
|
17534
|
+
return { ref, track: trunk };
|
|
17535
|
+
return { ref: "HEAD", track: false };
|
|
17386
17536
|
}
|
|
17387
|
-
function
|
|
17388
|
-
|
|
17389
|
-
"[description]",
|
|
17390
|
-
`Text to forward to the /${slashCommand} slash command`
|
|
17391
|
-
).description(description).option("--once", "Exit when the initial task completes").option("--resume-session <id>", RESUME_SESSION_FLAG).action(
|
|
17392
|
-
(text17, opts) => launchMode(slashCommand, {
|
|
17393
|
-
once: opts.once,
|
|
17394
|
-
description: text17,
|
|
17395
|
-
resumeSessionId: opts.resumeSession
|
|
17396
|
-
})
|
|
17397
|
-
);
|
|
17398
|
-
if (alias) command.alias(alias);
|
|
17537
|
+
function cloneTrunkBranch(clone) {
|
|
17538
|
+
return cloneHead(clone) ?? remoteDefaultBranch(clone);
|
|
17399
17539
|
}
|
|
17400
|
-
function
|
|
17401
|
-
|
|
17540
|
+
function remoteDefaultBranch(clone) {
|
|
17541
|
+
const head = gitSyncOrNull(clone, [
|
|
17542
|
+
"symbolic-ref",
|
|
17543
|
+
"--short",
|
|
17544
|
+
"refs/remotes/origin/HEAD"
|
|
17545
|
+
]);
|
|
17546
|
+
if (!head) return cloneHead(clone) ?? "main";
|
|
17547
|
+
const slash = head.indexOf("/");
|
|
17548
|
+
return slash === -1 ? head : head.slice(slash + 1);
|
|
17402
17549
|
}
|
|
17403
|
-
function
|
|
17404
|
-
|
|
17405
|
-
|
|
17406
|
-
|
|
17407
|
-
|
|
17408
|
-
|
|
17409
|
-
|
|
17410
|
-
|
|
17550
|
+
function cloneHead(clone) {
|
|
17551
|
+
return gitSyncOrNull(clone, ["symbolic-ref", "--short", "HEAD"]);
|
|
17552
|
+
}
|
|
17553
|
+
|
|
17554
|
+
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
17555
|
+
function createWorktree(clone, strategy, boundTreeRoots2) {
|
|
17556
|
+
const base = strategy.root ? expandTilde2(strategy.root) : dirname23(clone);
|
|
17557
|
+
const registered = new Set(listWorktreePaths(clone));
|
|
17558
|
+
const branches = new Set(listLocalBranches(clone));
|
|
17559
|
+
const path71 = nextWorktreePath(
|
|
17560
|
+
clone,
|
|
17561
|
+
base,
|
|
17562
|
+
(candidate) => registered.has(candidate) || existsSync43(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename12(candidate))
|
|
17411
17563
|
);
|
|
17412
|
-
|
|
17413
|
-
|
|
17414
|
-
"
|
|
17415
|
-
"
|
|
17416
|
-
|
|
17564
|
+
const start3 = worktreeStartPoint(clone, strategy.trunk);
|
|
17565
|
+
gitSync(clone, [
|
|
17566
|
+
"worktree",
|
|
17567
|
+
"add",
|
|
17568
|
+
start3.track ? "--track" : "--no-track",
|
|
17569
|
+
"-b",
|
|
17570
|
+
basename12(path71),
|
|
17571
|
+
path71,
|
|
17572
|
+
start3.ref
|
|
17573
|
+
]);
|
|
17574
|
+
recordWorktree(path71, clone, getCurrentOrigin(clone));
|
|
17575
|
+
daemonLog(
|
|
17576
|
+
start3.track ? `worktree allocated ${path71} (branch ${basename12(path71)} tracking ${start3.ref}) for clone ${clone}` : `worktree allocated ${path71} (branch ${basename12(path71)} off ${start3.ref}, no mainline tracking) for clone ${clone}`
|
|
17417
17577
|
);
|
|
17418
|
-
|
|
17419
|
-
|
|
17578
|
+
return path71;
|
|
17579
|
+
}
|
|
17580
|
+
|
|
17581
|
+
// src/commands/sessions/daemon/worktree/treeDurability.ts
|
|
17582
|
+
import { existsSync as existsSync44 } from "fs";
|
|
17583
|
+
function treeDurability(state) {
|
|
17584
|
+
if (state.dirty) return { durable: false, reason: "uncommitted changes" };
|
|
17585
|
+
if (state.localOnlyCommits)
|
|
17586
|
+
return { durable: false, reason: "unpushed commits" };
|
|
17587
|
+
return { durable: true };
|
|
17588
|
+
}
|
|
17589
|
+
function* durabilityProbes() {
|
|
17590
|
+
const status3 = yield ["status", "--porcelain"];
|
|
17591
|
+
if (!status3.ok)
|
|
17592
|
+
return { durable: false, reason: `tree state unreadable: ${status3.error}` };
|
|
17593
|
+
const upstream = yield [
|
|
17594
|
+
"rev-parse",
|
|
17595
|
+
"--abbrev-ref",
|
|
17596
|
+
"--symbolic-full-name",
|
|
17597
|
+
"@{upstream}"
|
|
17598
|
+
];
|
|
17599
|
+
let localOnlyCommits;
|
|
17600
|
+
if (upstream.ok && upstream.out) {
|
|
17601
|
+
const ahead = yield ["rev-list", "--count", "@{upstream}..HEAD"];
|
|
17602
|
+
localOnlyCommits = !ahead.ok || Number(ahead.out) > 0;
|
|
17603
|
+
} else {
|
|
17604
|
+
const remoteBranches = yield ["branch", "-r", "--contains", "HEAD"];
|
|
17605
|
+
localOnlyCommits = !remoteBranches.ok || remoteBranches.out === "";
|
|
17606
|
+
}
|
|
17607
|
+
return treeDurability({ dirty: status3.out !== "", localOnlyCommits });
|
|
17608
|
+
}
|
|
17609
|
+
async function checkDurability(cwd) {
|
|
17610
|
+
if (!existsSync44(cwd)) return { durable: true };
|
|
17611
|
+
const probes = durabilityProbes();
|
|
17612
|
+
let step = probes.next();
|
|
17613
|
+
while (!step.done) step = probes.next(await gitResult(cwd, step.value));
|
|
17614
|
+
return step.value;
|
|
17615
|
+
}
|
|
17616
|
+
function checkDurabilitySync(cwd) {
|
|
17617
|
+
if (!existsSync44(cwd)) return { durable: true };
|
|
17618
|
+
const probes = durabilityProbes();
|
|
17619
|
+
let step = probes.next();
|
|
17620
|
+
while (!step.done) step = probes.next(gitSyncResult(cwd, step.value));
|
|
17621
|
+
return step.value;
|
|
17622
|
+
}
|
|
17623
|
+
|
|
17624
|
+
// src/commands/sessions/daemon/worktree/worktreeConfigFor.ts
|
|
17625
|
+
var DISABLED = {
|
|
17626
|
+
enabled: false,
|
|
17627
|
+
trunk: false,
|
|
17628
|
+
install: true,
|
|
17629
|
+
commitBeforeManualChecks: false,
|
|
17630
|
+
copy: [".env", "settings.local.json", ".claude/settings.local.json"]
|
|
17631
|
+
};
|
|
17632
|
+
function worktreeConfigFor(cwd) {
|
|
17633
|
+
try {
|
|
17634
|
+
return loadConfigFrom(cwd).worktree ?? DISABLED;
|
|
17635
|
+
} catch {
|
|
17636
|
+
return DISABLED;
|
|
17637
|
+
}
|
|
17638
|
+
}
|
|
17639
|
+
|
|
17640
|
+
// src/commands/sessions/daemon/worktree/allocateTree.ts
|
|
17641
|
+
function allocateTree(requestedCwd, boundTreeRoots2, options2 = {}) {
|
|
17642
|
+
if (!requestedCwd)
|
|
17643
|
+
return { cwd: requestedCwd, kind: "primary", created: false };
|
|
17644
|
+
const repoRoot = findRepoRoot(requestedCwd) ?? requestedCwd;
|
|
17645
|
+
const cfg = worktreeConfigFor(repoRoot);
|
|
17646
|
+
if (!cfg.enabled)
|
|
17647
|
+
return { cwd: requestedCwd, kind: "primary", created: false };
|
|
17648
|
+
const clone = mainWorktree(repoRoot) ?? repoRoot;
|
|
17649
|
+
if (planAllocation(clone, boundTreeRoots2) === "primary" && !wouldDisturbWorkInProgress(clone, options2.forCheckout === true))
|
|
17650
|
+
return { cwd: clone, kind: "primary", created: false, clone };
|
|
17651
|
+
const path71 = createWorktree(
|
|
17652
|
+
clone,
|
|
17653
|
+
{ root: cfg.root, trunk: cfg.trunk },
|
|
17654
|
+
boundTreeRoots2
|
|
17655
|
+
);
|
|
17656
|
+
return { cwd: path71, kind: "worktree", created: true, clone };
|
|
17657
|
+
}
|
|
17658
|
+
function wouldDisturbWorkInProgress(clone, forCheckout) {
|
|
17659
|
+
if (!forCheckout) return false;
|
|
17660
|
+
const durability = checkDurabilitySync(clone);
|
|
17661
|
+
if (durability.durable) return false;
|
|
17662
|
+
daemonLog(
|
|
17663
|
+
`tree ${clone} not used for a PR checkout: ${durability.reason} \u2014 spilling to a worktree`
|
|
17664
|
+
);
|
|
17665
|
+
return true;
|
|
17666
|
+
}
|
|
17667
|
+
|
|
17668
|
+
// src/commands/sessions/daemon/persistedSessionSchema.ts
|
|
17669
|
+
import { z as z6 } from "zod";
|
|
17670
|
+
var persistedSessionSchema = z6.object({
|
|
17671
|
+
name: z6.string(),
|
|
17672
|
+
title: z6.string().optional(),
|
|
17673
|
+
subtitle: z6.string().optional(),
|
|
17674
|
+
commandType: z6.enum(["claude", "run", "assist"]),
|
|
17675
|
+
harness: z6.enum(["claude", "codex", "pi"]).optional(),
|
|
17676
|
+
status: z6.enum(["running", "waiting", "done", "error", "stopped"]).optional(),
|
|
17677
|
+
cwd: z6.string(),
|
|
17678
|
+
startedAt: z6.number(),
|
|
17679
|
+
runningMs: z6.number().optional(),
|
|
17680
|
+
claudeSessionId: z6.string().optional(),
|
|
17681
|
+
initialPrompt: z6.string().optional(),
|
|
17682
|
+
runName: z6.string().optional(),
|
|
17683
|
+
runArgs: z6.array(z6.string()).optional(),
|
|
17684
|
+
assistArgs: z6.array(z6.string()).optional(),
|
|
17685
|
+
activity: activitySchema.optional(),
|
|
17686
|
+
starred: z6.boolean().optional(),
|
|
17687
|
+
undurable: z6.object({ reason: z6.string(), removesTree: z6.boolean().optional() }).optional()
|
|
17688
|
+
});
|
|
17689
|
+
|
|
17690
|
+
// src/commands/sessions/daemon/toPersistedSession.ts
|
|
17691
|
+
function toPersistedSession(session) {
|
|
17692
|
+
return {
|
|
17693
|
+
name: session.name,
|
|
17694
|
+
title: session.title,
|
|
17695
|
+
subtitle: session.subtitle,
|
|
17696
|
+
commandType: session.commandType,
|
|
17697
|
+
harness: session.harness,
|
|
17698
|
+
status: session.status,
|
|
17699
|
+
cwd: session.cwd ?? process.cwd(),
|
|
17700
|
+
startedAt: session.startedAt,
|
|
17701
|
+
runningMs: accumulatedRunningMs(session),
|
|
17702
|
+
claudeSessionId: session.claudeSessionId,
|
|
17703
|
+
initialPrompt: session.initialPrompt,
|
|
17704
|
+
runName: session.runName,
|
|
17705
|
+
runArgs: session.runArgs,
|
|
17706
|
+
assistArgs: session.assistArgs,
|
|
17707
|
+
activity: session.activity,
|
|
17708
|
+
starred: session.starred,
|
|
17709
|
+
undurable: session.undurable
|
|
17710
|
+
};
|
|
17711
|
+
}
|
|
17712
|
+
function accumulatedRunningMs(session) {
|
|
17713
|
+
return session.runningSince != null ? session.runningMs + Date.now() - session.runningSince : session.runningMs;
|
|
17714
|
+
}
|
|
17715
|
+
|
|
17716
|
+
// src/commands/sessions/daemon/loadPersistedSessions.ts
|
|
17717
|
+
var SESSIONS_FILE = "sessions.json";
|
|
17718
|
+
function loadPersistedSessions() {
|
|
17719
|
+
const data = loadJson(SESSIONS_FILE);
|
|
17720
|
+
if (!Array.isArray(data)) return [];
|
|
17721
|
+
return data.flatMap((entry) => {
|
|
17722
|
+
const parsed = persistedSessionSchema.safeParse(entry);
|
|
17723
|
+
return parsed.success ? [parsed.data] : [];
|
|
17724
|
+
});
|
|
17725
|
+
}
|
|
17726
|
+
function savePersistedSessions(sessions) {
|
|
17727
|
+
saveJson(SESSIONS_FILE, sessions);
|
|
17728
|
+
}
|
|
17729
|
+
function persistLiveSessions(sessions) {
|
|
17730
|
+
const live = [...sessions.values()].filter(
|
|
17731
|
+
(s) => (s.pty || s.status === "stopped") && s.status !== "done"
|
|
17732
|
+
);
|
|
17733
|
+
savePersistedSessions(live.map(toPersistedSession));
|
|
17734
|
+
logPersist(live);
|
|
17735
|
+
}
|
|
17736
|
+
var lastPersistSignature = "";
|
|
17737
|
+
function logPersist(live) {
|
|
17738
|
+
const signature = live.map((s) => `${s.id}:${s.status}`).join(",");
|
|
17739
|
+
if (signature === lastPersistSignature) return;
|
|
17740
|
+
lastPersistSignature = signature;
|
|
17741
|
+
daemonLog(
|
|
17742
|
+
live.length > 0 ? `persisted ${live.length} session(s): ${live.map((s) => s.name).join(", ")}` : "persisted 0 sessions (sessions.json cleared)"
|
|
17743
|
+
);
|
|
17744
|
+
}
|
|
17745
|
+
|
|
17746
|
+
// src/commands/sessions/daemon/worktree/persistedTreeRoots.ts
|
|
17747
|
+
function persistedTreeRoots() {
|
|
17748
|
+
const roots = /* @__PURE__ */ new Set();
|
|
17749
|
+
for (const { cwd } of loadPersistedSessions()) {
|
|
17750
|
+
if (cwd) roots.add(findRepoRoot(cwd) ?? cwd);
|
|
17751
|
+
}
|
|
17752
|
+
return roots;
|
|
17753
|
+
}
|
|
17754
|
+
|
|
17755
|
+
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
17756
|
+
import { execFile as execFile8 } from "child_process";
|
|
17757
|
+
import { copyFileSync, existsSync as existsSync46, mkdirSync as mkdirSync16 } from "fs";
|
|
17758
|
+
import { dirname as dirname24, join as join48 } from "path";
|
|
17759
|
+
|
|
17760
|
+
// src/commands/sessions/daemon/worktree/resolveInstallCommand.ts
|
|
17761
|
+
import { existsSync as existsSync45 } from "fs";
|
|
17762
|
+
import { join as join47 } from "path";
|
|
17763
|
+
function detectInstallCommand(repoRoot) {
|
|
17764
|
+
if (!existsSync45(join47(repoRoot, "package.json"))) return null;
|
|
17765
|
+
if (existsSync45(join47(repoRoot, "pnpm-lock.yaml"))) return "pnpm install";
|
|
17766
|
+
if (existsSync45(join47(repoRoot, "yarn.lock"))) return "yarn install";
|
|
17767
|
+
if (existsSync45(join47(repoRoot, "bun.lockb"))) return "bun install";
|
|
17768
|
+
return "npm install";
|
|
17769
|
+
}
|
|
17770
|
+
function resolveInstallCommand(repoRoot, install) {
|
|
17771
|
+
if (install === false) return null;
|
|
17772
|
+
if (typeof install === "string") return install;
|
|
17773
|
+
return detectInstallCommand(repoRoot);
|
|
17774
|
+
}
|
|
17775
|
+
|
|
17776
|
+
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
17777
|
+
function seedWorktree(worktreePath, clone, onSeeded = () => {
|
|
17778
|
+
}) {
|
|
17779
|
+
const cfg = worktreeConfigFor(clone);
|
|
17780
|
+
copyConfigFiles(worktreePath, clone, cfg.copy);
|
|
17781
|
+
runInstall(worktreePath, clone, cfg.install, onSeeded);
|
|
17782
|
+
}
|
|
17783
|
+
function copyConfigFiles(worktreePath, clone, copy) {
|
|
17784
|
+
for (const rel of copy) {
|
|
17785
|
+
const src = join48(clone, rel);
|
|
17786
|
+
if (!existsSync46(src)) continue;
|
|
17787
|
+
const dest = join48(worktreePath, rel);
|
|
17788
|
+
try {
|
|
17789
|
+
mkdirSync16(dirname24(dest), { recursive: true });
|
|
17790
|
+
copyFileSync(src, dest);
|
|
17791
|
+
daemonLog(`worktree ${worktreePath} seeded ${rel}`);
|
|
17792
|
+
} catch (error) {
|
|
17793
|
+
daemonLog(
|
|
17794
|
+
`worktree ${worktreePath} failed to seed ${rel}: ${message(error)}`
|
|
17795
|
+
);
|
|
17796
|
+
}
|
|
17797
|
+
}
|
|
17798
|
+
}
|
|
17799
|
+
function runInstall(worktreePath, clone, install, onSeeded) {
|
|
17800
|
+
const command = resolveInstallCommand(clone, install);
|
|
17801
|
+
if (!command) {
|
|
17802
|
+
onSeeded();
|
|
17803
|
+
return;
|
|
17804
|
+
}
|
|
17805
|
+
const windows = /^[A-Za-z]:[\\/]/.test(worktreePath);
|
|
17806
|
+
const shell = windows ? "cmd.exe" : process.env.SHELL ?? "bash";
|
|
17807
|
+
const shellArgs = windows ? ["/c", command] : ["-l", "-c", command];
|
|
17808
|
+
daemonLog(`worktree ${worktreePath} installing deps: ${command}`);
|
|
17809
|
+
execFile8(shell, shellArgs, { cwd: worktreePath }, (error) => {
|
|
17810
|
+
daemonLog(
|
|
17811
|
+
error ? `worktree ${worktreePath} install failed: ${error.message}` : `worktree ${worktreePath} install complete`
|
|
17812
|
+
);
|
|
17813
|
+
onSeeded();
|
|
17814
|
+
});
|
|
17815
|
+
}
|
|
17816
|
+
function message(error) {
|
|
17817
|
+
return error instanceof Error ? error.message : String(error);
|
|
17818
|
+
}
|
|
17819
|
+
|
|
17820
|
+
// src/commands/review/moveToPrCheckoutTree.ts
|
|
17821
|
+
function placedByDaemon() {
|
|
17822
|
+
return process.env.ASSIST_SESSION === "1";
|
|
17823
|
+
}
|
|
17824
|
+
function seed(worktreePath, clone) {
|
|
17825
|
+
console.log(`Preparing ${worktreePath}\u2026`);
|
|
17826
|
+
return new Promise(
|
|
17827
|
+
(resolve20) => seedWorktree(worktreePath, clone, resolve20)
|
|
17828
|
+
);
|
|
17829
|
+
}
|
|
17830
|
+
async function moveToPrCheckoutTree() {
|
|
17831
|
+
if (placedByDaemon()) return;
|
|
17832
|
+
const from = process.cwd();
|
|
17833
|
+
const alloc = allocateTree(from, persistedTreeRoots(), {
|
|
17834
|
+
forCheckout: true
|
|
17835
|
+
});
|
|
17836
|
+
if (!alloc.cwd || alloc.cwd === from) return;
|
|
17837
|
+
process.chdir(alloc.cwd);
|
|
17838
|
+
console.log(`Checking the PR out in ${alloc.cwd}`);
|
|
17839
|
+
appendDaemonLog(`pr checkout placed in ${alloc.cwd} (invoked from ${from})`);
|
|
17840
|
+
if (alloc.created && alloc.clone) await seed(alloc.cwd, alloc.clone);
|
|
17841
|
+
}
|
|
17842
|
+
|
|
17843
|
+
// src/commands/review/checkoutPr.ts
|
|
17844
|
+
async function checkoutPr(number) {
|
|
17845
|
+
await moveToPrCheckoutTree();
|
|
17846
|
+
try {
|
|
17847
|
+
execFileSync6("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
17848
|
+
} catch {
|
|
17849
|
+
console.error(chalk155.red(`gh pr checkout ${number} failed; aborting.`));
|
|
17850
|
+
process.exit(1);
|
|
17851
|
+
}
|
|
17852
|
+
}
|
|
17853
|
+
|
|
17854
|
+
// src/commands/reviewPrComments.ts
|
|
17855
|
+
async function reviewPrComments(number) {
|
|
17856
|
+
if (number) await checkoutPr(number);
|
|
17857
|
+
const claudeSessionId = randomUUID4();
|
|
17858
|
+
emitActivity({
|
|
17859
|
+
kind: "command",
|
|
17860
|
+
name: "review-pr-comments",
|
|
17861
|
+
claudeSessionId
|
|
17862
|
+
});
|
|
17863
|
+
const { done: done2 } = spawnClaude("/review-pr-comments", {
|
|
17864
|
+
permissionMode: "acceptEdits",
|
|
17865
|
+
sessionId: claudeSessionId
|
|
17866
|
+
});
|
|
17867
|
+
await done2;
|
|
17868
|
+
}
|
|
17869
|
+
|
|
17870
|
+
// src/commands/registerLaunch.ts
|
|
17871
|
+
var RESUME_SESSION_FLAG = "Resume an interrupted Claude session (used by the sessions daemon on restart)";
|
|
17872
|
+
function registerNext(program2) {
|
|
17873
|
+
program2.command("next").argument("[id]", "Backlog item ID to run first").description("Alias for backlog next").option("--once", "Exit after the first completed item run").action(
|
|
17874
|
+
(id, opts) => next({ allowEdits: true, once: opts.once }, id)
|
|
17875
|
+
);
|
|
17876
|
+
}
|
|
17877
|
+
function registerDescriptionLaunch(program2, name, slashCommand, description, alias) {
|
|
17878
|
+
const command = program2.command(name).argument(
|
|
17879
|
+
"[description]",
|
|
17880
|
+
`Text to forward to the /${slashCommand} slash command`
|
|
17881
|
+
).description(description).option("--once", "Exit when the initial task completes").option("--resume-session <id>", RESUME_SESSION_FLAG).action(
|
|
17882
|
+
(text17, opts) => launchMode(slashCommand, {
|
|
17883
|
+
once: opts.once,
|
|
17884
|
+
description: text17,
|
|
17885
|
+
resumeSessionId: opts.resumeSession
|
|
17886
|
+
})
|
|
17887
|
+
);
|
|
17888
|
+
if (alias) command.alias(alias);
|
|
17889
|
+
}
|
|
17890
|
+
function registerReviewPrComments(program2) {
|
|
17891
|
+
program2.command("review-pr-comments").argument("[number]", "PR number to check out first").description("Launch Claude in /review-pr-comments mode (single session)").action((number) => reviewPrComments(number));
|
|
17892
|
+
}
|
|
17893
|
+
function registerLaunch(program2) {
|
|
17894
|
+
registerNext(program2);
|
|
17895
|
+
registerDescriptionLaunch(
|
|
17896
|
+
program2,
|
|
17897
|
+
"draft",
|
|
17898
|
+
"draft",
|
|
17899
|
+
"Launch Claude in /draft mode, chain into next on /next signal",
|
|
17900
|
+
"feat"
|
|
17901
|
+
);
|
|
17902
|
+
registerDescriptionLaunch(
|
|
17903
|
+
program2,
|
|
17904
|
+
"bug",
|
|
17905
|
+
"bug",
|
|
17906
|
+
"Launch Claude in /bug mode, chain into next on /next signal"
|
|
17907
|
+
);
|
|
17908
|
+
registerReviewPrComments(program2);
|
|
17909
|
+
registerRefineLaunch(program2, RESUME_SESSION_FLAG);
|
|
17420
17910
|
}
|
|
17421
17911
|
|
|
17422
17912
|
// src/commands/registerList.ts
|
|
@@ -17431,13 +17921,13 @@ function registerList(program2) {
|
|
|
17431
17921
|
}
|
|
17432
17922
|
|
|
17433
17923
|
// src/commands/mermaid/index.ts
|
|
17434
|
-
import { mkdirSync as
|
|
17924
|
+
import { mkdirSync as mkdirSync17, readdirSync as readdirSync9 } from "fs";
|
|
17435
17925
|
import { resolve as resolve13 } from "path";
|
|
17436
17926
|
import chalk158 from "chalk";
|
|
17437
17927
|
|
|
17438
17928
|
// src/commands/mermaid/exportFile.ts
|
|
17439
17929
|
import { readFileSync as readFileSync37, writeFileSync as writeFileSync31 } from "fs";
|
|
17440
|
-
import { basename as
|
|
17930
|
+
import { basename as basename13, extname as extname2, resolve as resolve12 } from "path";
|
|
17441
17931
|
import chalk157 from "chalk";
|
|
17442
17932
|
|
|
17443
17933
|
// src/commands/mermaid/renderBlock.ts
|
|
@@ -17464,7 +17954,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
17464
17954
|
async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
17465
17955
|
const content = readFileSync37(file, "utf8");
|
|
17466
17956
|
const blocks = extractMermaidBlocks(content);
|
|
17467
|
-
const stem =
|
|
17957
|
+
const stem = basename13(file, extname2(file));
|
|
17468
17958
|
if (onlyIndex !== void 0) {
|
|
17469
17959
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
17470
17960
|
console.error(
|
|
@@ -17500,7 +17990,7 @@ function extractMermaidBlocks(markdown) {
|
|
|
17500
17990
|
async function mermaidExport(file, options2 = {}) {
|
|
17501
17991
|
const { mermaid } = loadConfig();
|
|
17502
17992
|
const outDir = resolve13(process.cwd(), options2.out ?? ".");
|
|
17503
|
-
|
|
17993
|
+
mkdirSync17(outDir, { recursive: true });
|
|
17504
17994
|
if (options2.index !== void 0) {
|
|
17505
17995
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
17506
17996
|
console.error(
|
|
@@ -17547,7 +18037,7 @@ function registerMermaid(program2) {
|
|
|
17547
18037
|
// src/commands/netcap/netcap.ts
|
|
17548
18038
|
import { mkdir as mkdir4 } from "fs/promises";
|
|
17549
18039
|
import { createServer as createServer2 } from "http";
|
|
17550
|
-
import { dirname as
|
|
18040
|
+
import { dirname as dirname26 } from "path";
|
|
17551
18041
|
import chalk160 from "chalk";
|
|
17552
18042
|
|
|
17553
18043
|
// src/commands/netcap/corsHeaders.ts
|
|
@@ -17626,15 +18116,15 @@ function createNetcapHandler(options2) {
|
|
|
17626
18116
|
// src/commands/netcap/prepareExtensionForLoad.ts
|
|
17627
18117
|
import { cp, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
17628
18118
|
import { networkInterfaces } from "os";
|
|
17629
|
-
import { join as
|
|
18119
|
+
import { join as join50 } from "path";
|
|
17630
18120
|
import chalk159 from "chalk";
|
|
17631
18121
|
|
|
17632
18122
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
17633
|
-
import { dirname as
|
|
18123
|
+
import { dirname as dirname25, join as join49 } from "path";
|
|
17634
18124
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
17635
|
-
var moduleDir =
|
|
18125
|
+
var moduleDir = dirname25(fileURLToPath6(import.meta.url));
|
|
17636
18126
|
function netcapExtensionDir() {
|
|
17637
|
-
return
|
|
18127
|
+
return join49(moduleDir, "commands", "netcap", "netcap-extension");
|
|
17638
18128
|
}
|
|
17639
18129
|
|
|
17640
18130
|
// src/commands/netcap/prepareExtensionForLoad.ts
|
|
@@ -17649,7 +18139,7 @@ function lanIPv4() {
|
|
|
17649
18139
|
return void 0;
|
|
17650
18140
|
}
|
|
17651
18141
|
async function configureBackground(dir, host, port, filter) {
|
|
17652
|
-
const file =
|
|
18142
|
+
const file = join50(dir, "background.js");
|
|
17653
18143
|
const source = await readFile3(file, "utf8");
|
|
17654
18144
|
await writeFile3(
|
|
17655
18145
|
file,
|
|
@@ -17689,20 +18179,20 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
17689
18179
|
}
|
|
17690
18180
|
|
|
17691
18181
|
// src/commands/netcap/resolveNetcapOutPath.ts
|
|
17692
|
-
import { isAbsolute as isAbsolute2, join as
|
|
18182
|
+
import { isAbsolute as isAbsolute2, join as join52, resolve as resolve14 } from "path";
|
|
17693
18183
|
|
|
17694
18184
|
// src/commands/netcap/defaultCapturePath.ts
|
|
17695
18185
|
import { homedir as homedir19 } from "os";
|
|
17696
|
-
import { join as
|
|
18186
|
+
import { join as join51 } from "path";
|
|
17697
18187
|
function defaultCapturePath() {
|
|
17698
|
-
return
|
|
18188
|
+
return join51(homedir19(), ".assist", "netcap", "capture.jsonl");
|
|
17699
18189
|
}
|
|
17700
18190
|
|
|
17701
18191
|
// src/commands/netcap/resolveNetcapOutPath.ts
|
|
17702
18192
|
function resolveNetcapOutPath(out) {
|
|
17703
18193
|
if (!out) return defaultCapturePath();
|
|
17704
18194
|
const dir = isAbsolute2(out) ? out : resolve14(process.cwd(), out);
|
|
17705
|
-
return
|
|
18195
|
+
return join52(dir, "capture.jsonl");
|
|
17706
18196
|
}
|
|
17707
18197
|
|
|
17708
18198
|
// src/commands/netcap/netcap.ts
|
|
@@ -17710,7 +18200,7 @@ async function netcap(options2) {
|
|
|
17710
18200
|
const port = Number(options2.port);
|
|
17711
18201
|
const outPath = resolveNetcapOutPath(options2.out);
|
|
17712
18202
|
const filter = options2.filter ?? "";
|
|
17713
|
-
await mkdir4(
|
|
18203
|
+
await mkdir4(dirname26(outPath), { recursive: true });
|
|
17714
18204
|
const extensionPath = await prepareExtensionForLoad(port, filter);
|
|
17715
18205
|
let count7 = 0;
|
|
17716
18206
|
const handler = createNetcapHandler({
|
|
@@ -17749,7 +18239,7 @@ netcap stopped \u2014 captured ${count7} ${count7 === 1 ? "entry" : "entries"} t
|
|
|
17749
18239
|
|
|
17750
18240
|
// src/commands/netcap/netcapExtract.ts
|
|
17751
18241
|
import { writeFileSync as writeFileSync32 } from "fs";
|
|
17752
|
-
import { join as
|
|
18242
|
+
import { join as join53 } from "path";
|
|
17753
18243
|
import chalk161 from "chalk";
|
|
17754
18244
|
|
|
17755
18245
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
@@ -18194,7 +18684,7 @@ function extractPostsFromCapture(captureFile) {
|
|
|
18194
18684
|
function netcapExtract(file) {
|
|
18195
18685
|
const captureFile = file ?? defaultCapturePath();
|
|
18196
18686
|
const posts = extractPostsFromCapture(captureFile);
|
|
18197
|
-
const outFile =
|
|
18687
|
+
const outFile = join53(captureFile, "..", "posts.json");
|
|
18198
18688
|
writeFileSync32(outFile, `${JSON.stringify(posts, null, 2)}
|
|
18199
18689
|
`);
|
|
18200
18690
|
console.log(
|
|
@@ -18346,7 +18836,7 @@ function registerPrompts(program2) {
|
|
|
18346
18836
|
}
|
|
18347
18837
|
|
|
18348
18838
|
// src/commands/prs/shared.ts
|
|
18349
|
-
import { execSync as
|
|
18839
|
+
import { execSync as execSync41 } from "child_process";
|
|
18350
18840
|
function isGhNotInstalled(error) {
|
|
18351
18841
|
if (error instanceof Error) {
|
|
18352
18842
|
const msg = error.message.toLowerCase();
|
|
@@ -18364,12 +18854,12 @@ function getRepoInfo() {
|
|
|
18364
18854
|
const preferred = getPreferredRemoteRepo();
|
|
18365
18855
|
if (preferred) return preferred;
|
|
18366
18856
|
const repoInfo = JSON.parse(
|
|
18367
|
-
|
|
18857
|
+
execSync41("gh repo view --json owner,name", { encoding: "utf8" })
|
|
18368
18858
|
);
|
|
18369
18859
|
return { org: repoInfo.owner.login, repo: repoInfo.name };
|
|
18370
18860
|
}
|
|
18371
18861
|
function getCurrentBranch2() {
|
|
18372
|
-
return
|
|
18862
|
+
return execSync41("git rev-parse --abbrev-ref HEAD", {
|
|
18373
18863
|
encoding: "utf8"
|
|
18374
18864
|
}).trim();
|
|
18375
18865
|
}
|
|
@@ -18377,7 +18867,7 @@ function viewCurrentPr(fields) {
|
|
|
18377
18867
|
const { org, repo } = getRepoInfo();
|
|
18378
18868
|
const branch2 = getCurrentBranch2();
|
|
18379
18869
|
return JSON.parse(
|
|
18380
|
-
|
|
18870
|
+
execSync41(`gh pr view ${branch2} --json ${fields} -R ${org}/${repo}`, {
|
|
18381
18871
|
encoding: "utf8"
|
|
18382
18872
|
})
|
|
18383
18873
|
);
|
|
@@ -18679,24 +19169,24 @@ function edit(options2) {
|
|
|
18679
19169
|
}
|
|
18680
19170
|
|
|
18681
19171
|
// src/commands/prs/fixed.ts
|
|
18682
|
-
import { execSync as
|
|
19172
|
+
import { execSync as execSync44 } from "child_process";
|
|
18683
19173
|
|
|
18684
19174
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
18685
|
-
import { execSync as
|
|
19175
|
+
import { execSync as execSync43 } from "child_process";
|
|
18686
19176
|
import { unlinkSync as unlinkSync14, writeFileSync as writeFileSync33 } from "fs";
|
|
18687
19177
|
import { tmpdir as tmpdir6 } from "os";
|
|
18688
|
-
import { join as
|
|
19178
|
+
import { join as join55 } from "path";
|
|
18689
19179
|
|
|
18690
19180
|
// src/commands/prs/loadCommentsCache.ts
|
|
18691
|
-
import { existsSync as
|
|
18692
|
-
import { join as
|
|
19181
|
+
import { existsSync as existsSync47, readFileSync as readFileSync39, unlinkSync as unlinkSync13 } from "fs";
|
|
19182
|
+
import { join as join54 } from "path";
|
|
18693
19183
|
import { parse as parse2 } from "yaml";
|
|
18694
19184
|
function getCachePath(prNumber) {
|
|
18695
|
-
return
|
|
19185
|
+
return join54(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
18696
19186
|
}
|
|
18697
19187
|
function loadCommentsCache(prNumber) {
|
|
18698
19188
|
const cachePath = getCachePath(prNumber);
|
|
18699
|
-
if (!
|
|
19189
|
+
if (!existsSync47(cachePath)) {
|
|
18700
19190
|
return null;
|
|
18701
19191
|
}
|
|
18702
19192
|
const content = readFileSync39(cachePath, "utf8");
|
|
@@ -18704,16 +19194,16 @@ function loadCommentsCache(prNumber) {
|
|
|
18704
19194
|
}
|
|
18705
19195
|
function deleteCommentsCache(prNumber) {
|
|
18706
19196
|
const cachePath = getCachePath(prNumber);
|
|
18707
|
-
if (
|
|
19197
|
+
if (existsSync47(cachePath)) {
|
|
18708
19198
|
unlinkSync13(cachePath);
|
|
18709
19199
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
18710
19200
|
}
|
|
18711
19201
|
}
|
|
18712
19202
|
|
|
18713
19203
|
// src/commands/prs/replyToComment.ts
|
|
18714
|
-
import { execSync as
|
|
19204
|
+
import { execSync as execSync42 } from "child_process";
|
|
18715
19205
|
function replyToComment(org, repo, prNumber, commentId, message2) {
|
|
18716
|
-
|
|
19206
|
+
execSync42(
|
|
18717
19207
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message2.replace(/"/g, String.raw`\"`)}" -F in_reply_to=${commentId}`,
|
|
18718
19208
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
18719
19209
|
);
|
|
@@ -18722,10 +19212,10 @@ function replyToComment(org, repo, prNumber, commentId, message2) {
|
|
|
18722
19212
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
18723
19213
|
function resolveThread(threadId) {
|
|
18724
19214
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
18725
|
-
const queryFile =
|
|
19215
|
+
const queryFile = join55(tmpdir6(), `gh-mutation-${Date.now()}.graphql`);
|
|
18726
19216
|
writeFileSync33(queryFile, mutation);
|
|
18727
19217
|
try {
|
|
18728
|
-
|
|
19218
|
+
execSync43(
|
|
18729
19219
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
18730
19220
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
18731
19221
|
);
|
|
@@ -18777,7 +19267,7 @@ function resolveCommentWithReply(commentId, message2) {
|
|
|
18777
19267
|
// src/commands/prs/fixed.ts
|
|
18778
19268
|
function verifySha(sha) {
|
|
18779
19269
|
try {
|
|
18780
|
-
return
|
|
19270
|
+
return execSync44(`git rev-parse --verify ${sha}`, {
|
|
18781
19271
|
encoding: "utf8"
|
|
18782
19272
|
}).trim();
|
|
18783
19273
|
} catch {
|
|
@@ -18791,7 +19281,7 @@ function fixed(commentId, sha) {
|
|
|
18791
19281
|
const { org, repo } = getRepoInfo();
|
|
18792
19282
|
const repoUrl = `https://github.com/${org}/${repo}`;
|
|
18793
19283
|
const message2 = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
|
|
18794
|
-
|
|
19284
|
+
pushCommit();
|
|
18795
19285
|
resolveCommentWithReply(commentId, message2);
|
|
18796
19286
|
} catch (error) {
|
|
18797
19287
|
if (isGhNotInstalled(error)) {
|
|
@@ -18804,21 +19294,21 @@ function fixed(commentId, sha) {
|
|
|
18804
19294
|
}
|
|
18805
19295
|
|
|
18806
19296
|
// src/commands/prs/listComments/index.ts
|
|
18807
|
-
import { existsSync as
|
|
18808
|
-
import { join as
|
|
19297
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync18, writeFileSync as writeFileSync35 } from "fs";
|
|
19298
|
+
import { join as join57 } from "path";
|
|
18809
19299
|
import { stringify } from "yaml";
|
|
18810
19300
|
|
|
18811
19301
|
// src/commands/prs/fetchThreadIds.ts
|
|
18812
|
-
import { execSync as
|
|
19302
|
+
import { execSync as execSync45 } from "child_process";
|
|
18813
19303
|
import { unlinkSync as unlinkSync15, writeFileSync as writeFileSync34 } from "fs";
|
|
18814
19304
|
import { tmpdir as tmpdir7 } from "os";
|
|
18815
|
-
import { join as
|
|
19305
|
+
import { join as join56 } from "path";
|
|
18816
19306
|
var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
|
|
18817
19307
|
function fetchThreadIds(org, repo, prNumber) {
|
|
18818
|
-
const queryFile =
|
|
19308
|
+
const queryFile = join56(tmpdir7(), `gh-query-${Date.now()}.graphql`);
|
|
18819
19309
|
writeFileSync34(queryFile, THREAD_QUERY);
|
|
18820
19310
|
try {
|
|
18821
|
-
const result =
|
|
19311
|
+
const result = execSync45(
|
|
18822
19312
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
18823
19313
|
{ encoding: "utf8" }
|
|
18824
19314
|
);
|
|
@@ -18840,9 +19330,9 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
18840
19330
|
}
|
|
18841
19331
|
|
|
18842
19332
|
// src/commands/prs/listComments/fetchReviewComments.ts
|
|
18843
|
-
import { execSync as
|
|
19333
|
+
import { execSync as execSync46 } from "child_process";
|
|
18844
19334
|
function fetchJson(endpoint) {
|
|
18845
|
-
const result =
|
|
19335
|
+
const result = execSync46(`gh api --paginate ${endpoint}`, {
|
|
18846
19336
|
encoding: "utf8"
|
|
18847
19337
|
});
|
|
18848
19338
|
if (!result.trim()) return [];
|
|
@@ -18929,16 +19419,16 @@ function printComments2(result) {
|
|
|
18929
19419
|
|
|
18930
19420
|
// src/commands/prs/listComments/index.ts
|
|
18931
19421
|
function writeCommentsCache(prNumber, comments3) {
|
|
18932
|
-
const assistDir =
|
|
18933
|
-
if (!
|
|
18934
|
-
|
|
19422
|
+
const assistDir = join57(process.cwd(), ".assist");
|
|
19423
|
+
if (!existsSync48(assistDir)) {
|
|
19424
|
+
mkdirSync18(assistDir, { recursive: true });
|
|
18935
19425
|
}
|
|
18936
19426
|
const cacheData = {
|
|
18937
19427
|
prNumber,
|
|
18938
19428
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18939
19429
|
comments: comments3
|
|
18940
19430
|
};
|
|
18941
|
-
const cachePath =
|
|
19431
|
+
const cachePath = join57(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
18942
19432
|
writeFileSync35(cachePath, stringify(cacheData));
|
|
18943
19433
|
}
|
|
18944
19434
|
function handleKnownErrors(error) {
|
|
@@ -18971,7 +19461,7 @@ async function listComments() {
|
|
|
18971
19461
|
];
|
|
18972
19462
|
updateCache(prNumber, allComments);
|
|
18973
19463
|
const hasLineComments = allComments.some((c) => c.type === "line");
|
|
18974
|
-
const cachePath = hasLineComments ?
|
|
19464
|
+
const cachePath = hasLineComments ? join57(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
|
|
18975
19465
|
return { comments: allComments, cachePath };
|
|
18976
19466
|
} catch (error) {
|
|
18977
19467
|
const handled = handleKnownErrors(error);
|
|
@@ -18981,7 +19471,7 @@ async function listComments() {
|
|
|
18981
19471
|
}
|
|
18982
19472
|
|
|
18983
19473
|
// src/commands/prs/prs/index.ts
|
|
18984
|
-
import { execSync as
|
|
19474
|
+
import { execSync as execSync47 } from "child_process";
|
|
18985
19475
|
|
|
18986
19476
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
18987
19477
|
import enquirer9 from "enquirer";
|
|
@@ -19088,7 +19578,7 @@ async function prs(options2) {
|
|
|
19088
19578
|
const state = options2.open ? "open" : options2.closed ? "closed" : "all";
|
|
19089
19579
|
try {
|
|
19090
19580
|
const { org, repo } = getRepoInfo();
|
|
19091
|
-
const result =
|
|
19581
|
+
const result = execSync47(
|
|
19092
19582
|
`gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100 -R ${org}/${repo}`,
|
|
19093
19583
|
{ encoding: "utf8" }
|
|
19094
19584
|
);
|
|
@@ -19159,16 +19649,16 @@ function buildCreateArgs(title, body, options2) {
|
|
|
19159
19649
|
}
|
|
19160
19650
|
|
|
19161
19651
|
// src/commands/prs/readSessionPrRef.ts
|
|
19162
|
-
import { execSync as
|
|
19652
|
+
import { execSync as execSync48 } from "child_process";
|
|
19163
19653
|
function readSessionPrRef() {
|
|
19164
19654
|
try {
|
|
19165
|
-
const branch2 =
|
|
19655
|
+
const branch2 = execSync48("git rev-parse --abbrev-ref HEAD", {
|
|
19166
19656
|
encoding: "utf8",
|
|
19167
19657
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19168
19658
|
}).trim();
|
|
19169
19659
|
if (!branch2 || branch2 === "HEAD") return null;
|
|
19170
19660
|
const pr = JSON.parse(
|
|
19171
|
-
|
|
19661
|
+
execSync48(`gh pr view ${branch2} --json number,title,url,state`, {
|
|
19172
19662
|
encoding: "utf8",
|
|
19173
19663
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19174
19664
|
})
|
|
@@ -19296,7 +19786,7 @@ function reply(commentId, body) {
|
|
|
19296
19786
|
}
|
|
19297
19787
|
|
|
19298
19788
|
// src/commands/prs/wontfix.ts
|
|
19299
|
-
import { execSync as
|
|
19789
|
+
import { execSync as execSync49 } from "child_process";
|
|
19300
19790
|
function validateReason(reason2) {
|
|
19301
19791
|
const lowerReason = reason2.toLowerCase();
|
|
19302
19792
|
if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
|
|
@@ -19313,7 +19803,7 @@ function validateShaReferences(reason2) {
|
|
|
19313
19803
|
const invalidShas = [];
|
|
19314
19804
|
for (const sha of shas) {
|
|
19315
19805
|
try {
|
|
19316
|
-
|
|
19806
|
+
execSync49(`git cat-file -t ${sha}`, { stdio: "pipe" });
|
|
19317
19807
|
} catch {
|
|
19318
19808
|
invalidShas.push(sha);
|
|
19319
19809
|
}
|
|
@@ -19590,10 +20080,10 @@ import chalk168 from "chalk";
|
|
|
19590
20080
|
import Enquirer2 from "enquirer";
|
|
19591
20081
|
|
|
19592
20082
|
// src/commands/ravendb/searchItems.ts
|
|
19593
|
-
import { execSync as
|
|
20083
|
+
import { execSync as execSync50 } from "child_process";
|
|
19594
20084
|
import chalk167 from "chalk";
|
|
19595
20085
|
function opExec(args) {
|
|
19596
|
-
return
|
|
20086
|
+
return execSync50(`op ${args}`, {
|
|
19597
20087
|
encoding: "utf8",
|
|
19598
20088
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19599
20089
|
}).trim();
|
|
@@ -19745,7 +20235,7 @@ ${errorText}`
|
|
|
19745
20235
|
}
|
|
19746
20236
|
|
|
19747
20237
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
19748
|
-
import { execSync as
|
|
20238
|
+
import { execSync as execSync51 } from "child_process";
|
|
19749
20239
|
import chalk172 from "chalk";
|
|
19750
20240
|
function resolveOpSecret(reference) {
|
|
19751
20241
|
if (!reference.startsWith("op://")) {
|
|
@@ -19753,7 +20243,7 @@ function resolveOpSecret(reference) {
|
|
|
19753
20243
|
process.exit(1);
|
|
19754
20244
|
}
|
|
19755
20245
|
try {
|
|
19756
|
-
return
|
|
20246
|
+
return execSync51(`op read "${reference}"`, {
|
|
19757
20247
|
encoding: "utf8",
|
|
19758
20248
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19759
20249
|
}).trim();
|
|
@@ -20017,7 +20507,7 @@ Refactor check failed:
|
|
|
20017
20507
|
}
|
|
20018
20508
|
|
|
20019
20509
|
// src/commands/refactor/check/getViolations/index.ts
|
|
20020
|
-
import { execSync as
|
|
20510
|
+
import { execSync as execSync52 } from "child_process";
|
|
20021
20511
|
import fs25 from "fs";
|
|
20022
20512
|
import { minimatch as minimatch6 } from "minimatch";
|
|
20023
20513
|
|
|
@@ -20067,7 +20557,7 @@ function getGitFiles(options2) {
|
|
|
20067
20557
|
}
|
|
20068
20558
|
const files = /* @__PURE__ */ new Set();
|
|
20069
20559
|
if (options2.staged || options2.modified) {
|
|
20070
|
-
const staged =
|
|
20560
|
+
const staged = execSync52("git diff --cached --name-only", {
|
|
20071
20561
|
encoding: "utf8"
|
|
20072
20562
|
});
|
|
20073
20563
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
@@ -20075,7 +20565,7 @@ function getGitFiles(options2) {
|
|
|
20075
20565
|
}
|
|
20076
20566
|
}
|
|
20077
20567
|
if (options2.unstaged || options2.modified) {
|
|
20078
|
-
const unstaged =
|
|
20568
|
+
const unstaged = execSync52("git diff --name-only", { encoding: "utf8" });
|
|
20079
20569
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
20080
20570
|
files.add(file);
|
|
20081
20571
|
}
|
|
@@ -21342,8 +21832,8 @@ function findRootParent(file, importedBy, visited) {
|
|
|
21342
21832
|
function clusterFiles(graph) {
|
|
21343
21833
|
const clusters = /* @__PURE__ */ new Map();
|
|
21344
21834
|
for (const file of graph.files) {
|
|
21345
|
-
const
|
|
21346
|
-
if (
|
|
21835
|
+
const basename19 = path52.basename(file, path52.extname(file));
|
|
21836
|
+
if (basename19 === "index") continue;
|
|
21347
21837
|
const importers = graph.importedBy.get(file);
|
|
21348
21838
|
if (!importers || importers.size !== 1) continue;
|
|
21349
21839
|
const parent = [...importers][0];
|
|
@@ -21649,9 +22139,6 @@ function registerRefactor(program2) {
|
|
|
21649
22139
|
registerRestructure(refactorCommand);
|
|
21650
22140
|
}
|
|
21651
22141
|
|
|
21652
|
-
// src/commands/review/review.ts
|
|
21653
|
-
import { execFileSync as execFileSync9 } from "child_process";
|
|
21654
|
-
|
|
21655
22142
|
// src/commands/review/annotateDiffWithLineNumbers.ts
|
|
21656
22143
|
var FILE_HEADER2 = /^\+\+\+ (?:b\/)?(.+)$/;
|
|
21657
22144
|
var HUNK_HEADER2 = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
|
|
@@ -21766,28 +22253,28 @@ ${annotateDiffWithLineNumbers(context.diff.trimEnd())}
|
|
|
21766
22253
|
|
|
21767
22254
|
// src/commands/review/buildReviewPaths.ts
|
|
21768
22255
|
import { homedir as homedir20 } from "os";
|
|
21769
|
-
import { basename as
|
|
22256
|
+
import { basename as basename14, join as join58 } from "path";
|
|
21770
22257
|
function buildReviewPaths(repoRoot, key) {
|
|
21771
|
-
const reviewDir =
|
|
22258
|
+
const reviewDir = join58(
|
|
21772
22259
|
homedir20(),
|
|
21773
22260
|
".assist",
|
|
21774
22261
|
"reviews",
|
|
21775
|
-
|
|
22262
|
+
basename14(repoRoot),
|
|
21776
22263
|
key
|
|
21777
22264
|
);
|
|
21778
22265
|
return {
|
|
21779
22266
|
reviewDir,
|
|
21780
|
-
requestPath:
|
|
21781
|
-
claudePath:
|
|
21782
|
-
codexPath:
|
|
21783
|
-
synthesisPath:
|
|
22267
|
+
requestPath: join58(reviewDir, "request.md"),
|
|
22268
|
+
claudePath: join58(reviewDir, "claude.md"),
|
|
22269
|
+
codexPath: join58(reviewDir, "codex.md"),
|
|
22270
|
+
synthesisPath: join58(reviewDir, "synthesis.md")
|
|
21784
22271
|
};
|
|
21785
22272
|
}
|
|
21786
22273
|
|
|
21787
22274
|
// src/commands/review/fetchExistingComments.ts
|
|
21788
|
-
import { execSync as
|
|
22275
|
+
import { execSync as execSync53 } from "child_process";
|
|
21789
22276
|
function fetchRawComments(org, repo, prNumber) {
|
|
21790
|
-
const out =
|
|
22277
|
+
const out = execSync53(
|
|
21791
22278
|
`gh api --paginate repos/${org}/${repo}/pulls/${prNumber}/comments`,
|
|
21792
22279
|
{ encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }
|
|
21793
22280
|
);
|
|
@@ -21818,14 +22305,14 @@ function fetchExistingComments() {
|
|
|
21818
22305
|
}
|
|
21819
22306
|
|
|
21820
22307
|
// src/commands/review/gatherContext.ts
|
|
21821
|
-
import { execSync as
|
|
22308
|
+
import { execSync as execSync56 } from "child_process";
|
|
21822
22309
|
|
|
21823
22310
|
// src/commands/review/fetchPrDiff.ts
|
|
21824
|
-
import { execSync as
|
|
22311
|
+
import { execSync as execSync54 } from "child_process";
|
|
21825
22312
|
function fetchPrDiff(prNumber, baseSha, headSha) {
|
|
21826
22313
|
const { org, repo } = getRepoInfo();
|
|
21827
22314
|
try {
|
|
21828
|
-
return
|
|
22315
|
+
return execSync54(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
|
|
21829
22316
|
encoding: "utf8",
|
|
21830
22317
|
maxBuffer: 256 * 1024 * 1024,
|
|
21831
22318
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -21840,19 +22327,19 @@ function isDiffTooLarge(error) {
|
|
|
21840
22327
|
}
|
|
21841
22328
|
function fetchDiffViaGit(baseSha, headSha) {
|
|
21842
22329
|
try {
|
|
21843
|
-
|
|
22330
|
+
execSync54(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
|
|
21844
22331
|
} catch {
|
|
21845
22332
|
}
|
|
21846
|
-
return
|
|
22333
|
+
return execSync54(`git diff ${baseSha}...${headSha}`, {
|
|
21847
22334
|
encoding: "utf8",
|
|
21848
22335
|
maxBuffer: 256 * 1024 * 1024
|
|
21849
22336
|
});
|
|
21850
22337
|
}
|
|
21851
22338
|
|
|
21852
22339
|
// src/commands/review/fetchPrDiffInfo.ts
|
|
21853
|
-
import { execSync as
|
|
22340
|
+
import { execSync as execSync55 } from "child_process";
|
|
21854
22341
|
function getCurrentBranch3() {
|
|
21855
|
-
return
|
|
22342
|
+
return execSync55("git rev-parse --abbrev-ref HEAD", {
|
|
21856
22343
|
encoding: "utf8"
|
|
21857
22344
|
}).trim();
|
|
21858
22345
|
}
|
|
@@ -21860,7 +22347,7 @@ function fetchPrDiffInfo() {
|
|
|
21860
22347
|
const { org, repo } = getRepoInfo();
|
|
21861
22348
|
const branch2 = getCurrentBranch3();
|
|
21862
22349
|
const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
|
|
21863
|
-
const raw =
|
|
22350
|
+
const raw = execSync55(
|
|
21864
22351
|
`gh pr list --state open --head ${branch2} --json ${fields} -R ${org}/${repo}`,
|
|
21865
22352
|
{
|
|
21866
22353
|
encoding: "utf8",
|
|
@@ -21885,7 +22372,7 @@ function fetchPrDiffInfo() {
|
|
|
21885
22372
|
}
|
|
21886
22373
|
function fetchPrChangedFiles(prNumber) {
|
|
21887
22374
|
const { org, repo } = getRepoInfo();
|
|
21888
|
-
const out =
|
|
22375
|
+
const out = execSync55(
|
|
21889
22376
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/files --paginate --jq ".[].filename"`,
|
|
21890
22377
|
{
|
|
21891
22378
|
encoding: "utf8",
|
|
@@ -21897,11 +22384,11 @@ function fetchPrChangedFiles(prNumber) {
|
|
|
21897
22384
|
|
|
21898
22385
|
// src/commands/review/gatherContext.ts
|
|
21899
22386
|
function gatherContext() {
|
|
21900
|
-
const branch2 =
|
|
22387
|
+
const branch2 = execSync56("git rev-parse --abbrev-ref HEAD", {
|
|
21901
22388
|
encoding: "utf8"
|
|
21902
22389
|
}).trim();
|
|
21903
|
-
const sha =
|
|
21904
|
-
const shortSha =
|
|
22390
|
+
const sha = execSync56("git rev-parse HEAD", { encoding: "utf8" }).trim();
|
|
22391
|
+
const shortSha = execSync56("git rev-parse --short=7 HEAD", {
|
|
21905
22392
|
encoding: "utf8"
|
|
21906
22393
|
}).trim();
|
|
21907
22394
|
const prInfo = fetchPrDiffInfo();
|
|
@@ -22319,14 +22806,14 @@ async function handlePostSynthesis(synthesisPath, options2) {
|
|
|
22319
22806
|
}
|
|
22320
22807
|
|
|
22321
22808
|
// src/commands/review/prepareReviewDir.ts
|
|
22322
|
-
import { existsSync as
|
|
22809
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync19, unlinkSync as unlinkSync16, writeFileSync as writeFileSync36 } from "fs";
|
|
22323
22810
|
function clearReviewFiles(paths) {
|
|
22324
22811
|
for (const path71 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
22325
|
-
if (
|
|
22812
|
+
if (existsSync49(path71)) unlinkSync16(path71);
|
|
22326
22813
|
}
|
|
22327
22814
|
}
|
|
22328
22815
|
function prepareReviewDir(paths, requestBody, force) {
|
|
22329
|
-
|
|
22816
|
+
mkdirSync19(paths.reviewDir, { recursive: true });
|
|
22330
22817
|
if (force) clearReviewFiles(paths);
|
|
22331
22818
|
writeFileSync36(paths.requestPath, requestBody);
|
|
22332
22819
|
}
|
|
@@ -22607,7 +23094,7 @@ function printReviewerFailures(results) {
|
|
|
22607
23094
|
}
|
|
22608
23095
|
|
|
22609
23096
|
// src/commands/review/runAndSynthesise.ts
|
|
22610
|
-
import { existsSync as
|
|
23097
|
+
import { existsSync as existsSync51, unlinkSync as unlinkSync18 } from "fs";
|
|
22611
23098
|
|
|
22612
23099
|
// src/commands/review/buildReviewerStdin.ts
|
|
22613
23100
|
var REVIEW_PROMPT = `You are acting as a reviewer for a proposed code change made by another engineer. The full review request \u2014 branch, base, changed files, and unified diff \u2014 is in the request file whose absolute path is given below.
|
|
@@ -23027,7 +23514,7 @@ function resolveClaude(args) {
|
|
|
23027
23514
|
}
|
|
23028
23515
|
|
|
23029
23516
|
// src/commands/review/runCodexReviewer.ts
|
|
23030
|
-
import { existsSync as
|
|
23517
|
+
import { existsSync as existsSync50, unlinkSync as unlinkSync17 } from "fs";
|
|
23031
23518
|
|
|
23032
23519
|
// src/commands/review/parseCodexEvent.ts
|
|
23033
23520
|
function isItemStarted(value) {
|
|
@@ -23079,7 +23566,7 @@ async function runCodexReviewer(spec) {
|
|
|
23079
23566
|
reportReviewerToolUse(spec.name, event, spinner);
|
|
23080
23567
|
}
|
|
23081
23568
|
});
|
|
23082
|
-
if (result.exitCode !== 0 &&
|
|
23569
|
+
if (result.exitCode !== 0 && existsSync50(spec.outputPath)) {
|
|
23083
23570
|
unlinkSync17(spec.outputPath);
|
|
23084
23571
|
}
|
|
23085
23572
|
return finaliseReviewerRun({ ...spec, command }, spinner, result);
|
|
@@ -23225,7 +23712,7 @@ async function runAndSynthesise(args) {
|
|
|
23225
23712
|
console.error("Both reviewers failed; skipping synthesis.");
|
|
23226
23713
|
return { ok: false, failures };
|
|
23227
23714
|
}
|
|
23228
|
-
if (anyFresh &&
|
|
23715
|
+
if (anyFresh && existsSync51(paths.synthesisPath)) {
|
|
23229
23716
|
unlinkSync18(paths.synthesisPath);
|
|
23230
23717
|
}
|
|
23231
23718
|
const synthesisResult = await synthesise(paths, { multi });
|
|
@@ -23346,20 +23833,13 @@ function validateOptions(options2) {
|
|
|
23346
23833
|
process.exit(1);
|
|
23347
23834
|
}
|
|
23348
23835
|
}
|
|
23349
|
-
function checkoutPr(number) {
|
|
23350
|
-
try {
|
|
23351
|
-
execFileSync9("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
23352
|
-
} catch {
|
|
23353
|
-
console.error(`gh pr checkout ${number} failed; aborting.`);
|
|
23354
|
-
process.exit(1);
|
|
23355
|
-
}
|
|
23356
|
-
}
|
|
23357
23836
|
async function review(options2 = {}) {
|
|
23358
23837
|
validateOptions(options2);
|
|
23359
|
-
const
|
|
23838
|
+
const invokedIn = resolveRepoRoot();
|
|
23360
23839
|
emitActivity({ kind: "command", name: "review" });
|
|
23361
|
-
if (options2.number)
|
|
23362
|
-
await
|
|
23840
|
+
if (!options2.number) return reviewPr(invokedIn, options2);
|
|
23841
|
+
await checkoutPr(options2.number);
|
|
23842
|
+
return reviewPr(resolveRepoRoot(), options2);
|
|
23363
23843
|
}
|
|
23364
23844
|
|
|
23365
23845
|
// src/commands/registerReview.ts
|
|
@@ -24105,27 +24585,27 @@ async function configure() {
|
|
|
24105
24585
|
}
|
|
24106
24586
|
|
|
24107
24587
|
// src/commands/transcript/list.ts
|
|
24108
|
-
import { existsSync as
|
|
24109
|
-
import { join as
|
|
24588
|
+
import { existsSync as existsSync52, readdirSync as readdirSync10, statSync as statSync8 } from "fs";
|
|
24589
|
+
import { join as join59 } from "path";
|
|
24110
24590
|
function list4() {
|
|
24111
24591
|
const { vttDir } = getTranscriptConfig();
|
|
24112
|
-
if (!
|
|
24592
|
+
if (!existsSync52(vttDir)) return;
|
|
24113
24593
|
for (const entry of readdirSync10(vttDir)) {
|
|
24114
24594
|
if (!entry.endsWith(".vtt")) continue;
|
|
24115
|
-
if (statSync8(
|
|
24595
|
+
if (statSync8(join59(vttDir, entry)).isDirectory()) continue;
|
|
24116
24596
|
console.log(entry);
|
|
24117
24597
|
}
|
|
24118
24598
|
}
|
|
24119
24599
|
|
|
24120
24600
|
// src/commands/transcript/move.ts
|
|
24121
24601
|
import {
|
|
24122
|
-
existsSync as
|
|
24123
|
-
mkdirSync as
|
|
24602
|
+
existsSync as existsSync53,
|
|
24603
|
+
mkdirSync as mkdirSync20,
|
|
24124
24604
|
readFileSync as readFileSync42,
|
|
24125
24605
|
renameSync as renameSync2,
|
|
24126
24606
|
writeFileSync as writeFileSync38
|
|
24127
24607
|
} from "fs";
|
|
24128
|
-
import { basename as
|
|
24608
|
+
import { basename as basename15, join as join60 } from "path";
|
|
24129
24609
|
|
|
24130
24610
|
// src/commands/transcript/cleanText.ts
|
|
24131
24611
|
function cleanText(text17) {
|
|
@@ -24338,9 +24818,9 @@ function convertVttToMarkdown(inputPath) {
|
|
|
24338
24818
|
return formatChatLog(messages);
|
|
24339
24819
|
}
|
|
24340
24820
|
function archiveRawVtt(vttDir, sourcePath, filename) {
|
|
24341
|
-
const processedDir =
|
|
24342
|
-
|
|
24343
|
-
renameSync2(sourcePath,
|
|
24821
|
+
const processedDir = join60(vttDir, "processed");
|
|
24822
|
+
mkdirSync20(processedDir, { recursive: true });
|
|
24823
|
+
renameSync2(sourcePath, join60(processedDir, filename));
|
|
24344
24824
|
}
|
|
24345
24825
|
function move(file, options2) {
|
|
24346
24826
|
const { date, client } = options2;
|
|
@@ -24349,20 +24829,20 @@ function move(file, options2) {
|
|
|
24349
24829
|
process.exit(1);
|
|
24350
24830
|
}
|
|
24351
24831
|
const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
24352
|
-
const filename =
|
|
24353
|
-
const sourcePath =
|
|
24354
|
-
if (!
|
|
24832
|
+
const filename = basename15(file);
|
|
24833
|
+
const sourcePath = join60(vttDir, filename);
|
|
24834
|
+
if (!existsSync53(sourcePath)) {
|
|
24355
24835
|
console.error(`Error: VTT file not found: ${sourcePath}`);
|
|
24356
24836
|
process.exit(1);
|
|
24357
24837
|
}
|
|
24358
|
-
const base =
|
|
24838
|
+
const base = basename15(filename, ".vtt").replace(/ Transcription$/, "");
|
|
24359
24839
|
const outputName = `${date} ${base}.md`;
|
|
24360
|
-
const formattedDir =
|
|
24361
|
-
|
|
24362
|
-
const formattedPath =
|
|
24840
|
+
const formattedDir = join60(transcriptsDir, client);
|
|
24841
|
+
mkdirSync20(formattedDir, { recursive: true });
|
|
24842
|
+
const formattedPath = join60(formattedDir, outputName);
|
|
24363
24843
|
writeFileSync38(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
|
|
24364
24844
|
archiveRawVtt(vttDir, sourcePath, filename);
|
|
24365
|
-
const summaryPath =
|
|
24845
|
+
const summaryPath = join60(summaryDir, client, outputName);
|
|
24366
24846
|
console.log(`Formatted transcript: ${formattedPath}`);
|
|
24367
24847
|
console.log(`Summary target: ${summaryPath}`);
|
|
24368
24848
|
}
|
|
@@ -24482,45 +24962,45 @@ function registerVerify(program2) {
|
|
|
24482
24962
|
|
|
24483
24963
|
// src/commands/voice/devices.ts
|
|
24484
24964
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
24485
|
-
import { join as
|
|
24965
|
+
import { join as join62 } from "path";
|
|
24486
24966
|
|
|
24487
24967
|
// src/commands/voice/shared.ts
|
|
24488
24968
|
import { homedir as homedir21 } from "os";
|
|
24489
|
-
import { dirname as
|
|
24969
|
+
import { dirname as dirname28, join as join61 } from "path";
|
|
24490
24970
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
24491
|
-
var __dirname5 =
|
|
24492
|
-
var VOICE_DIR =
|
|
24971
|
+
var __dirname5 = dirname28(fileURLToPath7(import.meta.url));
|
|
24972
|
+
var VOICE_DIR = join61(homedir21(), ".assist", "voice");
|
|
24493
24973
|
var voicePaths = {
|
|
24494
24974
|
dir: VOICE_DIR,
|
|
24495
|
-
pid:
|
|
24496
|
-
log:
|
|
24497
|
-
venv:
|
|
24498
|
-
lock:
|
|
24975
|
+
pid: join61(VOICE_DIR, "voice.pid"),
|
|
24976
|
+
log: join61(VOICE_DIR, "voice.log"),
|
|
24977
|
+
venv: join61(VOICE_DIR, ".venv"),
|
|
24978
|
+
lock: join61(VOICE_DIR, "voice.lock")
|
|
24499
24979
|
};
|
|
24500
24980
|
function getPythonDir() {
|
|
24501
|
-
return
|
|
24981
|
+
return join61(__dirname5, "commands", "voice", "python");
|
|
24502
24982
|
}
|
|
24503
24983
|
function getVenvPython() {
|
|
24504
|
-
return process.platform === "win32" ?
|
|
24984
|
+
return process.platform === "win32" ? join61(voicePaths.venv, "Scripts", "python.exe") : join61(voicePaths.venv, "bin", "python");
|
|
24505
24985
|
}
|
|
24506
24986
|
function getLockDir() {
|
|
24507
24987
|
const config = loadConfig();
|
|
24508
24988
|
return config.voice?.lockDir ?? VOICE_DIR;
|
|
24509
24989
|
}
|
|
24510
24990
|
function getLockFile() {
|
|
24511
|
-
return
|
|
24991
|
+
return join61(getLockDir(), "voice.lock");
|
|
24512
24992
|
}
|
|
24513
24993
|
|
|
24514
24994
|
// src/commands/voice/devices.ts
|
|
24515
24995
|
function devices() {
|
|
24516
|
-
const script =
|
|
24996
|
+
const script = join62(getPythonDir(), "list_devices.py");
|
|
24517
24997
|
spawnSync6(getVenvPython(), [script], { stdio: "inherit" });
|
|
24518
24998
|
}
|
|
24519
24999
|
|
|
24520
25000
|
// src/commands/voice/logs.ts
|
|
24521
|
-
import { existsSync as
|
|
25001
|
+
import { existsSync as existsSync54, readFileSync as readFileSync43 } from "fs";
|
|
24522
25002
|
function logs(options2) {
|
|
24523
|
-
if (!
|
|
25003
|
+
if (!existsSync54(voicePaths.log)) {
|
|
24524
25004
|
console.log("No voice log file found");
|
|
24525
25005
|
return;
|
|
24526
25006
|
}
|
|
@@ -24547,13 +25027,13 @@ function logs(options2) {
|
|
|
24547
25027
|
|
|
24548
25028
|
// src/commands/voice/setup.ts
|
|
24549
25029
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
24550
|
-
import { mkdirSync as
|
|
24551
|
-
import { join as
|
|
25030
|
+
import { mkdirSync as mkdirSync22 } from "fs";
|
|
25031
|
+
import { join as join64 } from "path";
|
|
24552
25032
|
|
|
24553
25033
|
// src/commands/voice/checkLockFile.ts
|
|
24554
|
-
import { execSync as
|
|
24555
|
-
import { existsSync as
|
|
24556
|
-
import { join as
|
|
25034
|
+
import { execSync as execSync57 } from "child_process";
|
|
25035
|
+
import { existsSync as existsSync55, mkdirSync as mkdirSync21, readFileSync as readFileSync44, writeFileSync as writeFileSync39 } from "fs";
|
|
25036
|
+
import { join as join63 } from "path";
|
|
24557
25037
|
function isProcessAlive2(pid) {
|
|
24558
25038
|
try {
|
|
24559
25039
|
process.kill(pid, 0);
|
|
@@ -24564,7 +25044,7 @@ function isProcessAlive2(pid) {
|
|
|
24564
25044
|
}
|
|
24565
25045
|
function checkLockFile() {
|
|
24566
25046
|
const lockFile = getLockFile();
|
|
24567
|
-
if (!
|
|
25047
|
+
if (!existsSync55(lockFile)) return;
|
|
24568
25048
|
try {
|
|
24569
25049
|
const lock2 = JSON.parse(readFileSync44(lockFile, "utf8"));
|
|
24570
25050
|
if (lock2.pid && isProcessAlive2(lock2.pid)) {
|
|
@@ -24577,10 +25057,10 @@ function checkLockFile() {
|
|
|
24577
25057
|
}
|
|
24578
25058
|
}
|
|
24579
25059
|
function bootstrapVenv() {
|
|
24580
|
-
if (
|
|
25060
|
+
if (existsSync55(getVenvPython())) return;
|
|
24581
25061
|
console.log("Setting up Python environment...");
|
|
24582
25062
|
const pythonDir = getPythonDir();
|
|
24583
|
-
|
|
25063
|
+
execSync57(
|
|
24584
25064
|
`uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
|
|
24585
25065
|
{
|
|
24586
25066
|
stdio: "inherit",
|
|
@@ -24590,7 +25070,7 @@ function bootstrapVenv() {
|
|
|
24590
25070
|
}
|
|
24591
25071
|
function writeLockFile(pid) {
|
|
24592
25072
|
const lockFile = getLockFile();
|
|
24593
|
-
|
|
25073
|
+
mkdirSync21(join63(lockFile, ".."), { recursive: true });
|
|
24594
25074
|
writeFileSync39(
|
|
24595
25075
|
lockFile,
|
|
24596
25076
|
JSON.stringify({
|
|
@@ -24603,10 +25083,10 @@ function writeLockFile(pid) {
|
|
|
24603
25083
|
|
|
24604
25084
|
// src/commands/voice/setup.ts
|
|
24605
25085
|
function setup() {
|
|
24606
|
-
|
|
25086
|
+
mkdirSync22(voicePaths.dir, { recursive: true });
|
|
24607
25087
|
bootstrapVenv();
|
|
24608
25088
|
console.log("\nDownloading models...\n");
|
|
24609
|
-
const script =
|
|
25089
|
+
const script = join64(getPythonDir(), "setup_models.py");
|
|
24610
25090
|
const result = spawnSync7(getVenvPython(), [script], {
|
|
24611
25091
|
stdio: "inherit",
|
|
24612
25092
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
@@ -24619,8 +25099,8 @@ function setup() {
|
|
|
24619
25099
|
|
|
24620
25100
|
// src/commands/voice/start.ts
|
|
24621
25101
|
import { spawn as spawn7 } from "child_process";
|
|
24622
|
-
import { mkdirSync as
|
|
24623
|
-
import { join as
|
|
25102
|
+
import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync40 } from "fs";
|
|
25103
|
+
import { join as join65 } from "path";
|
|
24624
25104
|
|
|
24625
25105
|
// src/commands/voice/buildDaemonEnv.ts
|
|
24626
25106
|
function buildDaemonEnv(options2) {
|
|
@@ -24653,12 +25133,12 @@ function spawnBackground(python, script, env) {
|
|
|
24653
25133
|
console.log(`Voice daemon started (PID ${pid})`);
|
|
24654
25134
|
}
|
|
24655
25135
|
function start2(options2) {
|
|
24656
|
-
|
|
25136
|
+
mkdirSync23(voicePaths.dir, { recursive: true });
|
|
24657
25137
|
checkLockFile();
|
|
24658
25138
|
bootstrapVenv();
|
|
24659
25139
|
const debug = options2.debug || options2.foreground || process.platform === "win32";
|
|
24660
25140
|
const env = buildDaemonEnv({ debug });
|
|
24661
|
-
const script =
|
|
25141
|
+
const script = join65(getPythonDir(), "voice_daemon.py");
|
|
24662
25142
|
const python = getVenvPython();
|
|
24663
25143
|
if (options2.foreground) {
|
|
24664
25144
|
spawnForeground(python, script, env);
|
|
@@ -24668,7 +25148,7 @@ function start2(options2) {
|
|
|
24668
25148
|
}
|
|
24669
25149
|
|
|
24670
25150
|
// src/commands/voice/status.ts
|
|
24671
|
-
import { existsSync as
|
|
25151
|
+
import { existsSync as existsSync56, readFileSync as readFileSync45 } from "fs";
|
|
24672
25152
|
function isProcessAlive3(pid) {
|
|
24673
25153
|
try {
|
|
24674
25154
|
process.kill(pid, 0);
|
|
@@ -24678,12 +25158,12 @@ function isProcessAlive3(pid) {
|
|
|
24678
25158
|
}
|
|
24679
25159
|
}
|
|
24680
25160
|
function readRecentLogs(count7) {
|
|
24681
|
-
if (!
|
|
25161
|
+
if (!existsSync56(voicePaths.log)) return [];
|
|
24682
25162
|
const lines = readFileSync45(voicePaths.log, "utf8").trim().split("\n");
|
|
24683
25163
|
return lines.slice(-count7);
|
|
24684
25164
|
}
|
|
24685
25165
|
function status2() {
|
|
24686
|
-
if (!
|
|
25166
|
+
if (!existsSync56(voicePaths.pid)) {
|
|
24687
25167
|
console.log("Voice daemon: not running (no PID file)");
|
|
24688
25168
|
return;
|
|
24689
25169
|
}
|
|
@@ -24706,9 +25186,9 @@ function status2() {
|
|
|
24706
25186
|
}
|
|
24707
25187
|
|
|
24708
25188
|
// src/commands/voice/stop.ts
|
|
24709
|
-
import { existsSync as
|
|
25189
|
+
import { existsSync as existsSync57, readFileSync as readFileSync46, unlinkSync as unlinkSync19 } from "fs";
|
|
24710
25190
|
function stop2() {
|
|
24711
|
-
if (!
|
|
25191
|
+
if (!existsSync57(voicePaths.pid)) {
|
|
24712
25192
|
console.log("Voice daemon is not running (no PID file)");
|
|
24713
25193
|
return;
|
|
24714
25194
|
}
|
|
@@ -24725,7 +25205,7 @@ function stop2() {
|
|
|
24725
25205
|
}
|
|
24726
25206
|
try {
|
|
24727
25207
|
const lockFile = getLockFile();
|
|
24728
|
-
if (
|
|
25208
|
+
if (existsSync57(lockFile)) unlinkSync19(lockFile);
|
|
24729
25209
|
} catch {
|
|
24730
25210
|
}
|
|
24731
25211
|
console.log("Voice daemon stopped");
|
|
@@ -24947,9 +25427,9 @@ async function auth() {
|
|
|
24947
25427
|
}
|
|
24948
25428
|
|
|
24949
25429
|
// src/commands/roam/postRoamActivity.ts
|
|
24950
|
-
import { execFileSync as
|
|
25430
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
24951
25431
|
import { readdirSync as readdirSync11, readFileSync as readFileSync47, statSync as statSync9 } from "fs";
|
|
24952
|
-
import { join as
|
|
25432
|
+
import { join as join66 } from "path";
|
|
24953
25433
|
function findPortFile(roamDir) {
|
|
24954
25434
|
let entries;
|
|
24955
25435
|
try {
|
|
@@ -24958,7 +25438,7 @@ function findPortFile(roamDir) {
|
|
|
24958
25438
|
return void 0;
|
|
24959
25439
|
}
|
|
24960
25440
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
24961
|
-
const path71 =
|
|
25441
|
+
const path71 = join66(roamDir, name);
|
|
24962
25442
|
try {
|
|
24963
25443
|
return { path: path71, mtimeMs: statSync9(path71).mtimeMs };
|
|
24964
25444
|
} catch {
|
|
@@ -24970,7 +25450,7 @@ function findPortFile(roamDir) {
|
|
|
24970
25450
|
function postRoamActivity(app, event) {
|
|
24971
25451
|
const appData = process.env.APPDATA;
|
|
24972
25452
|
if (!appData) return;
|
|
24973
|
-
const portFile = findPortFile(
|
|
25453
|
+
const portFile = findPortFile(join66(appData, "Roam"));
|
|
24974
25454
|
if (!portFile) return;
|
|
24975
25455
|
let port;
|
|
24976
25456
|
try {
|
|
@@ -24980,7 +25460,7 @@ function postRoamActivity(app, event) {
|
|
|
24980
25460
|
}
|
|
24981
25461
|
const url = `http://127.0.0.1:${port}/api/v1/activity/${app}/${event}?pid=${app === "codex" ? 99998 : 99999}`;
|
|
24982
25462
|
try {
|
|
24983
|
-
|
|
25463
|
+
execFileSync9("curl", ["-sf", "--max-time", "0.2", "-X", "POST", url], {
|
|
24984
25464
|
stdio: "ignore"
|
|
24985
25465
|
});
|
|
24986
25466
|
} catch {
|
|
@@ -25188,11 +25668,11 @@ function resolveParams(params, cliArgs) {
|
|
|
25188
25668
|
}
|
|
25189
25669
|
|
|
25190
25670
|
// src/commands/run/runPreCommands.ts
|
|
25191
|
-
import { execSync as
|
|
25671
|
+
import { execSync as execSync58 } from "child_process";
|
|
25192
25672
|
function runPreCommands(pre, cwd) {
|
|
25193
25673
|
for (const cmd of pre) {
|
|
25194
25674
|
try {
|
|
25195
|
-
|
|
25675
|
+
execSync58(cmd, { stdio: "inherit", cwd });
|
|
25196
25676
|
} catch (error) {
|
|
25197
25677
|
const code = error && typeof error === "object" && "status" in error ? error.status : 1;
|
|
25198
25678
|
process.exit(code);
|
|
@@ -25201,16 +25681,16 @@ function runPreCommands(pre, cwd) {
|
|
|
25201
25681
|
}
|
|
25202
25682
|
|
|
25203
25683
|
// src/commands/run/spawnRunCommand.ts
|
|
25204
|
-
import { execFileSync as
|
|
25205
|
-
import { existsSync as
|
|
25206
|
-
import { dirname as
|
|
25684
|
+
import { execFileSync as execFileSync10, spawn as spawn8 } from "child_process";
|
|
25685
|
+
import { existsSync as existsSync58 } from "fs";
|
|
25686
|
+
import { dirname as dirname29, join as join67, resolve as resolve15 } from "path";
|
|
25207
25687
|
function resolveCommand2(command) {
|
|
25208
25688
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
25209
25689
|
try {
|
|
25210
|
-
const gitPath =
|
|
25211
|
-
const gitRoot = resolve15(
|
|
25212
|
-
const gitBash =
|
|
25213
|
-
if (
|
|
25690
|
+
const gitPath = execFileSync10("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
25691
|
+
const gitRoot = resolve15(dirname29(gitPath), "..");
|
|
25692
|
+
const gitBash = join67(gitRoot, "bin", "bash.exe");
|
|
25693
|
+
if (existsSync58(gitBash)) return gitBash;
|
|
25214
25694
|
} catch {
|
|
25215
25695
|
}
|
|
25216
25696
|
return command;
|
|
@@ -25297,8 +25777,8 @@ async function run3(name, args) {
|
|
|
25297
25777
|
}
|
|
25298
25778
|
|
|
25299
25779
|
// src/commands/run/add.ts
|
|
25300
|
-
import { mkdirSync as
|
|
25301
|
-
import { join as
|
|
25780
|
+
import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync41 } from "fs";
|
|
25781
|
+
import { join as join68 } from "path";
|
|
25302
25782
|
|
|
25303
25783
|
// src/commands/run/extractOption.ts
|
|
25304
25784
|
function extractOption(args, flag) {
|
|
@@ -25359,15 +25839,15 @@ function saveNewRunConfig(name, command, args, cwd) {
|
|
|
25359
25839
|
saveConfig(config);
|
|
25360
25840
|
}
|
|
25361
25841
|
function createCommandFile(name) {
|
|
25362
|
-
const dir =
|
|
25363
|
-
|
|
25842
|
+
const dir = join68(".claude", "commands");
|
|
25843
|
+
mkdirSync24(dir, { recursive: true });
|
|
25364
25844
|
const content = `---
|
|
25365
25845
|
description: Run ${name}
|
|
25366
25846
|
---
|
|
25367
25847
|
|
|
25368
25848
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
25369
25849
|
`;
|
|
25370
|
-
const filePath =
|
|
25850
|
+
const filePath = join68(dir, `${name}.md`);
|
|
25371
25851
|
writeFileSync41(filePath, content);
|
|
25372
25852
|
console.log(`Created command file: ${filePath}`);
|
|
25373
25853
|
}
|
|
@@ -25423,8 +25903,8 @@ function link2() {
|
|
|
25423
25903
|
}
|
|
25424
25904
|
|
|
25425
25905
|
// src/commands/run/remove.ts
|
|
25426
|
-
import { existsSync as
|
|
25427
|
-
import { join as
|
|
25906
|
+
import { existsSync as existsSync59, unlinkSync as unlinkSync20 } from "fs";
|
|
25907
|
+
import { join as join69 } from "path";
|
|
25428
25908
|
function findRemoveIndex() {
|
|
25429
25909
|
const idx = process.argv.indexOf("remove");
|
|
25430
25910
|
if (idx === -1 || idx + 1 >= process.argv.length) return -1;
|
|
@@ -25439,8 +25919,8 @@ function parseRemoveName() {
|
|
|
25439
25919
|
return process.argv[idx + 1];
|
|
25440
25920
|
}
|
|
25441
25921
|
function deleteCommandFile(name) {
|
|
25442
|
-
const filePath =
|
|
25443
|
-
if (
|
|
25922
|
+
const filePath = join69(".claude", "commands", `${name}.md`);
|
|
25923
|
+
if (existsSync59(filePath)) {
|
|
25444
25924
|
unlinkSync20(filePath);
|
|
25445
25925
|
console.log(`Deleted command file: ${filePath}`);
|
|
25446
25926
|
}
|
|
@@ -25493,10 +25973,10 @@ function registerRun(program2) {
|
|
|
25493
25973
|
}
|
|
25494
25974
|
|
|
25495
25975
|
// src/commands/screenshot/index.ts
|
|
25496
|
-
import { execSync as
|
|
25497
|
-
import { existsSync as
|
|
25976
|
+
import { execSync as execSync59 } from "child_process";
|
|
25977
|
+
import { existsSync as existsSync60, mkdirSync as mkdirSync25, unlinkSync as unlinkSync21, writeFileSync as writeFileSync42 } from "fs";
|
|
25498
25978
|
import { tmpdir as tmpdir8 } from "os";
|
|
25499
|
-
import { join as
|
|
25979
|
+
import { join as join70, resolve as resolve17 } from "path";
|
|
25500
25980
|
import chalk206 from "chalk";
|
|
25501
25981
|
|
|
25502
25982
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
@@ -25626,17 +26106,17 @@ Write-Output $OutputPath
|
|
|
25626
26106
|
|
|
25627
26107
|
// src/commands/screenshot/index.ts
|
|
25628
26108
|
function buildOutputPath(outputDir, processName) {
|
|
25629
|
-
if (!
|
|
25630
|
-
|
|
26109
|
+
if (!existsSync60(outputDir)) {
|
|
26110
|
+
mkdirSync25(outputDir, { recursive: true });
|
|
25631
26111
|
}
|
|
25632
26112
|
const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
25633
26113
|
return resolve17(outputDir, `${processName}-${timestamp6}.png`);
|
|
25634
26114
|
}
|
|
25635
26115
|
function runPowerShellScript(processName, outputPath) {
|
|
25636
|
-
const scriptPath =
|
|
26116
|
+
const scriptPath = join70(tmpdir8(), `assist-screenshot-${Date.now()}.ps1`);
|
|
25637
26117
|
writeFileSync42(scriptPath, captureWindowPs1, "utf8");
|
|
25638
26118
|
try {
|
|
25639
|
-
|
|
26119
|
+
execSync59(
|
|
25640
26120
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
25641
26121
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf8" }
|
|
25642
26122
|
);
|
|
@@ -25660,11 +26140,11 @@ function screenshot(processName) {
|
|
|
25660
26140
|
}
|
|
25661
26141
|
|
|
25662
26142
|
// src/commands/sessions/daemon/listDaemonPids.ts
|
|
25663
|
-
import { execFileSync as
|
|
26143
|
+
import { execFileSync as execFileSync11 } from "child_process";
|
|
25664
26144
|
function listDaemonPids() {
|
|
25665
26145
|
if (process.platform === "win32") return [];
|
|
25666
26146
|
try {
|
|
25667
|
-
const out =
|
|
26147
|
+
const out = execFileSync11("ps", ["-eo", "pid=,args="], {
|
|
25668
26148
|
encoding: "utf8"
|
|
25669
26149
|
});
|
|
25670
26150
|
return out.split("\n").filter((line) => line.includes("assist") && / daemon run\b/.test(line)).map((line) => Number.parseInt(line.trim(), 10)).filter((pid) => Number.isInteger(pid));
|
|
@@ -25709,163 +26189,62 @@ function applyLine(result, pending, line) {
|
|
|
25709
26189
|
}
|
|
25710
26190
|
}
|
|
25711
26191
|
|
|
25712
|
-
// src/commands/sessions/daemon/reportStolenSocket.ts
|
|
25713
|
-
import { readFileSync as readFileSync48 } from "fs";
|
|
25714
|
-
function reportStolenSocket(socketPid) {
|
|
25715
|
-
if (!socketPid) return;
|
|
25716
|
-
const filePid = readPidFile();
|
|
25717
|
-
if (filePid === void 0 || filePid === socketPid) return;
|
|
25718
|
-
console.error(
|
|
25719
|
-
`Warning: daemon.pid records PID ${filePid} but the socket is owned by PID ${socketPid} (stolen socket)`
|
|
25720
|
-
);
|
|
25721
|
-
}
|
|
25722
|
-
function readPidFile() {
|
|
25723
|
-
try {
|
|
25724
|
-
const pid = Number.parseInt(
|
|
25725
|
-
readFileSync48(daemonPaths.pid, "utf8").trim(),
|
|
25726
|
-
10
|
|
25727
|
-
);
|
|
25728
|
-
return Number.isInteger(pid) ? pid : void 0;
|
|
25729
|
-
} catch {
|
|
25730
|
-
return void 0;
|
|
25731
|
-
}
|
|
25732
|
-
}
|
|
25733
|
-
|
|
25734
|
-
// src/commands/sessions/daemon/daemonStatus.ts
|
|
25735
|
-
async function daemonStatus() {
|
|
25736
|
-
let socket;
|
|
25737
|
-
try {
|
|
25738
|
-
socket = await connectToDaemon();
|
|
25739
|
-
} catch {
|
|
25740
|
-
console.log("Sessions daemon is not running");
|
|
25741
|
-
reportStrays(listDaemonPids());
|
|
25742
|
-
return;
|
|
25743
|
-
}
|
|
25744
|
-
const { pid, sessions } = await queryDaemon(socket);
|
|
25745
|
-
socket.destroy();
|
|
25746
|
-
console.log(`Sessions daemon is running${pid ? ` (PID ${pid})` : ""}`);
|
|
25747
|
-
reportStolenSocket(pid);
|
|
25748
|
-
reportStrays(listDaemonPids().filter((p) => p !== pid));
|
|
25749
|
-
if (sessions.length === 0) {
|
|
25750
|
-
console.log("No sessions");
|
|
25751
|
-
return;
|
|
25752
|
-
}
|
|
25753
|
-
for (const session of sessions) {
|
|
25754
|
-
const restored = session.restored === false ? " (not restored)" : "";
|
|
25755
|
-
console.log(` [${session.status}] ${session.name}${restored}`);
|
|
25756
|
-
}
|
|
25757
|
-
}
|
|
25758
|
-
function reportStrays(pids) {
|
|
25759
|
-
if (pids.length === 0) return;
|
|
25760
|
-
console.error(
|
|
25761
|
-
`Warning: stray daemon process(es) detected: ${pids.join(", ")}`
|
|
25762
|
-
);
|
|
25763
|
-
}
|
|
25764
|
-
|
|
25765
|
-
// src/commands/sessions/daemon/drainDaemon.ts
|
|
25766
|
-
import { createInterface as createInterface6 } from "readline";
|
|
25767
|
-
|
|
25768
|
-
// src/commands/sessions/daemon/daemonLog.ts
|
|
25769
|
-
var RING_CAPACITY = 1e3;
|
|
25770
|
-
var ring = [];
|
|
25771
|
-
var sink;
|
|
25772
|
-
function daemonLog(message2) {
|
|
25773
|
-
emit3(`${(/* @__PURE__ */ new Date()).toISOString()} [${process.pid}] ${message2}`);
|
|
25774
|
-
}
|
|
25775
|
-
function relayDaemonLog(line) {
|
|
25776
|
-
emit3(`[windows] ${line}`);
|
|
25777
|
-
}
|
|
25778
|
-
function emit3(line) {
|
|
25779
|
-
console.log(line);
|
|
25780
|
-
ring.push(line);
|
|
25781
|
-
if (ring.length > RING_CAPACITY) ring.shift();
|
|
25782
|
-
sink?.(line);
|
|
25783
|
-
}
|
|
25784
|
-
function setDaemonLogSink(next3) {
|
|
25785
|
-
sink = next3;
|
|
25786
|
-
}
|
|
25787
|
-
function recentDaemonLogLines() {
|
|
25788
|
-
return [...ring];
|
|
25789
|
-
}
|
|
25790
|
-
|
|
25791
|
-
// src/commands/sessions/daemon/persistedSessionSchema.ts
|
|
25792
|
-
import { z as z6 } from "zod";
|
|
25793
|
-
var persistedSessionSchema = z6.object({
|
|
25794
|
-
name: z6.string(),
|
|
25795
|
-
title: z6.string().optional(),
|
|
25796
|
-
subtitle: z6.string().optional(),
|
|
25797
|
-
commandType: z6.enum(["claude", "run", "assist"]),
|
|
25798
|
-
harness: z6.enum(["claude", "codex", "pi"]).optional(),
|
|
25799
|
-
status: z6.enum(["running", "waiting", "done", "error", "stopped"]).optional(),
|
|
25800
|
-
cwd: z6.string(),
|
|
25801
|
-
startedAt: z6.number(),
|
|
25802
|
-
runningMs: z6.number().optional(),
|
|
25803
|
-
claudeSessionId: z6.string().optional(),
|
|
25804
|
-
initialPrompt: z6.string().optional(),
|
|
25805
|
-
runName: z6.string().optional(),
|
|
25806
|
-
runArgs: z6.array(z6.string()).optional(),
|
|
25807
|
-
assistArgs: z6.array(z6.string()).optional(),
|
|
25808
|
-
activity: activitySchema.optional(),
|
|
25809
|
-
starred: z6.boolean().optional(),
|
|
25810
|
-
undurable: z6.object({ reason: z6.string(), removesTree: z6.boolean().optional() }).optional()
|
|
25811
|
-
});
|
|
25812
|
-
|
|
25813
|
-
// src/commands/sessions/daemon/toPersistedSession.ts
|
|
25814
|
-
function toPersistedSession(session) {
|
|
25815
|
-
return {
|
|
25816
|
-
name: session.name,
|
|
25817
|
-
title: session.title,
|
|
25818
|
-
subtitle: session.subtitle,
|
|
25819
|
-
commandType: session.commandType,
|
|
25820
|
-
harness: session.harness,
|
|
25821
|
-
status: session.status,
|
|
25822
|
-
cwd: session.cwd ?? process.cwd(),
|
|
25823
|
-
startedAt: session.startedAt,
|
|
25824
|
-
runningMs: accumulatedRunningMs(session),
|
|
25825
|
-
claudeSessionId: session.claudeSessionId,
|
|
25826
|
-
initialPrompt: session.initialPrompt,
|
|
25827
|
-
runName: session.runName,
|
|
25828
|
-
runArgs: session.runArgs,
|
|
25829
|
-
assistArgs: session.assistArgs,
|
|
25830
|
-
activity: session.activity,
|
|
25831
|
-
starred: session.starred,
|
|
25832
|
-
undurable: session.undurable
|
|
25833
|
-
};
|
|
25834
|
-
}
|
|
25835
|
-
function accumulatedRunningMs(session) {
|
|
25836
|
-
return session.runningSince != null ? session.runningMs + Date.now() - session.runningSince : session.runningMs;
|
|
25837
|
-
}
|
|
25838
|
-
|
|
25839
|
-
// src/commands/sessions/daemon/loadPersistedSessions.ts
|
|
25840
|
-
var SESSIONS_FILE = "sessions.json";
|
|
25841
|
-
function loadPersistedSessions() {
|
|
25842
|
-
const data = loadJson(SESSIONS_FILE);
|
|
25843
|
-
if (!Array.isArray(data)) return [];
|
|
25844
|
-
return data.flatMap((entry) => {
|
|
25845
|
-
const parsed = persistedSessionSchema.safeParse(entry);
|
|
25846
|
-
return parsed.success ? [parsed.data] : [];
|
|
25847
|
-
});
|
|
26192
|
+
// src/commands/sessions/daemon/reportStolenSocket.ts
|
|
26193
|
+
import { readFileSync as readFileSync48 } from "fs";
|
|
26194
|
+
function reportStolenSocket(socketPid) {
|
|
26195
|
+
if (!socketPid) return;
|
|
26196
|
+
const filePid = readPidFile();
|
|
26197
|
+
if (filePid === void 0 || filePid === socketPid) return;
|
|
26198
|
+
console.error(
|
|
26199
|
+
`Warning: daemon.pid records PID ${filePid} but the socket is owned by PID ${socketPid} (stolen socket)`
|
|
26200
|
+
);
|
|
25848
26201
|
}
|
|
25849
|
-
function
|
|
25850
|
-
|
|
26202
|
+
function readPidFile() {
|
|
26203
|
+
try {
|
|
26204
|
+
const pid = Number.parseInt(
|
|
26205
|
+
readFileSync48(daemonPaths.pid, "utf8").trim(),
|
|
26206
|
+
10
|
|
26207
|
+
);
|
|
26208
|
+
return Number.isInteger(pid) ? pid : void 0;
|
|
26209
|
+
} catch {
|
|
26210
|
+
return void 0;
|
|
26211
|
+
}
|
|
25851
26212
|
}
|
|
25852
|
-
|
|
25853
|
-
|
|
25854
|
-
|
|
25855
|
-
|
|
25856
|
-
|
|
25857
|
-
|
|
26213
|
+
|
|
26214
|
+
// src/commands/sessions/daemon/daemonStatus.ts
|
|
26215
|
+
async function daemonStatus() {
|
|
26216
|
+
let socket;
|
|
26217
|
+
try {
|
|
26218
|
+
socket = await connectToDaemon();
|
|
26219
|
+
} catch {
|
|
26220
|
+
console.log("Sessions daemon is not running");
|
|
26221
|
+
reportStrays(listDaemonPids());
|
|
26222
|
+
return;
|
|
26223
|
+
}
|
|
26224
|
+
const { pid, sessions } = await queryDaemon(socket);
|
|
26225
|
+
socket.destroy();
|
|
26226
|
+
console.log(`Sessions daemon is running${pid ? ` (PID ${pid})` : ""}`);
|
|
26227
|
+
reportStolenSocket(pid);
|
|
26228
|
+
reportStrays(listDaemonPids().filter((p) => p !== pid));
|
|
26229
|
+
if (sessions.length === 0) {
|
|
26230
|
+
console.log("No sessions");
|
|
26231
|
+
return;
|
|
26232
|
+
}
|
|
26233
|
+
for (const session of sessions) {
|
|
26234
|
+
const restored = session.restored === false ? " (not restored)" : "";
|
|
26235
|
+
console.log(` [${session.status}] ${session.name}${restored}`);
|
|
26236
|
+
}
|
|
25858
26237
|
}
|
|
25859
|
-
|
|
25860
|
-
|
|
25861
|
-
|
|
25862
|
-
|
|
25863
|
-
lastPersistSignature = signature;
|
|
25864
|
-
daemonLog(
|
|
25865
|
-
live.length > 0 ? `persisted ${live.length} session(s): ${live.map((s) => s.name).join(", ")}` : "persisted 0 sessions (sessions.json cleared)"
|
|
26238
|
+
function reportStrays(pids) {
|
|
26239
|
+
if (pids.length === 0) return;
|
|
26240
|
+
console.error(
|
|
26241
|
+
`Warning: stray daemon process(es) detected: ${pids.join(", ")}`
|
|
25866
26242
|
);
|
|
25867
26243
|
}
|
|
25868
26244
|
|
|
26245
|
+
// src/commands/sessions/daemon/drainDaemon.ts
|
|
26246
|
+
import { createInterface as createInterface6 } from "readline";
|
|
26247
|
+
|
|
25869
26248
|
// src/commands/sessions/daemon/clearPersistedSessionsOnDrain.ts
|
|
25870
26249
|
function clearPersistedSessionsOnDrain() {
|
|
25871
26250
|
const held = loadPersistedSessions().filter((s) => s.status === "stopped");
|
|
@@ -26213,7 +26592,7 @@ function readDesignSystemPrompt() {
|
|
|
26213
26592
|
import * as pty from "node-pty";
|
|
26214
26593
|
|
|
26215
26594
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
26216
|
-
import { chmodSync, existsSync as
|
|
26595
|
+
import { chmodSync, existsSync as existsSync61, statSync as statSync10 } from "fs";
|
|
26217
26596
|
import { createRequire as createRequire3 } from "module";
|
|
26218
26597
|
import path59 from "path";
|
|
26219
26598
|
var require4 = createRequire3(import.meta.url);
|
|
@@ -26228,7 +26607,7 @@ function ensureSpawnHelperExecutable() {
|
|
|
26228
26607
|
`${process.platform}-${process.arch}`,
|
|
26229
26608
|
"spawn-helper"
|
|
26230
26609
|
);
|
|
26231
|
-
if (!
|
|
26610
|
+
if (!existsSync61(helper)) return;
|
|
26232
26611
|
const mode = statSync10(helper).mode;
|
|
26233
26612
|
if ((mode & 73) === 0) chmodSync(helper, mode | 493);
|
|
26234
26613
|
}
|
|
@@ -26387,7 +26766,8 @@ function otherTreeHolders(sessions, session) {
|
|
|
26387
26766
|
}
|
|
26388
26767
|
|
|
26389
26768
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
26390
|
-
import { existsSync as
|
|
26769
|
+
import { existsSync as existsSync62 } from "fs";
|
|
26770
|
+
import { basename as basename16 } from "path";
|
|
26391
26771
|
|
|
26392
26772
|
// src/commands/sessions/daemon/worktree/removeTree.ts
|
|
26393
26773
|
async function removeTree(clone, worktreePath, force) {
|
|
@@ -26424,63 +26804,9 @@ function reason(error) {
|
|
|
26424
26804
|
return error instanceof Error ? error.message : String(error);
|
|
26425
26805
|
}
|
|
26426
26806
|
|
|
26427
|
-
// src/commands/sessions/daemon/worktree/treeDurability.ts
|
|
26428
|
-
import { existsSync as existsSync58 } from "fs";
|
|
26429
|
-
function treeDurability(state) {
|
|
26430
|
-
if (state.dirty) return { durable: false, reason: "uncommitted changes" };
|
|
26431
|
-
if (!state.push && state.localOnlyCommits)
|
|
26432
|
-
return { durable: false, reason: "unpushed commits" };
|
|
26433
|
-
return { durable: true };
|
|
26434
|
-
}
|
|
26435
|
-
function* durabilityProbes(cwd) {
|
|
26436
|
-
const status3 = yield ["status", "--porcelain"];
|
|
26437
|
-
if (!status3.ok)
|
|
26438
|
-
return { durable: false, reason: `tree state unreadable: ${status3.error}` };
|
|
26439
|
-
const upstream = yield [
|
|
26440
|
-
"rev-parse",
|
|
26441
|
-
"--abbrev-ref",
|
|
26442
|
-
"--symbolic-full-name",
|
|
26443
|
-
"@{upstream}"
|
|
26444
|
-
];
|
|
26445
|
-
let localOnlyCommits;
|
|
26446
|
-
if (upstream.ok && upstream.out) {
|
|
26447
|
-
const ahead = yield ["rev-list", "--count", "@{upstream}..HEAD"];
|
|
26448
|
-
localOnlyCommits = !ahead.ok || Number(ahead.out) > 0;
|
|
26449
|
-
} else {
|
|
26450
|
-
const remoteBranches = yield ["branch", "-r", "--contains", "HEAD"];
|
|
26451
|
-
localOnlyCommits = !remoteBranches.ok || remoteBranches.out === "";
|
|
26452
|
-
}
|
|
26453
|
-
return treeDurability({
|
|
26454
|
-
dirty: status3.out !== "",
|
|
26455
|
-
push: pushOnCommit(cwd),
|
|
26456
|
-
localOnlyCommits
|
|
26457
|
-
});
|
|
26458
|
-
}
|
|
26459
|
-
function pushOnCommit(cwd) {
|
|
26460
|
-
try {
|
|
26461
|
-
return loadConfigFrom(cwd).commit.push;
|
|
26462
|
-
} catch {
|
|
26463
|
-
return false;
|
|
26464
|
-
}
|
|
26465
|
-
}
|
|
26466
|
-
async function checkDurability(cwd) {
|
|
26467
|
-
if (!existsSync58(cwd)) return { durable: true };
|
|
26468
|
-
const probes = durabilityProbes(cwd);
|
|
26469
|
-
let step = probes.next();
|
|
26470
|
-
while (!step.done) step = probes.next(await gitResult(cwd, step.value));
|
|
26471
|
-
return step.value;
|
|
26472
|
-
}
|
|
26473
|
-
function checkDurabilitySync(cwd) {
|
|
26474
|
-
if (!existsSync58(cwd)) return { durable: true };
|
|
26475
|
-
const probes = durabilityProbes(cwd);
|
|
26476
|
-
let step = probes.next();
|
|
26477
|
-
while (!step.done) step = probes.next(gitSyncResult(cwd, step.value));
|
|
26478
|
-
return step.value;
|
|
26479
|
-
}
|
|
26480
|
-
|
|
26481
26807
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
26482
26808
|
async function reapWorktree(worktreePath, force = false) {
|
|
26483
|
-
if (!
|
|
26809
|
+
if (!existsSync62(worktreePath)) {
|
|
26484
26810
|
daemonLog(`worktree ${worktreePath} already gone; skipping reap`);
|
|
26485
26811
|
return false;
|
|
26486
26812
|
}
|
|
@@ -26492,23 +26818,23 @@ async function reapWorktree(worktreePath, force = false) {
|
|
|
26492
26818
|
}
|
|
26493
26819
|
}
|
|
26494
26820
|
const clone = mainWorktree(worktreePath) ?? worktreePath;
|
|
26495
|
-
const branch2 = await gitOrNull(worktreePath, [
|
|
26496
|
-
"symbolic-ref",
|
|
26497
|
-
"--short",
|
|
26498
|
-
"HEAD"
|
|
26499
|
-
]);
|
|
26500
26821
|
if (!await removeTree(clone, worktreePath, force)) return false;
|
|
26501
|
-
|
|
26822
|
+
await deleteWorktreeBranch(clone, basename16(worktreePath));
|
|
26502
26823
|
forgetWorktree(worktreePath);
|
|
26503
26824
|
daemonLog(`worktree ${worktreePath} reaped${force ? " (forced)" : ""}`);
|
|
26504
26825
|
return true;
|
|
26505
26826
|
}
|
|
26506
|
-
async function
|
|
26507
|
-
|
|
26827
|
+
async function deleteWorktreeBranch(clone, branch2) {
|
|
26828
|
+
if (!listLocalBranches(clone).includes(branch2)) return;
|
|
26829
|
+
const current = await gitOrNull2(clone, ["symbolic-ref", "--short", "HEAD"]);
|
|
26508
26830
|
if (branch2 === current) return;
|
|
26509
26831
|
try {
|
|
26510
26832
|
await git2(clone, ["branch", "-D", branch2]);
|
|
26511
|
-
|
|
26833
|
+
daemonLog(`worktree branch ${branch2} deleted from clone ${clone}`);
|
|
26834
|
+
} catch (error) {
|
|
26835
|
+
daemonLog(
|
|
26836
|
+
`worktree branch ${branch2} retained in clone ${clone}: ${error instanceof Error ? error.message : String(error)}`
|
|
26837
|
+
);
|
|
26512
26838
|
}
|
|
26513
26839
|
}
|
|
26514
26840
|
|
|
@@ -26534,21 +26860,6 @@ function dismissSession(sessions, id) {
|
|
|
26534
26860
|
return true;
|
|
26535
26861
|
}
|
|
26536
26862
|
|
|
26537
|
-
// src/commands/sessions/daemon/worktree/worktreeConfigFor.ts
|
|
26538
|
-
var DISABLED = {
|
|
26539
|
-
enabled: false,
|
|
26540
|
-
install: true,
|
|
26541
|
-
commitBeforeManualChecks: false,
|
|
26542
|
-
copy: [".env", "settings.local.json", ".claude/settings.local.json"]
|
|
26543
|
-
};
|
|
26544
|
-
function worktreeConfigFor(cwd) {
|
|
26545
|
-
try {
|
|
26546
|
-
return loadConfigFrom(cwd).worktree ?? DISABLED;
|
|
26547
|
-
} catch {
|
|
26548
|
-
return DISABLED;
|
|
26549
|
-
}
|
|
26550
|
-
}
|
|
26551
|
-
|
|
26552
26863
|
// src/commands/sessions/daemon/worktree/closeGateApplies.ts
|
|
26553
26864
|
function closeGateApplies(sessions, session) {
|
|
26554
26865
|
if (otherTreeHolders(sessions, session).length > 0) return false;
|
|
@@ -26570,12 +26881,12 @@ function setStatus2(session, newStatus) {
|
|
|
26570
26881
|
}
|
|
26571
26882
|
|
|
26572
26883
|
// src/commands/sessions/daemon/worktree/watchGitState.ts
|
|
26573
|
-
import { existsSync as
|
|
26884
|
+
import { existsSync as existsSync63, watch } from "fs";
|
|
26574
26885
|
var DEBOUNCE_MS = 500;
|
|
26575
26886
|
var POLL_MS = 3e4;
|
|
26576
26887
|
function watchGitState(cwd, onChange) {
|
|
26577
26888
|
const common = gitCommonDir(cwd);
|
|
26578
|
-
if (!common || !
|
|
26889
|
+
if (!common || !existsSync63(common)) return void 0;
|
|
26579
26890
|
const watchers = [
|
|
26580
26891
|
watchGitDir(common, onChange),
|
|
26581
26892
|
pollGitState(cwd, onChange)
|
|
@@ -27167,10 +27478,10 @@ function emitSessionOutput(session, clients, data) {
|
|
|
27167
27478
|
}
|
|
27168
27479
|
|
|
27169
27480
|
// src/commands/sessions/daemon/exitReason.ts
|
|
27170
|
-
import { existsSync as
|
|
27481
|
+
import { existsSync as existsSync64 } from "fs";
|
|
27171
27482
|
function exitReason(session, exitCode) {
|
|
27172
27483
|
const base = `process exited with code ${exitCode}`;
|
|
27173
|
-
if (session.cwd && !
|
|
27484
|
+
if (session.cwd && !existsSync64(session.cwd))
|
|
27174
27485
|
return `${base}: working directory ${session.cwd} no longer exists`;
|
|
27175
27486
|
return base;
|
|
27176
27487
|
}
|
|
@@ -27188,8 +27499,8 @@ function handleFailedResume(session, exitCode, onStatusChange) {
|
|
|
27188
27499
|
}
|
|
27189
27500
|
|
|
27190
27501
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
27191
|
-
import { existsSync as
|
|
27192
|
-
import { dirname as
|
|
27502
|
+
import { existsSync as existsSync65, mkdirSync as mkdirSync26, watch as watch2 } from "fs";
|
|
27503
|
+
import { dirname as dirname31 } from "path";
|
|
27193
27504
|
|
|
27194
27505
|
// src/commands/sessions/daemon/applyReviewPause.ts
|
|
27195
27506
|
function applyReviewPause(session, activity2) {
|
|
@@ -27243,9 +27554,9 @@ var DEBOUNCE_MS2 = 50;
|
|
|
27243
27554
|
function watchActivity(session, notify2, onClaudeSessionId) {
|
|
27244
27555
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
27245
27556
|
const path71 = activityPath(session.id);
|
|
27246
|
-
const dir =
|
|
27557
|
+
const dir = dirname31(path71);
|
|
27247
27558
|
try {
|
|
27248
|
-
|
|
27559
|
+
mkdirSync26(dir, { recursive: true });
|
|
27249
27560
|
} catch {
|
|
27250
27561
|
return;
|
|
27251
27562
|
}
|
|
@@ -27269,7 +27580,7 @@ function watchActivity(session, notify2, onClaudeSessionId) {
|
|
|
27269
27580
|
if (timer) clearTimeout(timer);
|
|
27270
27581
|
timer = setTimeout(read, DEBOUNCE_MS2);
|
|
27271
27582
|
});
|
|
27272
|
-
if (
|
|
27583
|
+
if (existsSync65(path71)) read();
|
|
27273
27584
|
}
|
|
27274
27585
|
function refreshActivity(session) {
|
|
27275
27586
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -27929,8 +28240,8 @@ function rearmStoppedSessions(sessions, notify2) {
|
|
|
27929
28240
|
}
|
|
27930
28241
|
|
|
27931
28242
|
// src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
|
|
27932
|
-
import { existsSync as
|
|
27933
|
-
import { basename as
|
|
28243
|
+
import { existsSync as existsSync68 } from "fs";
|
|
28244
|
+
import { basename as basename18 } from "path";
|
|
27934
28245
|
|
|
27935
28246
|
// src/commands/sessions/daemon/worktree/accountedTrees.ts
|
|
27936
28247
|
function accountedTrees(sessions) {
|
|
@@ -27958,71 +28269,6 @@ function detectExistingWorktree(cwd) {
|
|
|
27958
28269
|
return void 0;
|
|
27959
28270
|
}
|
|
27960
28271
|
|
|
27961
|
-
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
27962
|
-
import { execFile as execFile8 } from "child_process";
|
|
27963
|
-
import { copyFileSync, existsSync as existsSync65, mkdirSync as mkdirSync26 } from "fs";
|
|
27964
|
-
import { dirname as dirname30, join as join71 } from "path";
|
|
27965
|
-
|
|
27966
|
-
// src/commands/sessions/daemon/worktree/resolveInstallCommand.ts
|
|
27967
|
-
import { existsSync as existsSync64 } from "fs";
|
|
27968
|
-
import { join as join70 } from "path";
|
|
27969
|
-
function detectInstallCommand(repoRoot) {
|
|
27970
|
-
if (!existsSync64(join70(repoRoot, "package.json"))) return null;
|
|
27971
|
-
if (existsSync64(join70(repoRoot, "pnpm-lock.yaml"))) return "pnpm install";
|
|
27972
|
-
if (existsSync64(join70(repoRoot, "yarn.lock"))) return "yarn install";
|
|
27973
|
-
if (existsSync64(join70(repoRoot, "bun.lockb"))) return "bun install";
|
|
27974
|
-
return "npm install";
|
|
27975
|
-
}
|
|
27976
|
-
function resolveInstallCommand(repoRoot, install) {
|
|
27977
|
-
if (install === false) return null;
|
|
27978
|
-
if (typeof install === "string") return install;
|
|
27979
|
-
return detectInstallCommand(repoRoot);
|
|
27980
|
-
}
|
|
27981
|
-
|
|
27982
|
-
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
27983
|
-
function seedWorktree(worktreePath, clone, onSeeded = () => {
|
|
27984
|
-
}) {
|
|
27985
|
-
const cfg = worktreeConfigFor(clone);
|
|
27986
|
-
copyConfigFiles(worktreePath, clone, cfg.copy);
|
|
27987
|
-
runInstall(worktreePath, clone, cfg.install, onSeeded);
|
|
27988
|
-
}
|
|
27989
|
-
function copyConfigFiles(worktreePath, clone, copy) {
|
|
27990
|
-
for (const rel of copy) {
|
|
27991
|
-
const src = join71(clone, rel);
|
|
27992
|
-
if (!existsSync65(src)) continue;
|
|
27993
|
-
const dest = join71(worktreePath, rel);
|
|
27994
|
-
try {
|
|
27995
|
-
mkdirSync26(dirname30(dest), { recursive: true });
|
|
27996
|
-
copyFileSync(src, dest);
|
|
27997
|
-
daemonLog(`worktree ${worktreePath} seeded ${rel}`);
|
|
27998
|
-
} catch (error) {
|
|
27999
|
-
daemonLog(
|
|
28000
|
-
`worktree ${worktreePath} failed to seed ${rel}: ${message(error)}`
|
|
28001
|
-
);
|
|
28002
|
-
}
|
|
28003
|
-
}
|
|
28004
|
-
}
|
|
28005
|
-
function runInstall(worktreePath, clone, install, onSeeded) {
|
|
28006
|
-
const command = resolveInstallCommand(clone, install);
|
|
28007
|
-
if (!command) {
|
|
28008
|
-
onSeeded();
|
|
28009
|
-
return;
|
|
28010
|
-
}
|
|
28011
|
-
const windows = /^[A-Za-z]:[\\/]/.test(worktreePath);
|
|
28012
|
-
const shell = windows ? "cmd.exe" : process.env.SHELL ?? "bash";
|
|
28013
|
-
const shellArgs = windows ? ["/c", command] : ["-l", "-c", command];
|
|
28014
|
-
daemonLog(`worktree ${worktreePath} installing deps: ${command}`);
|
|
28015
|
-
execFile8(shell, shellArgs, { cwd: worktreePath }, (error) => {
|
|
28016
|
-
daemonLog(
|
|
28017
|
-
error ? `worktree ${worktreePath} install failed: ${error.message}` : `worktree ${worktreePath} install complete`
|
|
28018
|
-
);
|
|
28019
|
-
onSeeded();
|
|
28020
|
-
});
|
|
28021
|
-
}
|
|
28022
|
-
function message(error) {
|
|
28023
|
-
return error instanceof Error ? error.message : String(error);
|
|
28024
|
-
}
|
|
28025
|
-
|
|
28026
28272
|
// src/commands/sessions/daemon/worktree/bindNewWorktree.ts
|
|
28027
28273
|
function bindNewWorktree(session, alloc, notify2, startHeld = () => {
|
|
28028
28274
|
}) {
|
|
@@ -28084,9 +28330,9 @@ function capped(lines) {
|
|
|
28084
28330
|
}
|
|
28085
28331
|
|
|
28086
28332
|
// src/commands/sessions/daemon/worktree/reclaimVanishedWorktrees.ts
|
|
28087
|
-
import { existsSync as
|
|
28333
|
+
import { existsSync as existsSync67 } from "fs";
|
|
28088
28334
|
async function reclaimVanishedWorktrees(clone, paths) {
|
|
28089
|
-
if (!
|
|
28335
|
+
if (!existsSync67(clone)) {
|
|
28090
28336
|
for (const { path: path71 } of paths) forgetWorktree(path71);
|
|
28091
28337
|
daemonLog(
|
|
28092
28338
|
`clone ${clone} is gone; forgot ${paths.length} worktree record(s) it owned`
|
|
@@ -28122,7 +28368,7 @@ async function reclaimBranch(clone, branch2) {
|
|
|
28122
28368
|
}
|
|
28123
28369
|
|
|
28124
28370
|
// src/commands/sessions/daemon/worktree/resurfaceOrphanedWorktree.ts
|
|
28125
|
-
import { basename as
|
|
28371
|
+
import { basename as basename17 } from "path";
|
|
28126
28372
|
function resurfaceOrphanedWorktree(sessions, spawnWith, recovered, notify2) {
|
|
28127
28373
|
const { orphan, reason: reason2, held } = recovered;
|
|
28128
28374
|
let id;
|
|
@@ -28145,7 +28391,7 @@ function orphanedSession(id, recovered) {
|
|
|
28145
28391
|
const { orphan, reason: reason2, held } = recovered;
|
|
28146
28392
|
return {
|
|
28147
28393
|
...sessionBase(id, "stopped"),
|
|
28148
|
-
name: `recovered ${
|
|
28394
|
+
name: `recovered ${basename17(orphan.path)}`,
|
|
28149
28395
|
subtitle: `${held.summary} in ${orphan.path}`,
|
|
28150
28396
|
commandType: "claude",
|
|
28151
28397
|
pty: null,
|
|
@@ -28179,10 +28425,10 @@ async function recoverOrphanedWorktrees(sessions, spawnWith, notify2) {
|
|
|
28179
28425
|
const vanished = /* @__PURE__ */ new Map();
|
|
28180
28426
|
for (const { path: path71, clone } of readWorktreeRegistry()) {
|
|
28181
28427
|
if (accounted.has(path71)) continue;
|
|
28182
|
-
if (!
|
|
28428
|
+
if (!existsSync68(path71)) {
|
|
28183
28429
|
vanished.set(clone, [
|
|
28184
28430
|
...vanished.get(clone) ?? [],
|
|
28185
|
-
{ path: path71, branch:
|
|
28431
|
+
{ path: path71, branch: basename18(path71) }
|
|
28186
28432
|
]);
|
|
28187
28433
|
continue;
|
|
28188
28434
|
}
|
|
@@ -28358,7 +28604,7 @@ function treeSpawnContext(sessions, spawnWith, notify2, clients, onStatusChange)
|
|
|
28358
28604
|
}
|
|
28359
28605
|
|
|
28360
28606
|
// src/commands/sessions/daemon/watchTranscript.ts
|
|
28361
|
-
import { existsSync as
|
|
28607
|
+
import { existsSync as existsSync69, watch as watch3 } from "fs";
|
|
28362
28608
|
|
|
28363
28609
|
// src/commands/sessions/daemon/reconcileTranscriptStatus.ts
|
|
28364
28610
|
async function resolveTranscriptPath(session) {
|
|
@@ -28393,7 +28639,7 @@ function watchTranscript(session, onStatusChange) {
|
|
|
28393
28639
|
if (!session.cwd || !session.claudeSessionId) return;
|
|
28394
28640
|
if (session.watchedTranscriptId === session.claudeSessionId) return;
|
|
28395
28641
|
const dir = projectDirForCwd(session.cwd);
|
|
28396
|
-
if (!
|
|
28642
|
+
if (!existsSync69(dir)) return;
|
|
28397
28643
|
if (session.transcriptWatcher) {
|
|
28398
28644
|
session.transcriptWatcher.close();
|
|
28399
28645
|
session.transcriptWatcher = void 0;
|
|
@@ -28544,13 +28790,13 @@ async function defaultConnect() {
|
|
|
28544
28790
|
}
|
|
28545
28791
|
|
|
28546
28792
|
// src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
|
|
28547
|
-
import { existsSync as
|
|
28793
|
+
import { existsSync as existsSync70, readFileSync as readFileSync50 } from "fs";
|
|
28548
28794
|
import { posix } from "path";
|
|
28549
28795
|
function hasPersistedWindowsSessions() {
|
|
28550
28796
|
const sessionsFile = windowsSessionsFileFromWsl();
|
|
28551
28797
|
if (!sessionsFile) return false;
|
|
28552
28798
|
try {
|
|
28553
|
-
if (!
|
|
28799
|
+
if (!existsSync70(sessionsFile)) return false;
|
|
28554
28800
|
const data = JSON.parse(readFileSync50(sessionsFile, "utf8"));
|
|
28555
28801
|
return Array.isArray(data) && data.length > 0;
|
|
28556
28802
|
} catch (error) {
|
|
@@ -29129,81 +29375,6 @@ function resumeSession(id, sessionId, cwd, name) {
|
|
|
29129
29375
|
};
|
|
29130
29376
|
}
|
|
29131
29377
|
|
|
29132
|
-
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
29133
|
-
import { existsSync as existsSync70 } from "fs";
|
|
29134
|
-
import { basename as basename17, dirname as dirname31 } from "path";
|
|
29135
|
-
|
|
29136
|
-
// src/commands/sessions/daemon/worktree/planAllocation.ts
|
|
29137
|
-
import { basename as basename16, join as join72 } from "path";
|
|
29138
|
-
function planAllocation(clone, boundTreeRoots2) {
|
|
29139
|
-
return boundTreeRoots2.has(clone) ? "spill" : "primary";
|
|
29140
|
-
}
|
|
29141
|
-
function nextWorktreePath(clone, base, isTaken) {
|
|
29142
|
-
const name = basename16(clone);
|
|
29143
|
-
for (let n = 2; n < 1e3; n++) {
|
|
29144
|
-
const candidate = join72(base, `${name}-${n}`);
|
|
29145
|
-
if (!isTaken(candidate)) return candidate;
|
|
29146
|
-
}
|
|
29147
|
-
throw new Error(`no free worktree suffix for ${clone}`);
|
|
29148
|
-
}
|
|
29149
|
-
|
|
29150
|
-
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
29151
|
-
function createWorktree(clone, root, boundTreeRoots2) {
|
|
29152
|
-
const base = root ? expandTilde2(root) : dirname31(clone);
|
|
29153
|
-
const registered = new Set(listWorktreePaths(clone));
|
|
29154
|
-
const branches = new Set(listLocalBranches(clone));
|
|
29155
|
-
const path71 = nextWorktreePath(
|
|
29156
|
-
clone,
|
|
29157
|
-
base,
|
|
29158
|
-
(candidate) => registered.has(candidate) || existsSync70(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename17(candidate))
|
|
29159
|
-
);
|
|
29160
|
-
const trunk = cloneTrunkBranch(clone);
|
|
29161
|
-
gitSync(clone, ["config", "push.default", "upstream"]);
|
|
29162
|
-
gitSync(clone, [
|
|
29163
|
-
"worktree",
|
|
29164
|
-
"add",
|
|
29165
|
-
"--track",
|
|
29166
|
-
"-b",
|
|
29167
|
-
basename17(path71),
|
|
29168
|
-
path71,
|
|
29169
|
-
`origin/${trunk}`
|
|
29170
|
-
]);
|
|
29171
|
-
recordWorktree(path71, clone, getCurrentOrigin(clone));
|
|
29172
|
-
daemonLog(
|
|
29173
|
-
`worktree allocated ${path71} (branch ${basename17(path71)} tracking origin/${trunk}) for clone ${clone}`
|
|
29174
|
-
);
|
|
29175
|
-
return path71;
|
|
29176
|
-
}
|
|
29177
|
-
function cloneTrunkBranch(clone) {
|
|
29178
|
-
const branch2 = gitSyncOrNull(clone, ["symbolic-ref", "--short", "HEAD"]);
|
|
29179
|
-
if (branch2) return branch2;
|
|
29180
|
-
const head = gitSyncOrNull(clone, [
|
|
29181
|
-
"symbolic-ref",
|
|
29182
|
-
"--short",
|
|
29183
|
-
"refs/remotes/origin/HEAD"
|
|
29184
|
-
]);
|
|
29185
|
-
if (head) {
|
|
29186
|
-
const slash = head.indexOf("/");
|
|
29187
|
-
return slash === -1 ? head : head.slice(slash + 1);
|
|
29188
|
-
}
|
|
29189
|
-
return "main";
|
|
29190
|
-
}
|
|
29191
|
-
|
|
29192
|
-
// src/commands/sessions/daemon/worktree/allocateTree.ts
|
|
29193
|
-
function allocateTree(requestedCwd, boundTreeRoots2) {
|
|
29194
|
-
if (!requestedCwd)
|
|
29195
|
-
return { cwd: requestedCwd, kind: "primary", created: false };
|
|
29196
|
-
const repoRoot = findRepoRoot(requestedCwd) ?? requestedCwd;
|
|
29197
|
-
const cfg = worktreeConfigFor(repoRoot);
|
|
29198
|
-
if (!cfg.enabled)
|
|
29199
|
-
return { cwd: requestedCwd, kind: "primary", created: false };
|
|
29200
|
-
const clone = mainWorktree(repoRoot) ?? repoRoot;
|
|
29201
|
-
if (planAllocation(clone, boundTreeRoots2) === "primary")
|
|
29202
|
-
return { cwd: clone, kind: "primary", created: false, clone };
|
|
29203
|
-
const path71 = createWorktree(clone, cfg.root, boundTreeRoots2);
|
|
29204
|
-
return { cwd: path71, kind: "worktree", created: true, clone };
|
|
29205
|
-
}
|
|
29206
|
-
|
|
29207
29378
|
// src/commands/sessions/daemon/worktree/boundTreeRoots.ts
|
|
29208
29379
|
function boundTreeRoots(sessions) {
|
|
29209
29380
|
const roots = /* @__PURE__ */ new Set();
|
|
@@ -29228,9 +29399,17 @@ function holdsTree(session, root) {
|
|
|
29228
29399
|
return !durability.durable;
|
|
29229
29400
|
}
|
|
29230
29401
|
|
|
29402
|
+
// src/commands/sessions/daemon/worktree/isPrCheckoutArgs.ts
|
|
29403
|
+
var CHECKOUT_COMMANDS = /* @__PURE__ */ new Set(["review", "review-pr-comments"]);
|
|
29404
|
+
function isPrCheckoutArgs(args) {
|
|
29405
|
+
const [command, ...rest] = args;
|
|
29406
|
+
if (!command || !CHECKOUT_COMMANDS.has(command)) return false;
|
|
29407
|
+
return rest.some((arg) => /^[1-9]\d*$/.test(arg));
|
|
29408
|
+
}
|
|
29409
|
+
|
|
29231
29410
|
// src/commands/sessions/daemon/worktree/spawnInTree.ts
|
|
29232
|
-
function allocateAndBind(ctx, cwd, create) {
|
|
29233
|
-
const alloc = allocateTree(cwd, boundTreeRoots(ctx.sessions));
|
|
29411
|
+
function allocateAndBind(ctx, cwd, create, options2 = {}) {
|
|
29412
|
+
const alloc = allocateTree(cwd, boundTreeRoots(ctx.sessions), options2);
|
|
29234
29413
|
const needsSeeding = alloc.kind === "worktree" && alloc.created === true;
|
|
29235
29414
|
const id = ctx.spawnWith((sid) => create(sid, alloc.cwd, needsSeeding));
|
|
29236
29415
|
bindNewWorktree(ctx.sessions.get(id), alloc, ctx.notify, ctx.startHeld);
|
|
@@ -29247,7 +29426,8 @@ function spawnAssistInTree(ctx, assistArgs, cwd, meta) {
|
|
|
29247
29426
|
return allocateAndBind(
|
|
29248
29427
|
ctx,
|
|
29249
29428
|
cwd,
|
|
29250
|
-
(sid, resolvedCwd, holdUntilSeeded) => createAssistSession(sid, assistArgs, resolvedCwd, meta, holdUntilSeeded)
|
|
29429
|
+
(sid, resolvedCwd, holdUntilSeeded) => createAssistSession(sid, assistArgs, resolvedCwd, meta, holdUntilSeeded),
|
|
29430
|
+
{ forCheckout: isPrCheckoutArgs(assistArgs) }
|
|
29251
29431
|
);
|
|
29252
29432
|
}
|
|
29253
29433
|
function resumeInTree(ctx, sessionId, cwd, name) {
|
|
@@ -29955,11 +30135,21 @@ var sessionsConfigHelp = [
|
|
|
29955
30135
|
setter: "assist config set sessions.windowsVersionCheck block",
|
|
29956
30136
|
note: "Windows daemon version mismatch handling: block | warn | off"
|
|
29957
30137
|
},
|
|
30138
|
+
{
|
|
30139
|
+
key: "sessions.includeCommittedChanges",
|
|
30140
|
+
setter: "assist config set sessions.includeCommittedChanges true -g",
|
|
30141
|
+
note: "session card counts and /diff span the whole branch (merge-base with the default branch) instead of just uncommitted work (default off)"
|
|
30142
|
+
},
|
|
29958
30143
|
{
|
|
29959
30144
|
key: "worktree.enabled",
|
|
29960
30145
|
setter: "assist config set worktree.enabled true -g --repo",
|
|
29961
30146
|
note: "opt in per repo: spill concurrent sessions into adjacent <clone>-N worktrees (default off)"
|
|
29962
30147
|
},
|
|
30148
|
+
{
|
|
30149
|
+
key: "worktree.trunk",
|
|
30150
|
+
setter: "assist config set worktree.trunk true -g --repo",
|
|
30151
|
+
note: "trunk-based: a spilled worktree lands on the mainline (default off: it starts off the remote default with no mainline tracking, so the session raises its own branch and PR)"
|
|
30152
|
+
},
|
|
29963
30153
|
{
|
|
29964
30154
|
key: "worktree.root",
|
|
29965
30155
|
setter: "assist config set worktree.root ~/git -g --repo",
|
|
@@ -30000,7 +30190,7 @@ function summaryPathFor(jsonlPath2) {
|
|
|
30000
30190
|
}
|
|
30001
30191
|
|
|
30002
30192
|
// src/commands/sessions/summarise/summariseSession.ts
|
|
30003
|
-
import { execFileSync as
|
|
30193
|
+
import { execFileSync as execFileSync12 } from "child_process";
|
|
30004
30194
|
|
|
30005
30195
|
// src/commands/sessions/summarise/extractFirstUserMessage.ts
|
|
30006
30196
|
function extractFirstUserMessage(filePath) {
|
|
@@ -30024,7 +30214,7 @@ function summariseSession(jsonlPath2) {
|
|
|
30024
30214
|
}
|
|
30025
30215
|
const prompt = buildPrompt3(firstMessage, backlogIds);
|
|
30026
30216
|
try {
|
|
30027
|
-
const output =
|
|
30217
|
+
const output = execFileSync12("claude", ["-p", "--model", "haiku", prompt], {
|
|
30028
30218
|
encoding: "utf8",
|
|
30029
30219
|
timeout: 3e4,
|
|
30030
30220
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -30586,7 +30776,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
30586
30776
|
}
|
|
30587
30777
|
|
|
30588
30778
|
// src/commands/update.ts
|
|
30589
|
-
import { execSync as
|
|
30779
|
+
import { execSync as execSync60 } from "child_process";
|
|
30590
30780
|
import * as path70 from "path";
|
|
30591
30781
|
|
|
30592
30782
|
// src/commands/restartDaemonAfterUpdate.ts
|
|
@@ -30610,7 +30800,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
30610
30800
|
if (resolved.split(path70.sep).includes("node_modules")) {
|
|
30611
30801
|
return true;
|
|
30612
30802
|
}
|
|
30613
|
-
const globalPrefix =
|
|
30803
|
+
const globalPrefix = execSync60("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
30614
30804
|
return resolved.toLowerCase().startsWith(path70.resolve(globalPrefix).toLowerCase());
|
|
30615
30805
|
} catch {
|
|
30616
30806
|
return false;
|
|
@@ -30621,18 +30811,18 @@ async function update2() {
|
|
|
30621
30811
|
console.log(`Assist is installed at: ${installDir}`);
|
|
30622
30812
|
if (isGitRepo(installDir)) {
|
|
30623
30813
|
console.log("Detected git repo installation, pulling latest...");
|
|
30624
|
-
|
|
30814
|
+
execSync60("git pull", { cwd: installDir, stdio: "inherit" });
|
|
30625
30815
|
console.log("Installing dependencies...");
|
|
30626
|
-
|
|
30816
|
+
execSync60("npm i", { cwd: installDir, stdio: "inherit" });
|
|
30627
30817
|
console.log("Building...");
|
|
30628
|
-
|
|
30818
|
+
execSync60("npm run build", { cwd: installDir, stdio: "inherit" });
|
|
30629
30819
|
console.log("Syncing commands...");
|
|
30630
|
-
|
|
30820
|
+
execSync60("assist sync", { stdio: "inherit" });
|
|
30631
30821
|
} else if (isGlobalNpmInstall(installDir)) {
|
|
30632
30822
|
console.log("Detected global npm installation, updating...");
|
|
30633
|
-
|
|
30823
|
+
execSync60("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
|
|
30634
30824
|
console.log("Syncing commands...");
|
|
30635
|
-
|
|
30825
|
+
execSync60("assist sync", { stdio: "inherit" });
|
|
30636
30826
|
} else {
|
|
30637
30827
|
console.error(
|
|
30638
30828
|
"Could not determine installation method. Expected a git repo or global npm install."
|